|
| |||
|
|
bash-скриптинг и все-все-все [Решено] Приветствую. У меня есть вот какой расклад: есть машина с zLinux (SLES) 11.3. На ней есть пользователь, у которого в качестве командной строки прописан /bin/bash. На машине есть скрипт-менюшка (первая строка - #!/bin/sh), который по нажатию клавиши запускает другой скрипт, который запускает java [parameters] &. Случай А. Запуск скрипта-менюшки прописан пользователю в .profile, а после него в .profile стоит exit. Пользователь может запустить java, но, когда он выходит из системы (не скрипта, а именно системы, я проверял), ява завершается. Случай В. Запуск скрипта-менюшки из .profile вынесен, и он запускается из командной строки. При этом, если пользователь запускает java из менюшки, а потом выходит из системы, ява остается работать. WTF? Иерархия процессов в обоих случаях одинаковая: sshd -> -bash -> /bin/sh menu.sh. Запущенная java одинаково считает родительским процессом 1. Словом, мне совершенно непонятны причины различия. Пока что заткнул проблему, добавив в вызов java слева nohup, но хотелось бы разобраться с причинами. UPD: пришел ответ от поддержки. 1. Замечание случаю А (первое предложение) ---------------------------------------- Если в ходе выполнения .profile сессионный bash встречает exit (в самом профайле, а не где-нибудь во внутреннем скрипте), то он завершается, и сессия полноценно так и не запустится. Это легко проверить, поместив exit , например, в конце файла .profile . 2. Запущенные из .profile и из сессии фоновые процессы, имеющие одинаковые PPID ( 1 ) , при этом обычно имеют разные идентификаторы групп процессов PGID . Интерпретатор bash , запускаемый при открытии сессии (сеанса), становится лидером сессии (сеанса), и получает идентификатор сессии ( SID ) и PGID равными своему PID . Фоновый процесс, запускаемый из профайла, получает PGID и SID, равные SID лидера сессии. Фоновый же процесс, запускаемый из сессии, получает PGID, отличный от SID ( обычно равный своему PID или PID процесса, запустившего фоновый). При завершении сеанса лидер сессии ( bash ) сигналом SIGHUP завершает те фоновые процессы, у которых PGID и SID равны его SID, даже если у них нет управляющего терминала. Если же PGID отличен от SID, то этот фоновый процесс отсоединяется от управляющего терминала, если таковой имеется, и живёт дальше. 3. Есть несколько способов не допустить завершения фонового процесса, запущенного из профайла. Можно использовать упомянутую Вами команду nohup, однако она игнорирует стандартный ввод, а стандартный вывод направляет в файл nohup.out . Также можно с помощью встроенной команды trap замаскировать сигнал SIGHUP, поместив в профайл строку: trap '' 1 Однако в этом случае сигнал SIGHUP будет замаскирован для всех процессов сессии. Для решения данной проблемы лучше всего подходит механизм создания новой сессии ( setsid ) . Если программа доступна в исходных кодах, то следует использовать системный вызов setsid(), в результате выполнения которого PGID и SID вызывающего процесса устанавливаются равными идентификатору вызывающего процесса (PID). Вызывающий процесс будет единственным в этой новой группе процессов и новой сессии. В случае уже готовой программы нужно воспользоваться командой setsid. Запускаемая с ее помощью программа становится лидером новой сессии, лидером новой группы процессов и не имеет управляющего терминала. |
||||||||||||||