簡體   English   中英

在bash中退出管道

[英]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'退出。

  1. 我對嗎? 如果沒有,有人會提供正確的解釋嗎?
  2. 是否可以在'while'語句中添加任何內容以立即退出整個管道語句? 我知道我可以把尾巴的pid保存到一個臨時文件中,然后在'while'中讀取這個文件,然后殺掉尾巴。 有更簡單的方法嗎?
  3. 讓我擴大我的問題。 如果在腳本文件中使用此尾部|是否可以同時執行以下項目? 一個。 如果輸入了Ctrl-C或發出主shell進程的信號,主shell生成的主shell和各種子shell和后台進程將退出b。 我可以從尾部退出|僅在觸發器情況下,並保留其他子進程繼續運行c。 最好不要使用臨時文件或管道文件。

你說的沒錯。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM