Reputation: 91649
If I start a GNU screen session as a daemon, how would I retrieve its PID programmatically? I don't know how consistent the output of screen -ls
is, so I'd like to know how to do this with one of bash's constants, $$
, $!
or a better alternative.
I am starting the screen with screen -dmS screenname
.
How would I get the PID of a screen right before or immediately after starting the screen session?
Upvotes: 15
Views: 23327
Reputation: 31481
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 of your screen session:
echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
Upvotes: 3
Reputation: 13
The first answer didn't work for me. Instead, I used this:
screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"
grep -oE
returns only what matches the regex,
which matches at least 1 number, a literal dot, and then screen_name
. For example, this might output 784.screen_name
(if the pid was 784). Then, use sed to remove everything after the first dot through the end of the string.
Upvotes: 0
Reputation: 31
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'
.
Upvotes: 3
Reputation: 1
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
Upvotes: 0
Reputation: 1548
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.
Upvotes: 0
Reputation: 1549
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)
Upvotes: 8
Reputation: 14711
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
Upvotes: 2
Reputation: 104050
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
$
Upvotes: 19