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.

2
  • 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. Commented Jun 18, 2010 at 10:51
  • 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? Commented Jun 18, 2010 at 11:45

4 Answers 4

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.

7
  • 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. Commented Jun 18, 2010 at 11:42
  • 1
    There'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. Commented Jun 18, 2010 at 11:45
  • :) 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;) Commented Jun 18, 2010 at 11:49
  • @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? Commented Jun 18, 2010 at 11:58
  • That should be if /usr/bin/id -u > /dev/null 2>&1 - no need for the square brackets and -ne 0 Commented Jun 18, 2010 at 14:32
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...

1
  • v 1.7.2p1 It's strange that it should have a problem only the second time, not the first, third, etc. Commented Jun 18, 2010 at 11:45
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.

2
  • 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. Commented Jun 18, 2010 at 11:55
  • 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. Commented Jun 18, 2010 at 12:11
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 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.