从后台进程获取 PID 作为另一个用户运行

Posted

技术标签:

【中文标题】从后台进程获取 PID 作为另一个用户运行【英文标题】:Getting a PID from a Background Process Run as Another User 【发布时间】:2011-09-06 00:45:49 【问题描述】:

从提示符中获取后台进程 ID 很容易,方法是:

$ my_daemon &
$ echo $!

但是如果我想以不同的用户身份运行它怎么办:

su - joe -c "/path/to/my_daemon &;"

现在如何获取 my_daemon 的 PID?

【问题讨论】:

在我看来,这对我来说确实是主题;这是一个关于 shell 编程的问题,因此在 SO 的范围内。 【参考方案1】:

简明扼要 - 有很多困难。

您必须安排 su'd shell 将子 PID 写入文件,然后选择输出。鉴于创建文件的是“joe”而不是“dex”,这就增加了另一层复杂性。

最简单的解决办法大概是:

su - joe -c "/path/to/my_daemon & echo \$! > /tmp/su.joe.$$"
bg=$(</tmp/su.joe.$$)
rm -f /tmp/su.joe.$$   # Probably fails - joe owns it, dex does not

下一个解决方案涉及使用备用文件描述符 - 编号 3。

su - joe -c "/path/to/my_daemon 3>&- & echo \$! 1>&3" 3>/tmp/su.joe.$$
bg=$(</tmp/su.joe.$$)
rm -f /tmp/su.joe.$$

如果您担心中断等(您可能应该担心),那么您也可以捕获一些东西:

tmp=/tmp/su.joe.$$
trap "rm -f $tmp; exit 1" 0 1 2 3 13 15
su - joe -c "/path/to/my_daemon 3>&- & echo \$! 1>&3" 3>$tmp
bg=$(<$tmp)
rm -f $tmp
trap 0 1 2 3 13 15

(捕获的信号是 HUP、INT、QUIT、PIPE 和 TERM - 加上 0 表示 shell 退出。)

警告:不错的理论 - 未经测试的代码...

【讨论】:

很棒的答案。我也许可以通过这个:su - joe -c "/path/to/my_daemon &amp; echo \$! &gt; /tmp/su.joe.$$" 逃避 $! my_daemon &amp; 之后没有分号当然也是陷阱。我打算玩一下。 一定要在$后面加一个空格!否则外壳可能会奇怪地解释这一点。【参考方案2】:

这里介绍的方法对我不起作用。这是我所做的:

PID_FILE=/tmp/service_pid_file
su -m $SERVICE_USER -s /bin/bash -c "/path/to/executable $ARGS >/dev/null 2>&1 & echo \$! >$PID_FILE"
PID=`cat $PID_FILE`

【讨论】:

【参考方案3】:

只要后台进程的输出被重定向,就可以将PID发送到stdout:

su "$user" -c "$executable > '$log_file' 2>&1 & echo \$!"

然后可以将 PID 重定向到第一个用户拥有的文件,而不是第二个用户。

su "$user" -c "$executable > '$log_file' 2>&1 & echo \$!" > "$pid_file"

不过,日志文件确实需要由第二个用户拥有才能这样做。

【讨论】:

【参考方案4】:

这是我的解决方案

su oracle -c "/home/oracle/database/runInstaller" &
pid=$(pgrep -P $!)

解释

pgrep -P $! - 获取父 pid $! 的子进程

【讨论】:

为什么这被否决了?两行简洁的代码,不使用 tmp 文件。【参考方案5】:

我在Linux上采用了上述解决方案,但不得不添加一个睡眠来让子进程有机会启动。

su - joe -c "/path/to/my_daemon > /some/output/file" &
parent=$!
sleep 1
pid=$(pgrep -P $parent)

在 bash 中运行,它不喜欢 pid=$(pgrep -P $!),但如果我在 ! 之后添加一个空格,则可以:pid=$(pgrep -P $! )。我坚持使用额外的 $parent 变量来提醒自己下次查看脚本时我在做什么。

【讨论】:

以上是关于从后台进程获取 PID 作为另一个用户运行的主要内容,如果未能解决你的问题,请参考以下文章

获取子进程的pid

如何从 iPhone 中后台进程的名称访问(复制/修改)特定的 appfile 目录?

如何检查正在运行的进程是不是是后台进程? [关闭]

C - 在后台启动外部程序并获取 pid

运行并从后台进程获取输出

总是在后台运行线程/进程?