Qiu*_*fan 6 bash shell pipe quit
对于以下bash语句:
tail -Fn0 /tmp/report | while [ 1 ]; do echo "pre"; exit; echo "past"; done
Run Code Online (Sandbox Code Playgroud)
我得到了"pre",但没有退出bash提示符,然后如果我在/ tmp/report中输入内容,我可以退出这个脚本并进入bash提示符.
我认为这是合理的.'exit'使'while'语句退出,但'tail'仍然活着.如果输入的内容/tmp/report
,'tail'将输出到管道,那么'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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
您可以(不可靠地)杀死进程组:
tail -Fn0 /tmp/report | while :
do
echo "pre"
sh -c 'PGID=$( ps -o pgid= $$ | tr -d \ ); kill -TERM -$PGID'
echo "past"
done
Run Code Online (Sandbox Code Playgroud)
这可能会将信号发送到比您想要的更多的进程。如果您在交互式终端中运行上述命令,应该没问题,但在脚本中,进程组完全有可能(确实有可能)包含运行该命令的脚本。为了避免发送信号,明智的做法是启用监视并在后台运行管道,以确保为管道形成新的进程组:
#!/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
Run Code Online (Sandbox Code Playgroud)
请注意,我已将 替换while [ 1 ]
为while :
因为while [ 1 ]
样式很差。(它的行为与 完全相同while [ 0 ]
)。
归档时间: |
|
查看次数: |
3674 次 |
最近记录: |