Скрипт оболочки, который может проверить, был ли он основан на вызове - PullRequest
3 голосов
/ 31 августа 2010

Я написал скрипт, который опирается на ответы других серверов (использует wget для извлечения данных), и я хочу, чтобы он всегда выполнялся в фоновом режиме.Я знаю, что одно из решений состоит в том, чтобы просто написать скрипт-обертку, который будет вызывать мой скрипт с добавленным символом «&», но я хочу избежать этого беспорядка.определить, вызван ли он с помощью say ./foo.sh&, и если нет, выйти и перезапустить себя как таковой?

Спасибо всем!

Ответы [ 5 ]

7 голосов
/ 01 сентября 2010

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

В Linux (и, возможно, в других версиях) столбец STAT в ps включает + когда процесс является частью основной группы процессов своего терминала.Таким образом, буквальный ответ на ваш вопрос заключается в том, что вы можете поместить содержимое вашего скрипта в функцию main и вызвать ее с помощью:

case $(ps -o stat= -p $$) in
  *+*) main "$@" &;;
  *) main "$@";;
esac

Но вы все равно можете запустить main "$@" & в любом случае.В Unix форк это дешево.

Однако я настоятельно не советую делать то, что вы предлагаете.Это делает невозможным для кого-то запускать ваш сценарий и делать что-то еще после этого - можно ожидать, что он сможет написать your_script; my_postprocessing или your_script && my_postprocessing, но отказ от основной задачи сценария делает это невозможным.Принимая во внимание, что выигрыш иногда сохраняет один символ при вызове скрипта, не стоит делать ваш скрипт заметно менее полезным таким образом.

Если вы действительно хотите, чтобы скрипт работал в фоновом режиме, чтобы пользовательможете закрыть его терминал, вам нужно будет проделать дополнительную работу - вам нужно daemonize сценарий, который включает в себя не только фоновую обработку, но и закрытие всех файловых дескрипторов, у которых открыт терминал, что делает процессведущий сессии и многое другое.Я думаю, что это потребует разделения вашего скрипта на демонизирующий скрипт-обертку и основной скрипт.Но демонизация обычно выполняется для программ, которые никогда не завершаются, если явно не остановлены, что не соответствует описанному вами поведению.

2 голосов
/ 31 августа 2010

Я не знаю, как это сделать, но вы можете установить переменную в родительском скрипте и проверить ее в дочернем:

if [[ -z "$_BACKGROUNDED" ]] ; then
    _BACKGROUNDED=1 exec $0 $@ & exit
fi
# Put code here

Работает как в bash, так и в zsh.

1 голос
/ 08 августа 2012

команда "tty" говорит "не tty", если вы находитесь в фоновом режиме, или дает имя управляющего терминала (например, / dev / pts / 1), если вы на переднем плане. Простой способ сказать.

0 голосов
/ 20 января 2012

Помните, что вы не можете (или не рекомендуется) редактировать запущенный скрипт. Этот вопрос и ответы дают обходные пути.

0 голосов
/ 31 августа 2010

Я давно не пишу сценарии оболочки, но могу дать вам очень хорошую идею (надеюсь).Вы можете проверить значение $$ (это PID процесса) и сравнить с выводом команды "jobs -l".Эта последняя команда вернет PID всех фоновых процессов (заданий), и если значение $$ содержится в результате «jobs -l», это означает, что текущий сценарий выполняется в фоновом режиме.

...