6

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

$ my_daemon &
$ echo $!

但是,如果我想以不同的用户身份运行它,例如:

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

现在如何捕获 my_daemon 的 PID?

4

5 回答 5

13

简而言之 - 有很多困难。

您必须安排 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 退出。)

警告:很好的理论 - 未经测试的代码......

于 2011-06-01T06:51:29.530 回答
1

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

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`
于 2016-02-05T20:31:56.003 回答
1

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

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

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

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

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

于 2020-09-10T18:54:33.410 回答
-1

这是我的解决方案

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

解释

  • pgrep -P $!- 获取父pid的子进程$!
于 2013-01-11T07:16:57.557 回答
-1

我通过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变量来提醒自己下次查看脚本时我在做什么。

于 2013-04-12T18:20:32.290 回答