سؤال

There are already some existing questions asked here about running commands as another user. However, the question and answers focus on a single command instead of a long group of commands.

For example, consider the following script:

#!/bin/bash
set -e

root_command -p param1  # run as root

# these commands must be run as another user
command1 -p 'parameter with "quotes" inline'
command2 -p 'parameter with "quotes" inline'
command3 -p 'parameter with "quotes" inline'

There are a couple of important points to note here:

  • The final three commands must be run as another user using su or sudo. In the example there were three commands, but suppose that there were many more...

  • The commands themselves make use of single and double quotes.

The second point above prevents the use of the following syntax:

su somebody -c "command"

...since the commands themselves contain quotes.

What is the proper way to "group" the commands and run them under another user account?

هل كانت مفيدة؟

المحلول

Try this:

su somebody <<'EOF'
command1 -p 'parameter with "quotes" inline'
command2 -p 'parameter with "quotes" inline'
command3 -p 'parameter with "quotes" inline'
EOF

<< introduces a here-doc. The next token is the delimiter, and everything up to a line beginning with the delimiter is fed as standard input to the command. Putting the delimiter in single quotes prevents variable substitution within the here-doc.

نصائح أخرى

I'm not that great with Bash-foo, so there is bound to be a more elegant way, but I've approached this problem in the past by using multiple scripts and a "driver".

E.g.,

Driver

#!/bin/bash
set -e

su root script1
su somebody script2

Script1

#!/bin/bash
set -e

root_command -p param1  # Run as root

Script2

#!/bin/bash
set -e

# These commands must be run as another user
command1 -p 'parameter with "quotes" inline'
command2 -p 'parameter with "quotes" inline'
command3 -p 'parameter with "quotes" inline'

This script checks if the current user running the script is the desired user. If not, then the script is re-executed with the desired user.

#!/usr/bin/env bash

TOKEN_USER_X=TOKEN_USER_X
USER_X=peter # other user!

SCRIPT_PATH=$(readlink -f "$BASH_SOURCE")

if [[ "$@" != "$TOKEN_USER_X" ]]; then

    ###### RUN THIS PART AS the user who started the script

    echo "This script is $SCRIPT_PATH"

    echo -n "Current user: "
    echo $USER

    read -p "insert: "
    echo "got $REPLY"

    su - $USER_X -c "$SCRIPT_PATH $TOKEN_USER_X" # execute code below after else (marked #TOKEN_USER_X)

else
    #TOKEN_USER_X -- come here only if script received one parameter TOKEN_USER_X

    ###### RUN THIS PART AS USER peter

    echo
    echo "Now this script is $SCRIPT_PATH"

    echo -n "Current user: "
    echo $USER

    read -p "insert: "
    echo "got $REPLY"

    exit 0
fi

echo
echo "Back to initial user..."
echo -n "Current user: "
echo $USER
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top