Bash: получение PID для демонизированного сеанса экрана
Если я начну сеанс экрана GNU в качестве демона, как мне получить его PID программным способом? Я не знаю, насколько последовательный вывод screen -ls
так что я хотел бы знать, как сделать это с одной из констант bash, $$
, $!
или лучшая альтернатива.
Я запускаю экран с screen -dmS screenname
,
Как мне получить PID экрана прямо до или сразу после начала сеанса экрана?
6 ответов
Это показывает PID для экрана с именем 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
$
Ты можешь использовать:
screen -DmS nameofscreen
который не разветвляет процесс демона, позволяющий вам узнать pid.
Анализ выходных данных screen -ls может быть ненадежным, если два сеанса экрана были запущены с одним и тем же именем. Другой подход состоит в том, чтобы не допустить, чтобы сеанс экрана запустил процесс и поместил его в фоновом режиме:
Например, с существующим начальным сеансом экрана:
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-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)
Вы можете получить 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.
Допустим, вы хотите, чтобы PID программы, запущенной в Bash, находился в foo_Monitor
сеанс экрана. Используйте PID foo_Monitor
сеанс экрана, чтобы получить PID bash
сеанс выполняется в нем путем поиска PPID (PID Parent) для известного 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
Теперь получите только PID bash
сессия:
$ 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
Просто замените 1814 реальным PID или сеансом экрана:
echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
Этот ответ вдохновлен @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'
,
Я подозреваю, что вы действительно хотите 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 -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
Первый ответ у меня не сработал. Вместо этого я использовал это:
screen -ls | grep -oE "[0-9]+\.screen_name" | sed -e "s/\..*$//g"
grep -oE
возвращает только то, что соответствует регулярному выражению, которое соответствует как минимум 1 числу, буквальной точке, а затем screen_name
. Например, это может выводить784.screen_name
(если pid был 784). Затем используйте sed, чтобы удалить все, что находится после первой точки в конце строки.
Другой способ - использовать параметр экрана -Q для запроса сеанса:
screen -S nameofscreen -Q echo '$PID'
Обратите внимание, что это также будет отображать PID внутри сеанса экрана в качестве уведомления.