如果我作为守护进程启动GNU屏幕会话,我将如何以编程方式检索其PID?我不知道screen -ls
的输出是多么一致,所以我想知道如何使用bash的常量之一,$$
,$!
或更好的替代方法。
我正在使用screen -dmS screenname
启动屏幕。
如何在开始屏幕会话之前或之后立即获得屏幕的PID?
答案 0 :(得分:14)
这会显示名为nameofscreen
的屏幕的pid:
$ 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
$
答案 1 :(得分:3)
您可以在此处获取屏幕会话的PID:
$ 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
屏幕会话中以Bash运行程序的PID。使用foo_Monitor
屏幕会话的PID通过在PPID(父PID)中搜索已知的PID来获取其中运行的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
会话的PID:
$ ps -el | grep 1814 | grep bash | awk '{print $4}'
1815
现在我们想要那个 PID的过程。只需嵌套命令,这次使用-v
上的grep bash
标志来获取不 bash的进程:
echo $(ps -el | grep $(ps -el | grep 1814 | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
23869
只需用实际PID或屏幕会话替换1814:
echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
答案 2 :(得分:2)
我怀疑你真的希望程序的PID在屏幕内运行,这似乎不容易获得。 (并不是一个定义明确的问题,因为单个屏幕进程可以管理多个孩子 - 这是关于屏幕的好事之一!)
您可以使用pgrep查找PPID为屏幕PID的进程。或者做这样的事情:
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
答案 3 :(得分:0)
另一种方法是使用screen的-Q参数来查询会话:
screen -S nameofscreen -Q echo '$PID'
请注意,这也会在屏幕会话中显示PID作为通知。
答案 4 :(得分:0)
完成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获取进程的PID作为PPID,如下所示:
$ ps --ppid 19841 -o pid=
19842
答案 5 :(得分:0)
此答案的灵感来自@sarnold。
让我添加一种获取所有屏幕PID的方法:
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'
做其他事情。
答案 6 :(得分:0)
第一个答案对我不起作用。相反,我使用了这个:
screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"
grep -oE
仅返回与正则表达式匹配的内容,
至少匹配一个数字,一个文字点和一个screen_name
。例如,这可能输出784.screen_name
(如果pid为784)。然后,使用sed删除字符串中第一个点之后的所有内容。