Bash:获取后台屏幕会话的PID

Bash:获取后台屏幕会话的PID,bash,gnu-screen,Bash,Gnu Screen,如果我作为守护进程启动GNU屏幕会话,我将如何以编程方式检索其PID?我不知道screen-ls的输出有多一致,所以我想知道如何使用bash的一个常量,$,$或更好的选择 我用screen-dmS screenname启动屏幕 如何在启动屏幕会话之前或之后立即获取屏幕的PID?这将显示名为nameofscreen的屏幕的PID: $ screen -ls There are screens on: 19898.otherscreen (07/03/2012 05:50:45 PM)

如果我作为守护进程启动GNU屏幕会话,我将如何以编程方式检索其PID?我不知道
screen-ls
的输出有多一致,所以我想知道如何使用bash的一个常量,
$
$或更好的选择

我用
screen-dmS screenname
启动屏幕


如何在启动屏幕会话之前或之后立即获取屏幕的PID?

这将显示名为
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
$ 

我怀疑您真的想要在屏幕内运行程序的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
您可以使用:

screen -DmS nameofscreen
它不会派生一个允许您了解pid的守护进程

如果使用相同的名称启动了两个screen会话,那么解析screen-ls的输出可能不可靠。另一种方法是不要让screen会话分叉一个进程,而自己将其放在后台:

例如,对于现有的初始屏幕会话:

fess@hostname-1065% screen -ls
There is a screen on:
        19180.nameofscreen    (01/15/2013 10:11:02 AM)        (Detached)
使用-D-m而不是-D-m创建一个屏幕,它不会派生一个新进程。把它放在背景中,得到它的pid。(使用posix外壳语义)

现在有两个屏幕都有相同的名称:

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)

您可以在此处获得屏幕会话的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\u Monitor
屏幕会话中的Bash中运行程序的PID。使用
foo\u监视器
screen会话的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的过程。只需嵌套命令,这次使用
grep bash
上的
-v
标志来获取非bash的进程:

只需将1814替换为真正的PID或屏幕会话:

echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')

另一种方法是使用screen的-Q参数查询会话:

screen -S nameofscreen -Q echo '$PID'

请注意,这也将在屏幕会话中显示PID作为通知。

要完成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

这个答案的灵感来自@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'

执行其他操作第一个答案对我不起作用。相反,我用了这个:

screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"
grep-oE
仅返回与正则表达式匹配的内容,
它至少匹配一个数字,一个文字点,然后是
屏幕名称
。例如,这可能会输出
784.screen\u name
(如果pid为784)。然后,使用sed删除字符串末尾第一个点之后的所有内容。

screen-ls
有什么问题?。。为什么不能通过脚本使用
screen-ls
?如果在$PID中有孩子的PID,
ps-p$PID-o ppid=
将显示家长的PID。
pidList=(screen -ls | awk '/[0-9]{3,}\./ {print strtonum($1)}')
for pid in ${pidList[@]};
do
    screen -X -S $pid quit
done
screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"