在bash中退出管道

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'退出.

  1. 我对吗?如果没有,有人会提供正确的解释吗?
  2. 是否可以在'while'语句中添加任何内容以立即退出整个管道语句?我知道我可以把尾巴的pid保存到一个临时文件中,然后在'while'中读取这个文件,然后杀掉尾巴.有更简单的方法吗?
  3. 让我扩大我的问题.如果在脚本文件中使用此尾部|是否可以同时执行以下项目?一个.如果输入了Ctrl-C或发出主shell进程的信号,主shell生成的主shell和各种子shell和后台进程将退出b.我可以从尾部退出|仅在触发器情况下,并保留其他子进程继续运行c.最好不要使用临时文件或管道文件.

Bar*_*mar 8

你是对的。该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)


Wil*_*ell 2

您可以(不可靠地)杀死进程组:

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 ])。