2013-12-13 4 views
5

Для следующего Баша заявления:Выход из трубы в Баше

tail -Fn0 /tmp/report | while [ 1 ]; do echo "pre"; exit; echo "past"; done 

я получил «пред», но не вышел на Баш строку, а затем, если я что-то вход в/TMP/отчет, я мог бы бросить из этого скрипта и войдите в подсказку bash.

Я думаю, что это разумно. «exit» делает вывод «while» завершенным, но «хвост» все еще жив. Если что-то вводится в /tmp/report, «хвост» будет выводиться на канал, тогда «хвост» обнаружит, что труба закрыта, а затем «хвост» завершает работу.

  1. Я прав? Если нет, кто-нибудь обеспечит правильную интерпретацию?
  2. Можно ли добавить что-либо в оператор «while», чтобы сразу выйти из всего заявления о трубе? Я знаю, что могу сохранить pid хвоста во временный файл, а затем прочитать этот файл в «while», а затем убить хвост. Есть ли более простой способ?
  3. Позвольте мне расширить свой вопрос. Если использовать этот хвост в файле сценария, можно ли одновременно выполнять следующие пункты? a. Если вводится Ctrl-C или сигнализируется основной процесс оболочки, основная оболочка и различные подоболочки и фоновые процессы, порожденные основной оболочкой, завершатся b. Я мог бы выйти из хвоста, пока только в случае триггера, и сохранить другие подпроцессы, продолжая работать c. Лучше не использовать временный файл или файл трубы.
+0

Возможный дубликат [Невозможно завершить оболочку с помощью Ctrl + c] (http://stackoverflow.com/questions/20533745/cannot-terminate-a-shell-with-ctrlc) – shellter

ответ

1

Вы можете (недостоверно) уйти с убийства группы процессов:

tail -Fn0 /tmp/report | while : 
do 
    echo "pre" 
    sh -c 'PGID=$(ps -o pgid= $$ | tr -d \ ); kill -TERM -$PGID' 
    echo "past" 
done 

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

#!/bin/sh 

# In Posix shells that support the User Portability Utilities option 
# this includes bash & ksh), executing "set -m" turns on job control. 
# Background processes run in a separate process group. If the shell 
# is interactive, a line containing their exit status is printed to 
# stderr upon their completion. 
set -m 
tail -Fn0 /tmp/report | while : 
do 
    echo "pre" 
    sh -c 'PGID=$(ps -o pgid= $$ | tr -d \ ); kill -TERM -$PGID' 
    echo "past" 
done & 
wait 

Следует заметить, что я заменил while [ 1 ] с while : потому что while [ 1 ] плохой стиль. (Он ведет себя точно так же, как while [ 0 ]).

+0

Как я и проверял, набор -m является значительным, в то время как фоновый или нет, кажется одинаковым, как в ситуации, так и в хвосте, и все в одной новой группе процессов. Не могли бы вы подробнее рассказать об этом? –

+0

Стандарт требует, чтобы фоновые конвейеры запускались как отдельная группа процессов, если управление заданием включено. Хотя оболочка может запускать группу переднего плана в качестве другой группы процессов, она не требуется. –

3

Вы правы. Цикл while выполняется в подоболочке, потому что его ввод перенаправлен, и exit просто выходит из этой подоболочки.

Если вы используете bash 4.x, возможно, вы сможете достичь того, чего хотите, с помощью сопроцесса.

coproc TAIL { tail -Fn0 /tmp/report.txt ;} 
while [ 1 ] 
do 
    echo "pre" 
    break 
    echo "past" 
done <&${TAIL[0]} 
kill $TAIL_PID 

http://www.gnu.org/software/bash/manual/html_node/Coprocesses.html

В старых версиях, вы можете использовать запись фонового процесса в именованный канал:

pipe=/tmp/tail.$$ 
mkfifo $pipe 
tail -Fn0 /tmp/report.txt >$pipe & 
TAIL_PID=$! 
while [ 1 ] 
do 
    echo "pre" 
    break 
    echo "past" 
done <$pipe 
kill $TAIL_PID 
rm $pipe 
+0

Спасибо за помощь! Теперь мои знания растут. Ну, мой баш - 3.2.5. Возможно, ваш лучший, в то время как я все еще ожидаю других. –

+0

Вы можете эмулировать сопроцесс, используя фоновый процесс, записывающий именованный канал. – Barmar

+0

Добавлено решение с использованием именованного канала. – Barmar

Смежные вопросы