Почему setsid не может выйти из сценария оболочки?
$ cat test1.sh
#!/bin/bash
setsid sleep 100
Сценарий оболочки 'test1.sh' не завершится сразу.
$ cat test2.sh
#!/bin/bash
setsid sleep 100 &
Сценарий оболочки 'test2.sh' завершится сразу.
Может ли кто-нибудь объяснить для меня? Большое спасибо.
2 ответа
Вопрос, вероятно, является дубликатом этого еще более старого вопроса, и ответ там весьма полезен. Возможно, их следует объединить.
Меня тоже удивило такое поведение. Итак, я проверил справочную страницу:
DESCRIPTION
setsid runs a program in a new session. The command calls fork(2) if already a
process group leader. Otherwise, it executes a program in the current process.
This default behavior is possible to override by the --fork option.
Некоторый жаргон, чтобы понять здесь. Давайте проверим список определений POSIX (глава 3).
Сеанс это:
Набор групп процессов, созданных для целей управления заданиями. Каждая группа процессов является членом сеанса. Процесс считается членом сеанса, членом которого является его группа процессов. Вновь созданный процесс присоединяется к сеансу своего создателя. Процесс может изменить свое членство в сеансе; см. setsid(). В одном сеансе может быть несколько групп процессов.
The
fork()
call создает новый процесс, копируя текущий процесс. Больше информации в этом посте.
Лидер группы процессов:
Процесс, идентификатор процесса которого совпадает с идентификатором его группы процессов.
Так,
setsid
создаст новый процесс только в том случае, если он выполняется в качестве лидера группы процессов. Это всегда имеет место при запуске команды непосредственно в оболочке, поэтому очередь заданий может быть построена в виде списка групп процессов. Однако при запуске в составе сценария лидером группы является новый процесс оболочки, используемый для запуска сценария.
К счастью, у нас есть
--fork
возможность принудительного создания нового процесса. Например, сценарий оболочки:
#!/bin/sh
setsid --fork sleep 5
выйдет, не дожидаясь завершения, и
sleep
Команда будет продолжаться, даже если вы закроете оболочку, из которой был запущен скрипт. Насколько мне известно,
setsid --fork
это единственный способ убедиться, что команда выполняется как отдельный процесс .
Другие источники:
Ваш первый скрипт ждет setsid sleep 100
быть завершенным и затем возвращаемым (другими словами, он вернется после завершения сна, 100 секунд здесь), но 2-й сценарий не ожидает завершения команды, потому что &
переводит команду в фоновый режим и возвращает сразу. Цитировать man bash
:
If a command is terminated by the control operator &, the shell executes the
command in the background in a subshell. The shell does not wait for the command
to finish, and the return status is 0.
Также обратите внимание, что &
является оператором управления и имеет более высокий приоритет. Надеюсь это поможет!