Как запустить процесс в приостановленном состоянии под Linux?
Практически мне нужен процесс, который ведет себя так, как будто я нажал Ctrl+Z
только после того, как это началось.
Надеюсь, это можно сделать с помощью сценария оболочки.
(Кроме того, было бы неплохо знать полученный PID, поэтому я мог бы продолжить процесс позже.)
3 ответа
После запуска процесса вы можете отправить его SIGSTOP, чтобы приостановить его. Чтобы возобновить его, отправьте SIGCONT. Я думаю, что этот маленький сценарий может помочь вам
#!/bin/bash
$@ &
PID=$!
kill -STOP $PID
echo $PID
wait $PID
Он запускает процесс (команда send в качестве параметра), приостанавливает его, печатает идентификатор процесса и ожидает его завершения.
Из какой среды вы создаете процесс?
Если вы делаете это из среды, такой как код на C, вы можете выполнить fork(), а затем в дочерней среде отправить 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
(при условии, что у вас есть только одна работа).
Делать это с более чем одной работой? Оставлено как упражнение для читателя:)
MikeyB ответ правильный. Из этого вопроса о суперпользователе, вот более краткая версия:
( kill -SIGSTOP $BASHPID; exec my_command ) &
Чтобы понять это, нужно понять, как процессы запускаются в Unix: exec
Системный вызов заменяет текущую запущенную программу новой, сохраняя существующий PID. Таким образом, способ создания независимого процесса заключается в том, чтобы сначала fork
, а потом exec
, заменив запущенную программу в дочернем процессе на нужную программу.
Ингредиенты этой команды оболочки:
- Круглые скобки
(...)
запустить суб-оболочку: еще один экземпляр BASH. kill
Команда отправляет сигнал STOP этому процессу, который переводит его в состояние ожидания.- Как только вы разрешите продолжить процесс (отправив
CONT
сигнал),exec
Команда заставляет его заменить себя желаемой программой.my_command
сохраняет исходный PID суб-оболочки. - Вы можете использовать
$!
переменная, чтобы получить PID процесса.