【问题标题】:Spawning background process under different user in bash在bash中在不同用户下生成后台进程
【发布时间】:2014-02-06 05:31:14
【问题描述】:

我知道我可以运行此命令来生成后台进程并获取 PID:

PID=`$SCRIPT > /dev/null 2>&1 & echo $!`

并在不同的用户下运行命令:

su - $USER -c "$COMMAND"

我不希望脚本以 root 身份运行,而且我不知道如何将两者结合起来并获得生成进程的 PID。

谢谢!

【问题讨论】:

  • 为什么以 root 身份登录,然后以 non-root 用户身份su 来运行进程?为什么首先以 root 身份登录?
  • 这是用于初始化脚本
  • @t0x13:您的问题是否与$! 引用的过早扩展有关,即它在su 执行实际命令之前已扩展?如果我在 CentOS 6.5 上运行以下简单测试,我始终得到非空结果:PID=$(su $USER -c ': & echo ${!}'); echo $PID - 请注意该命令如何由单引号保护以防止过早扩展。在 double 引用的字符串中,使用 \$!

标签: bash centos


【解决方案1】:

我想你想要runuser 命令。一般语法:

runuser -l  userNameHere -c 'command'

我怀疑如果您将 $SCRIPT 变量设置为上述变量(进行适当更改),您的第一个命令将执行您想要的操作。

【讨论】:

  • 我收到了runuser: command not found,抱歉,我仍然不明白您的建议?
  • 为了清楚起见,我可以执行类似 PID=su - $USER -c "$SCRIPT > /dev/null 2>&1 & echo $!" 的操作,并且该进程会正常生成,但我无法获得 PID(它是空的),我可以使用 "$ !”
  • 一些背景:runuser 显然只带有Red Hat Linux derivatives,例如 RHEL、Fedora 和 CentOS(尽管 OP 似乎有一个可能没有它的旧 CentOS 版本)。这是一个简化的su,不需要密码,但必须以root身份运行;更多信息here
【解决方案2】:

详细说明:请参阅以下内容:-stackoverflow.com/questions/9119885/...

请特别参阅 Chris Dodd 的以下引言:

不幸的是,在 bash 版本 4 之前没有简单的方法可以做到这一点,当时 $BASHPID 是 介绍了。您可以做的一件事是编写一个打印其父 PID 的小程序:...

如果您有 bash 4 和 BASHPID,请参阅 $$ in a script vs $$ in a subshell

我没有第 4 版,所以我无法提供它的用法示例。

或者编写一个小型 C 程序来执行它的参数并将其 setuid 设置为 USER。 甚至制作一个 setuid shell 脚本(一般不推荐)。希望USER 已修复;如果没有,请获取runuser 的源代码,这实际上是 runuser(不是 POSIX 命令)所做的。

PID=`su - $USER -c "$SCRIPT > /dev/null 2>&1 & echo $!"`

您使用su(上图)的问题包括:

  • $! 是在 -c 的子 shell 的上下文中执行的 su,而不是当前的 shell PID
  • 你要求你的SCRIPT作为登录shell运行,所以你甚至不知道USER的shell是否支持$!
  • 您无法控制su(和用户的shell)创建的父子进程链。

IOW,当你使用时

PID=`$SCRIPT > /dev/null 2>&1 & echo $!`

只涉及一个程序,bash,以及两个(也许三个?)您几乎可以完全控制的进程。当您将su 加入其中时,事情的变化远比表面上明显的要多——bashsu 支持类似的论点,对吧?!? 出于显而易见的原因,su 使用了很多魔法来保护它及其“儿童环境”免受攻击;它甚至不喜欢被放在后台......

【讨论】:

  • 感谢您的解释。我会检查链接。
  • @kingolego:您的su 命令的直接问题是$! 立即被original shell 扩展,因为" 中的封闭。要真正将其传递给su 调用的shell(作为目标用户),您必须改用\$!(或者,使用单引号)。您可以在没有 su 的情况下通过交互比较以下两个命令来验证问题:bash -c ": & echo ${!}"bash -c ": & echo \${!}" - 只有后者才能按预期工作。
【解决方案3】:

有点晚了,但是这里有两个班轮可以工作,似乎需要两个班轮,这样它就不会等待 $SCRIPT 完成:

su $USER -c "$SCRIPT 2>&1 & >> $LogOrNull echo $! > /some/writeable/path"
PID="$(cat /some/writeable/path)"

/some/writeable/path 需要可由 $USER 写入 并且运行这些命令的用户需要具有读取权限

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 2011-01-31
    • 2013-07-28
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    相关资源
    最近更新 更多