sudo displays typed password in bash script

3

I have a bash script that uses sudo a few times. There's a couple of strange points about it though.

  1. It asks me for my password a few seconds after I've already entered it for a previous command.
  2. The second time I enter my password, it's echoed to the display.

Here's the relevant bits of the script.

sudo service apache2 stop
drush sql-dump --root="$SITE_DIR" --structure-tables-key=svn --ordered-dump | grep -iv 'dump completed on' | sudo tee "$DB_DIR/${SITE_NAME}.sql" > /dev/null
sudo svn diff "$DB_DIR" | less
sudo svn commit -m "$MESSAGE" "$DB_DIR"
sudo service apache2 start

The first password is to stop apache, and it works as expected. As mentioned, the sudo tee doesn't 'remember' that I have elevated privileges, asks for the password again, and echoes it to the screen. Given that tee is all about echoing to screen, I've played around a little with simple scripts which have | sudo tee, and they all work as expected.

Edit: I looked into the drush command itself, and it's a bash file that calls PHP using exec. This sounds like it might have potential - any ideas? Here's the line from drush.

exec php $SCRIPT_PATH --php=`which php` "$@"

Edit2: Was looking up something to do with Ruby scripts and came across this post about elevated privileges in scripts from serverfault.

Andy

Posted 2010-06-18T10:19:40.757

Reputation: 2 959

I can't imagine drush is too smart (Drupal Shell). Put echos in your script so you can see where in the script you get asked. – Jeremy L – 2010-06-18T10:51:42.867

I'm getting asked after the service stop, but before the diff, so it's got to be the sudo tee... is that what you meant? – Andy – 2010-06-18T11:45:55.683

Answers

8

May I suggest another solution? Stop using sudo in bash scripts, instead run the whole script with elevated rights.

You can easily check if the script is run as root or not:

if [[ $(/usr/bin/id -u) -ne 0 ]]; then
    echo "$0 must be run as root"
    exit 1
fi

Taken from this SO question.

Bobby

Posted 2010-06-18T10:19:40.757

Reputation: 8 534

I've only shown part of the script - there are other bits that don't need root privilege, and I'd prefer not to grant it to them. I could factor out the commands above into a separate script and sudo the whole script, but it seems a bit 'over-engineery' to me. – Andy – 2010-06-18T11:42:43.040

1There's a difference between "over-engineery" and "works" ;) The script in the OP read to me as bad form, in particular because the separate sudo invocations are counting on a side effect (temporary storage of authentication) which shouldn't be counted upon. A script less all the sudo calls could be run by root or by crond, which can't be said of the OP script. – msw – 2010-06-18T11:45:01.303

:) yeah, it'll work, but it seems to me that I'm scotch-taping the issue. If I don't understand why it's happening this time, I'm sure it'll crop up again. If I factor out some code I prefer it to be because I consider it a discrete reusable chunk - not because it's the only way I can get it to work though I don't know why;) – Andy – 2010-06-18T11:49:05.957

@msw The script doesn't 'count on' storing the authentication. It will still work fine if it isn't stored. I'm just bemused as to why in this case it isn't stored. Sorry, don't understand the last sentence - could you elaborate please? – Andy – 2010-06-18T11:58:19.490

That should be if /usr/bin/id -u > /dev/null 2>&1 - no need for the square brackets and -ne 0 – Paused until further notice. – 2010-06-18T14:32:24.103

@Dennis: No it shouldn't. id always returns 0 as its exit status. And what Bobby is checking is id's output (the UID), which is 0 for root. – user1686 – 2010-06-18T19:43:17.340

@grawity: Oops! – Paused until further notice. – 2010-06-18T19:58:02.940

0

Can you recheck your sudo version?
I see this in the current sudo manual,

-A

Normally, if sudo requires a password, it will read it from the current terminal. If the -A (askpass) option is specified, a (possibly graphical) helper program is executed to read the user's password and output the password to the standard output. If the SUDO_ASKPASS environment variable is set, it specifies the path to the helper program. Otherwise, the value specified by the askpass option in sudoers(5) is used.

and,

SUDO_ASKPASS

Specifies the path to a helper program used to read the password if no terminal is available or if the -A option is specified.

Can't recall having read or used this before...

nik

Posted 2010-06-18T10:19:40.757

Reputation: 50 788

v 1.7.2p1 It's strange that it should have a problem only the second time, not the first, third, etc. – Andy – 2010-06-18T11:45:03.097

0

From man 8 sudo examples:

To make a usage listing of the directories in the /home partition. Note that this runs the commands in a sub-shell to make the cd and file redirection work.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"

And I don't know what "tests" you ran with tee, but the simple case:

$ sudo id | sudo tee /tmp/junk

Prompts for two passwords at once and then they both fight over the input queue so neither one accepts the password (and they screw up the stty line discipline so the typed characters are echoed).

Update: Oh, you wanted to know why the sudo doesn't apply to the pipeline? Because the shell has to fork off the subprocesses of a pipeline each which inherits the context of the parent shell. As far as the shell is concerned, sudo is just a command and it runs its arguments in a context of elevated privilege which does not "flow" down the pipe. As a set of commands the pipeline can be read as

drush sql-dump > pipe ;  ( grep < pipe  ;  ( sudo tee file < pipe ) )

which is a more accurate model of what is happening.

msw

Posted 2010-06-18T10:19:40.757

Reputation: 3 287

For me your second example shows the fighting for input, but it doesn't echo the pass. Note I never have a command quite like that one; one example I used was sudo service ; ls | sudo tee output - works fine. – Andy – 2010-06-18T11:55:55.177

I understand why sudo doesn't apply to the pipeline, which is why I'm using sudo tee instead of normal redirection. What I don't understand is why it doesn't remember the entered password, and why it echoes the characters to screen. – Andy – 2010-06-18T12:11:20.520

0

You can also always look at something simple like creating a fifo or 'pipe' for output you want to read

`mkfifo -m 600 /path/to/fifo` 

man mkfifo for more info. Your code will now read something like:

sudo service apache2 stop 
#this will be visible and you can type in your password
stty -echo
# this will now remove echoing of characters to the screen
drush sql-dump --root="$SITE_DIR" --structure-tables-key=svn --ordered-dump | grep -iv 'dump completed on' | sudo tee "$DB_DIR/${SITE_NAME}.sql" > /dev/null
# as you are again looking for visible output, i would use the fifo here
sudo svn diff "$DB_DIR" \> /path/to/fifo &
sleep 4 # or longer
tail /path/to/fifo
sudo svn commit -m "$MESSAGE" "$DB_DIR"
sudo service apache2 start
stty echo

UberJim

Posted 2010-06-18T10:19:40.757

Reputation: 11