2013-06-28 5 views
4

У меня есть сценарий, который запускает другой сценарий в фоновом режиме, а затем завершает его. Я ожидал, что дочерний скрипт исчезнет, ​​но, в конце концов, ему все же удается напечатать некоторый результат. Вот пример:Как делаются процессы с & (в bash) и убивают их?

в сценарий one.sh:

echo "this is one" 
./two.sh & 
sleep 1 
pid=$! 
kill $pid 
echo "this was one" 

в сценарий two.sh:

echo "this is two" 
./three.sh 
echo "this was two" 

в сценарий three.sh:

echo "this is three" 
sleep 5 
echo "this was three" 

я побежал ./one.sh, который должен запускать two.sh в фоновом режиме, который, в свою очередь, запускает three.sh, но не в фоновом режиме! Выход получают:

this is one 
this is two 
this is three 
this was one 
this was three 

Если не «это три» не появляется на выходе, так как three.sh не побежали в фоновом режиме и two.sh останавливал one.sh? Не могли бы вы также указать мне на любую документацию, описывающую, как процессы ведут себя, когда (не) в фоновом режиме и что происходит, когда они прекращаются?

Большое спасибо за вашу помощь!

ответ

1

Вы убиваете фоновый процесс two.sh, но не two.sh и его ребенок three.sh.

Этот вопрос:

Best way to kill all child processes

имеет больше информации о убивая дочерние процессы.

1

Когда вы начинаете новый процесс из сценария bash, это в основном выполняется через fork().

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

Если родительский элемент умирает, он становится дочерним элементом процесса init. Затем роль процесса init собирает код возврата ребенка (пожинает) после его выхода. Поэтому, когда вы убиваете «два», «три» не убивают, а просто получают другого родителя. И это является причиной для трех отстающих.

Вопрос обсуждается с C-точка-обзора здесь: How to make child process die after parent exits?

+0

Процесс init не убивает ребенка; он просто собирает статистику от трупа (зомби), чтобы зомби не накапливались без ограничений. –

+0

Спасибо, я отредактировал ответ – kamjagin

0

Причиной этого может показаться удивительным является то, что можно было бы ожидать, что сигнал TERM (по умолчанию от «убить»), который будет распространяться на другими словами, сигнал SIGTERM (сигнал № 15), полученный с помощью two.sh, будет распространяться и на three.sh. Однако на самом деле это не так. Убийство two.sh просто убирает three.sh в процесс «init» (proceess ID 1) в качестве нового родительского процесса, а init будет очищаться после трех .sh, когда он выйдет.

Ситуация усложняется группами процессов, а в документации по bash говорится о том, как сигналы, генерируемые клавиатурой, посылаются всем процессам в группе процессов переднего плана, часто конвейер выполняется без «&» в конце. Однако эти проблемы не относятся к примерным скриптам.

Примечание. В Unix вы не должны использовать расширения .sh для исполняемых скриптов. Сосредоточьтесь на правильном выборе «#!/Bin/bash» или «#!/Bin/sh» в первой строке. Команды не должны выставлять свой язык реализации в имени команды, чтобы не переходить на другой язык позже, когда язык реализации изменяется, но другой код пришел к исходному, теперь некорректному расширению.