我编写了一个脚本,它接受一个字符串作为参数,该字符串是用户名和项目的串联。该脚本应该切换(su)到用户名,cd到基于项目字符串的特定目录。
我基本上想做:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
问题在于,一旦我做了......它只是在那里等待。这是有道理的,因为执行流程已经转移到用户。一旦我退出,其余的事情就会执行,但它不能按预期工作。
我将su添加到svn命令,但命令失败(即它没有更新所需目录中的svn)。
如何编写允许用户切换用户并调用svn(以及其他内容)的脚本?
答案 0 :(得分:81)
诀窍是使用“sudo”命令而不是“su”
您可能需要添加此
username1 ALL=(username2) NOPASSWD: /path/to/svn
到你的/ etc / sudoers文件
并将您的脚本更改为:
sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
其中username2是您要运行SVN命令的用户,而username1是运行脚本的用户。
如果您需要多个用户来运行此脚本,请使用%groupname
而不是username1
答案 1 :(得分:79)
更简单:使用sudo
运行shell并使用heredoc来提供命令。
#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
答案 2 :(得分:52)
使用以下脚本在其他用户下执行其余部分或部分脚本:
#!/bin/sh
id
exec sudo -u transmission /bin/sh - << eof
id
eof
答案 3 :(得分:41)
您需要将所有不同的用户命令作为自己的脚本执行。如果它只是一个或几个命令,那么内联应该可行。如果它有很多命令,那么最好将它们移动到自己的文件中。
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
答案 4 :(得分:32)
这是另一种方法,在我的情况下更方便(我只想删除root权限并从受限用户执行我的其余脚本):您可以使脚本从正确的用户重新启动。我们假设它最初以root身份运行。然后它会是这样的:
#!/bin/bash
if [ $UID -eq 0 ]; then
user=$1
dir=$2
shift 2 # if you need some other parameters
cd "$dir"
exec su "$user" "$0" -- "$@"
# nothing will be executed beyond that line,
# because exec replaces running process with the new one
fi
echo "This will be run from user $UID"
...
答案 5 :(得分:7)
使用sudo
代替
编辑:正如道格拉斯指出的那样,您不能在cd
中使用sudo
,因为它不是外部命令。您必须在子shell中运行命令才能使cd
正常工作。
sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
<击> 撞击>
<击>sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update
击> <击> 撞击>
可能会要求您输入该用户的密码,但只能输入一次。
答案 6 :(得分:6)
无法在shell脚本中更改用户。使用其他答案中描述的sudo的变通办法可能是您最好的选择。
如果你足够疯狂以root身份运行perl脚本,你可以使用保存真实/有效uid / gid的$< $( $> $)
变量来执行此操作,例如:
#!/usr/bin/perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
答案 7 :(得分:2)
这对我有用
我从“创业公司”中拆分了我的“配置”。
# Configure everything else ready to run
config.vm.provision :shell, path: "provision.sh"
config.vm.provision :shell, path: "start_env.sh", run: "always"
然后在我的start_env.sh
#!/usr/bin/env bash
echo "Starting Server Env"
#java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar &
#(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &")
cd /vagrant_projects/myproj
nohup grunt connect:server:keepalive 0<&- &>/dev/null &
nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null &
答案 8 :(得分:-2)
受到来自@ MarSoft的想法的启发,但我改变了以下几行:
USERNAME='desireduser'
COMMAND=$0
COMMANDARGS="$(printf " %q" "${@}")"
if [ $(whoami) != "$USERNAME" ]; then
exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS"
exit
fi
我使用sudo
来减少密码执行时的密码。如果要为用户输入密码,请删除sudo
。如果您不需要环境变量,请从sudo中删除-E
。
/usr/bin/bash -l
确保为初始化环境执行profile.d
脚本。