如果我作为一个守护进程启动GNU screen会话,如何以编程方式检索其PID?我不知道screen -ls的输出有多一致,因此我想知道如何使用bash的一个常量$$、$!或更好的替代方法来完成这项工作。我是用screen -dmS screenname启动screen的。在启动屏幕会话之前或之后立即获取屏幕的PID应该怎么做呢?
这将展示名为nameofscreen
的屏幕的进程ID:
$ screen -ls
There are screens on:
19898.otherscreen (07/03/2012 05:50:45 PM) (Detached)
19841.nameofscreen (07/03/2012 05:50:23 PM) (Detached)
2 Sockets in /var/run/screen/S-sarnold.
$ screen -ls | awk '/\.nameofscreen\t/ {print strtonum($1)}'
19841
$
您可以使用:
screen -DmS nameofscreen
该方法不会分叉出一个守护进程,让您能够知道pid。
如果使用相同的名称启动了两个screen会话,则解析screen -ls的输出可能不可靠。另一种方法是不要让screen会话分叉出一个进程,并自己将其放在后台:
例如,对于现有的初始screen会话:
fess@hostname-1065% screen -ls
There is a screen on:
19180.nameofscreen (01/15/2013 10:11:02 AM) (Detached)
fess@hostname-1066% screen -DmS nameofscreen &
[3] 19431
fess@hostname-1067% pid=$!
现在有两个屏幕,它们的名称相同:
fess@hostname-1068% screen -ls
There are screens on:
19431.nameofscreen (01/15/2013 10:53:31 AM) (Detached)
19180.nameofscreen (01/15/2013 10:11:02 AM) (Detached)
fess@hostname-1069% echo $pid
19431
我们可以准确地要求它退出:
fess@hostname-1070% screen -S $pid.nameofscreen -X quit
[3] - done screen -DmS nameofscreen
fess@hostname-1071% screen -ls
There is a screen on:
19180.nameofscreen (01/15/2013 10:11:02 AM) (Detached)
$ screen -ls
There are screens on:
1934.foo_Server (01/25/15 15:26:01) (Detached)
1876.foo_Webserver (01/25/15 15:25:37) (Detached)
1814.foo_Monitor (01/25/15 15:25:13) (Detached)
3 Sockets in /var/run/screen/S-ubuntu.
假设您想要获取在foo_Monitor
screen会话中运行的Bash程序的PID。使用foo_Monitor
screen会话的PID来查找已知PID的PPID(父进程ID),以获取其中运行的bash
会话的PID:
$ ps -el | grep 1814 | grep bash
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 1815 1814 0 80 0 - 5520 wait pts/1 00:00:00 bash
bash
会话的进程ID(PID):$ ps -el | grep 1814 | grep bash | awk '{print $4}'
1815
现在我们想要使用那个 PID 的进程。只需要嵌套命令,并且这次在 grep bash
命令中使用 -v
标志以获取不是 bash 进程的进程:
echo $(ps -el | grep $(ps -el | grep 1814 | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
23869
只需将1814替换为您的屏幕会话的真实PID:
echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
screen -ls | awk '/[0-9]{1,}\./ {print strtonum($1)}'
旧内核中0-299是守护进程的PID,因此您可以将{1,}更改为{3,}
您可以通过以下方式对每个进程进行操作,例如退出它们。
pidList=(screen -ls | awk '/[0-9]{3,}\./ {print strtonum($1)}')
for pid in ${pidList[@]};
do
screen -X -S $pid quit
done
你还可以使用 screen -X -S $pid stuff 'command\n'
来执行一些其他操作。
rm mypidfile
screen -dmS blah sh -c 'echo $$ > mypidfile ; exec sh'
# the write to mypidfile is happening in the background, so wait it to show up
while [ ! -s mypidfile ]; do sleep 1; done
pid=`cat mypidfile`
# $pid is now the PID of the shell that was exec'ed inside screen
ps -p $pid -o ppid=
将显示其父进程的 PID。 - Alan Curry补充sarnold的回答:
$ screen -ls
There are screens on:
19898.otherscreen (07/03/2012 05:50:45 PM) (Detached)
19841.nameofscreen (07/03/2012 05:50:23 PM) (Detached)
2 Sockets in /var/run/screen/S-sarnold.
$ screen -ls | awk '/\.nameofscreen\t/ {print strtonum($1)}'
19841
获取以此 PID 为 PPID 的进程的 PID,方法如下:
$ ps --ppid 19841 -o pid=
19842
screen -S nameofscreen -Q echo '$PID'
第一个答案对我没用。相反,我用了这个:
screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"
grep -oE
只返回与正则表达式匹配的内容,该正则表达式至少匹配一个数字、一个字面点和 screen_name
。例如,这可能会输出 784.screen_name
(如果 pid 是 784)。然后,使用 sed 命令删除第一个点之后到字符串结尾的所有内容。
screen -ls
有什么问题吗? - sarnoldscreen -ls
的脚本来完成呢? - sarnold