8

Let's say, I have the following bash script:

#!/bin/bash
sudo command1
command2
sudo command3

I don't want to run command2 as root, so I won't run the script itself with sudo. Therefore, as soon as I execute the script, sudo command1 asks for my password. Unfortunately, command2 takes about 2 hours to complete. So the sudo credentials timestamp timed out and when the script reaches sudo command3, I'm prompted for the password again.

I don't want to permanently disable the sudo credentials timestamp timeout altogether as described in https://superuser.com/a/149740 for example. I just want to disable the timeout temporarily, effectively keep the credentials for this one bash session until it ends.

finefoot
  • 3,060
  • 1
    Kick off a background job to run sudo -v every 5 minutes (e.g. watch -n 600 sudo -v &), for the duration of the command2 execution. – steve Apr 19 '19 at 16:35
  • 1
    @steve that's a good idea; you'd have to ensure that sudoers was configured with !requiretty, as it wouldn't have a tty in the background – Jeff Schaller Apr 19 '19 at 16:38

4 Answers4

5

I think your best bet is a (backgrounded) busy-wait loop that refreshes the sudo timestamp, which you then kill when you no longer need sudo privileges. Here's a sample script; it runs sleep 6 instead of your two-hour command2 and runs visible /bin/echo commands instead of command1 and command2:

#!/bin/sh
sudo /bin/echo command 1
while :; do sudo -v; sleep 1; done &
infiloop=$!
sleep 6
sudo /bin/echo command 3
kill "$infiloop"

For your actual script, I would recommend a looser loop:

#!/bin/sh
sudo command1
while :; do sudo -v; sleep 59; done &
infiloop=$!
command2
sudo command3
kill "$infiloop"

Adjust the sleep 59 to taste, depending on the existing timestamp_timeout setting in sudoers; I chose 59 just to demonstrate a choice you could make if the timestamp timeout was 60 seconds.

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
4

I must be missing something here, because the solution seems very obvious to me.

I don't want to run command2 as root, so I won't run the script itself with sudo.

But you can run the whole script with sudo without running command 2 as root if you change the script:

#!/bin/bash
command1
sudo -u ${SUDO_USER:-$USER} command2
command3
EmmaV
  • 4,067
  • Why would I test it without sudo? You didn't say you needed to run it both with and without sudo. – EmmaV Oct 06 '19 at 15:57
1

By refreshing credentials in the background:

#!/bin/bash

configurePermissions () { sudo -v refreshPermissions "$$" & }

refreshPermissions () { local pid="${1}"

while kill -0 "${pid}" 2> /dev/null; do
    sudo -v
    sleep 10
done

}

configurePermissions

0

Well, it would be possible to combine How can I make sudo forget the password automatically after one command? and What's the purpose of using `sudo -S` explicitly?

  1. Read password from user, save it in environment variable
  2. Run sudo with -k flag to ignore credentials so it will always prompt for the password
  3. Pass the password via stdin into sudo with flag -S
  4. Remove password environment variable

It might be useful for certain situations, but I'm not sure if it's a good idea to store the user's password in an environment variable.

finefoot
  • 3,060