如何在Bash中以另一个用户的身份执行一组命令?


69

这里已经存在一些有关以其他用户身份运行命令的现有问题。但是,问题和答案只针对单个命令,而不是一长串命令。

例如,考虑以下脚本:

#!/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'

这里有几点要注意的要点:

  • 最后三个命令必须使用su或作为其他用户运行sudo。在该示例中,有三个命令,但假设还有更多命令...

  • 命令本身使用单引号和双引号。

上面的第二点禁止使用以下语法:

su somebody -c "command"

...因为命令本身包含引号。

将命令“分组”并在另一个用户帐户下运行它们的正确方法是什么?


1
Unix stackexchange有运气吗?
icedwater

Answers:


159

尝试这个:

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

<<介绍一个here-doc。下一个标记是定界符,直到定界符开始的一行中的所有内容都作为命令的标准输入。将定界符放在单引号中可防止here-doc中的变量替换。


2
如果遇到“ su:必须从终端运行”,请尝试sudo su somebody <<'EOF'
波尔2014年

9
如果您使用<<EOF而不是<<'EOF',则将扩展here-doc中的变量。
Barmar 2014年

7
这对某些用户很有用:如果您需要命令在用户的完整环境中实际运行,就像他们已经登录一样,例如,该路径可能包含不同的路径。在“某人”之前添加连字符,例如:su-某人...
JJC 2015年

3
关闭EOF之前,请确保没有空格(例如,从缩进的“ if”语句调用时)。否则会引发错误-请参阅tldp.org/LDP/abs/html/here-docs.html
PetrÚjezdský16年

1
@PatrizioBekerle我在终端中以交互方式进行操作,但是我也只是在脚本中进行了尝试,所以它们都可以工作。
Barmar

7

我对bash-foo不太满意,因此肯定会有一种更优雅的方式,但是我过去通过使用多个脚本和一个“驱动程序”来解决此问题。

例如

司机

#!/bin/bash
set -e

su root script1
su somebody script2

脚本1

#!/bin/bash
set -e

root_command -p param1  # run as root

脚本2

#!/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'

0

该脚本检查运行脚本的当前用户是否为所需用户。如果不是,则用所需的用户重新执行脚本。

#!/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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.