[英]Quit from pipe in bash
對於以下bash語句:
tail -Fn0 /tmp/report | while [ 1 ]; do echo "pre"; exit; echo "past"; done
我得到了“pre”,但沒有退出bash提示符,然后如果我在/ tmp / report中輸入內容,我可以退出這個腳本並進入bash提示符。
我認為這是合理的。 'exit'使'while'語句退出,但'tail'仍然活着。 如果輸入到/tmp/report
,'tail'將輸出到pipe,那么'tail'將檢測到管道是否關閉,然后'tail'退出。
你說的沒錯。 while
循環在子shell中執行,因為它的輸入被重定向,而exit
只退出該子shell。
如果你正在運行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
你可以(不可靠)逃脫殺死進程組:
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 [ 1 ]
while :
因為while [ 1 ]
風格很差。 (它的行為與while [ 0 ]
完全相同)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.