LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   How do I perform commands in a bash script as a different user? (https://www.linuxquestions.org/questions/programming-9/how-do-i-perform-commands-in-a-bash-script-as-a-different-user-949461/)

theonislair 06-10-2012 12:02 AM

How do I perform commands in a bash script as a different user?
 
Hi. This is sort of a follow-up (but entirely new) question to one I posted yesterday.

Code:

#!/bin/bash
[... some checks ...]
sudo su - $1

HOMEURL="define(\'WP_HOME\'\, \'http://$HOSTNAME/~$USER\');"
SITEURL="define(\'WP_SITEURL\'\, \'http://$HOSTNAME/~$USER\');"
PUBHTML="$HOME/public_html"

cp $PUBHTML/wp-config.php $PUBHTML/wp-config.php.notmp

sed "/DB_COLLATE/ a\
$HOMEURL\n\
$SITEURL\
" $PUBHTML/wp-config.php > $PUBHTML/wp-config.php.tmp

cat $PUBHTML/wp-config.php.tmp > $PUBHTML/wp-config.php
rm $PUBHTML/wp-config.php.tmp

The code above works (thanks to this and pixellany), but not to the extent I want it to. The script has one possible argument (a username) that I'd like the shell to switch to, perform the cp, sed, cat and rm then return back to the original shell. $HOME and $USER need to return as the *argument* username's homedir and username, not the user performing it. I've tried double quotes (escaping the other double quotes with \), back ticks and single quotes (which are already escaped as literal).. what can I do to make this work? When the

Code:

sudo su - $1
is performed, the rest of the commands aren't performed as the user. Considering security I can't pass it off as a secondary script that the user performs, it all needs to be within one script that a (near) super user performs.
Code:

su -c "command" $1
won't work in this case either, unfortunately.

jlinkels 06-10-2012 12:52 AM

Code:

sudo -u otheruser /path/to/command parm1 parm2
jlinkels

theonislair 06-10-2012 01:20 AM

While I appreciate the gesture; that didn't work.

jlinkels 06-10-2012 01:35 AM

Quote:

Originally Posted by theonislair (Post 4699837)
that didn't work.

That doesn't say anything. How it doesn't work?

jlinkels

David the H. 06-10-2012 10:47 AM

You do realize that you also have to make sure that sudo is configured to allow that user to run that command, right?

Nominal Animal 06-10-2012 01:10 PM

Quote:

Originally Posted by theonislair (Post 4699809)
I'd like the shell to switch to, perform the cp, sed, cat and rm then return back to the original shell. $HOME and $USER need to return as the *argument* username's homedir and username, not the user performing it.

Code:

#!/bin/bash
if [ $# -lt 1 ] || [ "$*" = "-h" ] || [ "$*" = "--help" ]; then
    exec >&2
    echo ""
    echo "Usage: $0 -h | --help"
    echo "      $0 USER"
    echo ""
    exit 0
fi

User="$1"
shift 1
if [ -z "$User" ]; then
    echo "No user specified." >&2
    exit 1
fi
if ! id -u "$User" &>/dev/null ; then
    echo "$User: No such user." >&2
    exit 1
fi

Home="$(getent passwd "$User" | cut -d : -f 6)" || exit $?
if [ -z "$Home" ]; then
    echo "$User: This user has no known home directory." >&2
    exit 1
fi
if [ ! -d "$Home" ]; then
    echo "$User: Cannot locate user home directory ($Home)." >&2
    exit 1
fi

# Edit as $User:
sudo -u "$User" -- sed -e '/DB_COLLATE/ a\define(\x27WP_HOME\x27\, \x27http://'"$HOSTNAME/~$User"'\x27);\ndefine(\x27WP_SITEURL\x27\, \x27http://'"$HOSTNAME/~$User"'\x27);' -i "$Home/public_html/wp-config.php" || exit $?

# Back as original user ...

The sed expression is a bit messy; you might wish to test it first. Drop the -i option to have it only output the result instead of modifying the specified file.

If you need to do a more complex edit, I recommend putting that part in a separate scriptlet. You can do
Code:

sudo -u "$User" -- bash -c '
    ... scriptlet ...
' || exit $?

but the quoting inside is pretty hairy. Note that if you want the helper script to be non-executable, you can always do
Code:

sudo -u "$User" -- bash -c "export USER='$User'; export HOME='$Home'; . /path/to/helper" || exit $?
The || exit $? bits I've liberally sprinkled here and there means "but if that fails, abort the script".

Note the getent passwd "$User" | cut -d : -f 6 expression: I believe it is the most portable easy way to find the user home directory. It should work even when using a remote user database. It does work fine on all machines I tested, even on SunOS 5.10. You could always rely on Bash tilde expansion, but applying the expansion from a string is a bit difficult to do reliably; all the ways I could think of just now would involve eval.


All times are GMT -5. The time now is 12:10 AM.