157

我编写了一个脚本,该脚本将一个字符串作为参数,该字符串是用户名和项目的串联。该脚本应该切换 (su) 到用户名,cd 到基于项目字符串的特定目录。

我基本上想做:

su $USERNAME;  
cd /home/$USERNAME/$PROJECT;  
svn update;  

问题是,一旦我做了一个 su... 它就在那里等着。这是有道理的,因为执行流程已经转移到切换到用户。一旦我退出,其余的事情就会执行,但它不能按预期工作。

我在 svn 命令前添加了 su,但命令失败(即它没有更新所需目录中的 svn)。

如何编写允许用户切换用户和调用 svn(除其他外)的脚本?

4

9 回答 9

140

简单得多:用于sudo运行 shell 并使用heredoc为其提供命令。

#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami

(最初在 SuperUser 上回答)

于 2014-07-11T11:35:09.807 回答
101

诀窍是使用“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 是运行脚本的用户。

如果您需要多个用户来运行此脚本,请使用 a%groupname而不是 username1

于 2010-01-01T09:42:07.777 回答
63

您需要将所有不同用户的命令作为他们自己的脚本执行。如果它只是一个或几个命令,那么内联应该可以工作。如果有很多命令,那么最好将它们移动到自己的文件中。

su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME" 
于 2010-01-01T09:53:34.177 回答
61

这是另一种方法,在我的情况下更方便(我只是想放弃 root 权限并从受限用户执行我的脚本的其余部分):您可以让脚本从正确的用户重新启动。这种方法比使用sudosu -c使用“嵌套脚本”更具可读性。假设它最初以 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"
...
于 2015-04-30T13:36:57.790 回答
59

使用如下脚本在另一个用户下执行其余或部分脚本:

#!/bin/sh

id

exec sudo -u transmission /bin/sh - << eof

id

eof
于 2012-01-25T06:37:57.047 回答
8

sudo改为使用

编辑:正如道格拉斯指出的那样,您不能使用cdinsudo因为它不是外部命令。您必须在子 shell 中运行命令才能完成cd工作。

sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"

sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update

您可能会被要求输入该用户的密码,但只能输入一次。

于 2010-01-01T09:42:24.980 回答
7

无法在 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');
于 2010-01-01T11:33:02.133 回答
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 &
于 2014-07-29T17:58:43.600 回答
-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. 如果您不需要环境变量,请-E从 sudo 中删除。

/usr/bin/bash -l确保profile.d脚本针对已初始化的环境执行。

于 2017-05-17T09:39:03.863 回答