bash以su作为不同的用户执行命令

时间:2017-06-04 12:08:40

标签: bash dash-shell

我有一个最简单的问题,我不确定我做错了什么。

我有一个简单的shell脚本使用/ bin / sh

在脚本中我有以下内容:

exec_as_wwwdata() {
 if [ $(whoami) = ${WWW_USER} ]]; then
    $@
  else
    su -s /bin/sh -c '$@' ${WWW_USER}
  fi
}

我用

来称呼它
exec_as_wwwdata composer config -g github-oauth.github.com $COMPOSER_GITHUB_TOKEN

它什么也没做,没有任何错误信息。 如果我直接在脚本中调用以下内容

su -s /bin/sh -c 'composer config -g github-oauth.github.com $COMPOSER_GITHUB_TOKEN' ${WWW_USER}

它有效。

我在这里做错了什么?

根据反馈,我已将其更改为

exec_as_wwwdata() {
 if [ $(whoami) = ${WWW_USER} ]]; then
    $@
  else
    su -s /bin/sh -c '"$@"' "$WWW_USER" _ "$@"
  fi
}

虽然我用以下参数调用它

exec_as_wwwdata /usr/local/bin/php /usr/local/bin/composer create-project --repository-url=xxxx .

我收到以下错误消息

su: unrecognized option '--repository-url=

我认为字符串中存在问题。我该怎么逃避呢?

1 个答案:

答案 0 :(得分:1)

此处$@有两个重叠用途,您无意中偶然发现了部分正确的解决方案。 -c需要一个单词,而"$@"会产生多个不同的单词。正确的解决方案是

su -s /bin/sh -c '"$@"' "$WWW_USER" _ "$@"

简短版本:您不想从当前参数构建命令字符串;你想把它们作为参数传递给硬编码的命令字符串,让新的shell适当地扩展。

细分:

  • -s /bin/sh - 使用/bin/sh代替相应用户的登录shell
  • -c '"$@"'根据需要运行命令"$@"。请注意,这是一个硬编码值;一旦启动,新shell将正确扩展其位置参数。
  • "$WWW_USER" - 指定运行shell的用户
  • _ - 在正在运行的shell中指定$0的值。你可能不在乎这个价值是什么;你只需要一些占位符来防止你的第一个真实论点被视为$0的值。
  • "$@"当前位置参数作为参数传递给新shell,这会将 "$@"扩展为这些值。