Shell-Script

當“輸出”程序退出時終止匿名管道

  • July 8, 2020

所以假設我在 shell 腳本中有這樣的東西

command1 | command2

現在我怎樣才能讓它在退出command2時終止?command1

編輯:

這通常在嘗試從標準輸入讀取並註意到它返回 0 時預設發生command2。你有一些具體的例子,它不這樣做嗎?

幹得好:echo test | xmobar

我想這也可以用作替代xmobar

#!/bin/sh
while :; do :; done

此註釋解釋了當管道的另一端關閉時程序如何終止(或不終止):

關閉管道command1根本不會說明command2任何事情。command2在讀取管道、清空管道並獲得 EOF之前,什麼都不會發生。即使那樣,如果它還有工作要做,它也不必退出。類似地,如果command2先退出,command1直到它寫入管道才發現它,此時它接收到SIGPIPE. 如果它擷取了這一點,它也可以繼續其他工作。

所以這是可以自動發生的。現在你的問題:

command1 | command2

我怎樣才能使它command2在退出時終止command1[即使command2沒有註意到或不想終止]?

如果您的 shell 在單獨的程序組中執行管道,請嘗試終止整個組。例如,當啟用作業控制 ( ) 時,Bash 會執行此操作set -m。預設情況下,互動式 shell(在支持它的系統上)啟用它,但在腳本中不啟用。

範常式式碼:

#!/bin/bash
set -m
( command1; kill -s INT 0 ) | command2

整個管道在一個單獨的程序組中執行,其 PGID(程序組 ID)等於第一部分的 PID,在本例中是一個子外殼。kill 0向自己的程序組發送信號。這樣我們command2就在command1終止後發出信號。

筆記:

  • 在 Bashkill中是內置的,因此kill在範例中不是分配了 PID 和 PGID 的單獨程序。所以上面“它自己的程序組”這句話並不嚴格,應該是“子shell的程序組”。它仍然是我們想要使用的確切程序組。kill內置或/bin/kill可以使用,任何都可以。
  • command2可以改變自己的程序組。如果是這樣,解決方案將不起作用。
  • 因為幾乎所有信號command2都可能忽略信號或以幾乎任何方式處理它。選擇適合您需要的信號。
  • kill在終止後呼叫command1可能為時過早。它可能會導致在讀取和處理由;command2生成的所有數據之前退出。command1您可能希望它處理所有數據。根據行為方式,延遲(例如)command2可能很有用。請注意,(通用)Linux 不是實時作業系統,因此如果情況足夠糟糕,任何固定延遲都可能會變得太短。kill``sleep 2; kill …

引用自:https://unix.stackexchange.com/questions/597287