У меня есть скрипт сценария script.sh с командой cmd запущенной в фоновом режиме, то есть:

#!/bin/bash
…
cmd &
…

Если я открою эмулятор терминала (я пробовал xfce4-терминал и gnome-терминал) и запускаю script.sh внутри, моя команда cmd эффективно выполняется и выполняется в фоновом режиме, как и ожидалось.

Но, если я открою эмулятор терминала из предыдущего (или в начале моего сеанса рабочего стола, который является моим реальным вариантом использования), и выполню мой сценарий

xfce4-terminal -H -x script.sh (or gnome-terminal -x script.sh)

команда cmd больше не выполняется.

Я обнаружил, что могу заставить его исполниться, вставив set -m в мой скрипт, но я не понимаю, почему это необходимо (или на самом деле недостаточно) в этом случае, а не в предыдущем. Действительно, если я добавлю в свой сценарий set -o , я получу одинаковый вывод в обоих случаях.

Может кто-нибудь объяснить мне это и / или сказать, как правильно выполнять фоновые задания в сценариях оболочки? Спасибо!


РЕДАКТИРОВАТЬ: На самом деле, cmd выполняется в обоих случаях, но во втором случае он немедленно уничтожается при завершении script.sh . Чтобы предотвратить это, можно использовать nohup , но этого недостаточно, и это самое странное для меня: нужно также поставить sleep 1 или что-то в этом роде, чтобы позволить процессу правильно запускаться в фоновом режиме и отделяться от родительская оболочка, иначе она тоже убивается.

Я действительно не понимаю эту разницу в поведении между двумя оболочками, так как они не являются интерактивными, как указано в предыдущем комментарии.

2 ответа2

1

Если вы открываете xfce4-trminal или gnome-terminal (или другой терминал), ваша оболочка находится в интерактивном режиме. Каждый скрипт запускается в интерактивном режиме.

Если вы запускаете script.sh через

xfce4-terminal -H -x script.sh

или же

gnome-terminal -x script.sh

или другой терминал, ваша оболочка находится в неинтерактивном режиме.

Скрипты могут быть принудительно запущены в интерактивном режиме с опцией -i или с #!/bin/bash -i header. Имейте в виду, что это может привести к нестабильному поведению сценария или отображать сообщения об ошибках, даже если ошибок нет.

Что set -m? Это режим монитора. Фоновые процессы выполняются в отдельной группе процессов, и после их завершения печатается строка, содержащая их статус выхода. Он включен по умолчанию для интерактивных оболочек.

Что set -o? Это записать текущие настройки параметров в стандартный вывод в неопределенном формате.

Почему set -o работает?

Опция -o была принята из KornShell для удовлетворения потребностей пользователей. В дополнение к общепринятому дружественному интерфейсу, -o необходим для обеспечения режима редактирования командной строки vi, для которого историческая практика не выдает имя опции из одной буквы. (Хотя, возможно, было возможно изобрести такое письмо, было признано, что будут разработаны другие режимы редактирования, и -o предоставляет достаточно пространства имен для описания таких расширений.)

Исторические реализации несовместимы в формате, используемом для отчетов о состоянии опции -o. Формат +o без аргумента-опции был добавлен, чтобы обеспечить переносимый доступ к опциям, которые можно сохранить, а затем восстановить, используя, например, точечный скрипт.

В любом случае, set -m является предпочтительным способом.

0

Ответ на вопрос дан на Unix Stackexchange (см. Также дополнительные комментарии ниже ответа). Вопрос в том, кто посылает сигнал SIGHUP, кому и когда. И альтернативой set -m / set +m cmd & в script.sh является trap '' HUP / trap - HUP .

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .