bash 从以另一个用户身份运行的后台进程获取 PID

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6197165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 00:05:55  来源:igfitidea点击:

Getting a PID from a Background Process Run as Another User

bashpidsu

提问by Dex

Getting a background process ID is easy to do from the prompt by going:

通过以下方式从提示中获取后台进程 ID 很容易:

$ my_daemon &
$ echo $!

But what if I want to run it as a different user like:

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

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

Now how can I capture the PID of my_daemon?

现在如何捕获 my_daemon 的 PID?

回答by Jonathan Leffler

Succinctly - with a good deal of difficulty.

简洁 - 有很多困难。

You have to arrange for the su'd shell to write the child PID to a file and then pick the output. Given that it will be 'joe' creating the file and not 'dex', that adds another layer of complexity.

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

The simplest solution is probably:

最简单的解决方案可能是:

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

The next solution involves using a spare file descriptor - number 3.

下一个解决方案涉及使用备用文件描述符 - 编号 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.$$

If you're worried about interrupts etc (and you probably should be), then you trap things too:

如果您担心中断等(您可能应该担心),那么您也会陷入困境:

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

(The caught signals are HUP, INT, QUIT, PIPE and TERM - plus 0 for shell exit.)

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

Warning: nice theory - untested code...

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

回答by Dave

The approaches presented here didn't work for me. Here's what I did:

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

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`

回答by koola

Here's my solution

这是我的解决方案

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

Explantation

解释

  • pgrep -P $!- Gets the child process of the parent pid $!
  • pgrep -P $!- 获取父pid的子进程 $!

回答by pmoench

I took the above solution by Linux, but had to add a sleep to give the child process a chance to start.

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

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

Running in bash, it doesn't like pid=$(pgrep -P $!)but if I add a space after the !it's ok: pid=$(pgrep -P $! ). I stuck with the extra $parentvariable to remind myself what I'm doing next time I look at the script.

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