Bash: Getting PID of daemonized screen session

安稳与你 提交于 2019-11-30 13:41:05

This show the pid for a screen named nameofscreen:

$ 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
$ 

you can use:

screen -DmS nameofscreen

which does not fork a daemon process allowing you to know the pid.

Parsing the output of screen -ls can be unreliable if two screen sessions have been started with the same name. Another approach is to not let the screen session fork a process and put it in the background yourself:

For example with an existing initial screen session:

fess@hostname-1065% screen -ls
There is a screen on:
        19180.nameofscreen    (01/15/2013 10:11:02 AM)        (Detached)

create a screen using -D -m instead of -d -m which does not fork a new process. Put it in the background and get it's pid. (Using posix shell semantics)

fess@hostname-1066% screen -DmS nameofscreen & 
[3] 19431
fess@hostname-1067% pid=$! 

Now there are two screens both have the same name:

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)

but we know the difference:

fess@hostname-1069% echo $pid
19431

and we can accurately ask it to quit:

fess@hostname-1070% screen -S $pid.nameofscreen -X quit
[3]  - done       screen -DmS nameofscreen

now there's just the original one again:

fess@hostname-1071% screen -ls 
There is a screen on:
        19180.nameofscreen    (01/15/2013 10:11:02 AM)        (Detached)

You can get the PID of the screen sessions here like so:

$ 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.

Let us suppose that you want the PID of the program running in Bash in the foo_Monitor screen session. Use the PID of the foo_Monitor screen session to get the PID of the bash session running in it by searching PPIDs (Parent PID) for the known 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

Now get just the PID of the bash session:

$ ps -el | grep 1814 | grep bash | awk '{print $4}'
1815

Now we want the process with that PID. Just nest the commands, and this time use the -v flag on grep bash to get the process that is not bash:

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

Just replace 1814 with the real PID or your screen session:

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

I suspect you really want the PID of the program running inside screen, which doesn't seem to be easily available. (And not really a well-defined question, since a single screen process can manage multiple children - that's one of the great things about screen!)

You could use pgrep to find a process whose PPID is the screen PID. Or do something like this:

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

Another way is using screen's -Q parameter for querying the session:

screen -S nameofscreen -Q echo '$PID'

Note that this will also display the PID inside the screen session as a notification.

To complete sarnold's answer:

$ 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

... get the PIDs of processes with this PID as PPID as follows:

$ ps --ppid 19841 -o pid=
19842

This answer is inspired by @sarnold.

Let me add a way to get all the screen PID:

screen -ls | awk '/[0-9]{1,}\./ {print strtonum($1)}'

Since 0-299 is the PID of the daemon in the old kernel, you can change {1,} to {3,}

You can operate on each process in the following ways, such as exiting them.

pidList=(screen -ls | awk '/[0-9]{3,}\./ {print strtonum($1)}')
for pid in ${pidList[@]};
do
    screen -X -S $pid quit
done

You can also do some other things with screen -X -S $pid stuff 'command\n'.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!