Як запустити процес у підвішеному стані під Linux?


19

Практично мені потрібен процес, який веде себе так, ніби я натискав Ctrl+Zвідразу після його початку.

Сподіваємось, таке можна зробити за допомогою сценарію оболонки.

(Також, знаючи отриманий PID, було б чудово, тому я міг би продовжити процес згодом.)

Відповіді:


7

Після запуску процесу ви можете надіслати його SIGSTOP, щоб призупинити його. Щоб відновити його, надішліть SIGCONT. Я думаю, що цей маленький сценарій може вам допомогти

#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID

Він запускає процес (команда відправлення як параметр), призупиняє його, друкує ідентифікатор процесу та чекає, поки він закінчиться.


1
Я змінив його для продовження в кінці: [enter] #!/bin/bash [enter] $@ & [enter] PID=$! [enter] kill -STOP $PID [enter] echo "Suspended: $PID, press ENTER to continue it" [enter] read [enter] kill -CONT $PID [enter] wait $PID [enter] [enter]echo
java.is.for.desktop

7
Тільки щоб ви знали, підпроцес може закінчитися, перш ніж ви навіть отримаєте шанс надіслати на нього сигнал STOP.
MikeyB

16
Ще один день на перегонах.
ctrl-alt-delor

23

З якого середовища ви створюєте процес?

Якщо ви робите це з середовища, такого як код C, ви можете роздрібнити (), а потім у дитині, надіслати SIGSTOP до себе перед exec (), запобігаючи подальшому виконанню.

Більш загальним рішенням (мабуть, найкращим) було б створити заглушку, яка це робить. Тож програма заглушки:

  • Візьміть аргументи, що складаються з реального імені програми та аргументів
  • надішліть собі SIGSTOP
  • exec () реальна програма з відповідними аргументами

Це дозволить уникнути будь-яких умов перегонів, пов’язаних із тим, що нова обробка стає занадто далеко, перш ніж ви зможете надіслати на неї сигнал.


Приклад оболонки:

#!/bin/bash
kill -STOP $$
exec "$@"

І за допомогою наведеного вище кодексу:

michael@challenger:~$ ./stopcall.sh ls -al stopcall.sh

[1]+  Stopped                 ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ jobs -l
[1]+ 23143 Stopped (signal)        ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ kill -CONT 23143; sleep 1
-rwxr-xr-x 1 michael users 36 2011-07-24 22:48 stopcall.sh
[1]+  Done                    ./stopcall.sh ls -al stopcall.sh
michael@challenger:~$ 

jobs -lПоказує PID. Але якщо ви робите це з оболонки, вам не потрібен PID безпосередньо. Можна просто зробити: kill -CONT %1(якщо у вас є лише одна робота).

Робите це з більш ніж однією роботою? Зліва як вправа для читача :)


Я сподівався зробити це із сценарію оболонки ...
java.is.for.desktop

Чудово, тому оскільки ви хочете зробити це із сценарію оболонки, використовуйте програму stub.
MikeyB

20

Відповідь MikeyB правильна. З цього питання про суперпользователя, ось більш коротка версія:

( kill -SIGSTOP $BASHPID; exec my_command ) &

Щоб зрозуміти це, потрібно зрозуміти, як запускаються процеси на unix: execсистемний виклик замінює поточну запущену програму новою , зберігаючи існуючий PID. Тож спосіб створення незалежного процесу - це спочатку fork, а потім execзаміщення запущеної програми в дочірньому процесі бажаною програмою.

Інгредієнтами цієї команди оболонки є:

  1. В дужках (...)запускається підзагін: інший екземпляр BASH.
  2. killКоманда посилає сигнал СТОП в цей процес, який поміщає його в підвішеному стані.
  3. Як тільки ви дозволите процес тривати (посилаючи йому CONTсигнал), execкоманда змушує його замінити потрібну програму. my_commandзберігає оригінальний PID підкошти.
  4. Ви можете використовувати $!змінну, щоб отримати PID процесу.

2
Мені це подобається, оскільки він принципово правильний (просто те, що мені довелося використовувати -s STOPзамість -SIGSTOP). Ще дивуєтесь: чому це має бути $BASHPIDзамість цього $$? (Я, можливо, не дуже розумію різницю).
Hibou57

1
Для $$vs $BASHPID, я перевіряю, що останній є PID підшарпа, а не перший. Існує смішна проблема: застосування підказки в скрипті bash, найчастіше не вдається, і я повинен зробити щось подібне: PID=$!; ps -p $PID; kill -s CONT $PID;… це не вдасться, якщо я видалю ps -p $PIDчастину: процес, здається, зникає (вбивається?) Без повідомлення про помилку ніде . З інтерактивної оболонки все гаразд, проблема лише зі сценарію. Це занадто загадково.
Hibou57

Я спробував використати це рішення для переліку дескрипторів файлів my_command. ( goo.gl/cNbUE8 ), але дескриптори все ще однакові, неважливо, що є my_command.
rasty.g

Варіанти заміни $BASHPIDснарядів, окрім удару, дивіться тут
Якоб
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.