Linux
為什麼重定向輸出時’ping’不輸出摘要?
我可以 ping google.com幾秒鐘,當我按
Ctrl
+C
時,底部會顯示一個簡短的摘要:$ ping google.com PING google.com (74.125.131.113) 56(84) bytes of data. 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=2 ttl=56 time=46.7 ms 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=3 ttl=56 time=45.0 ms 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=4 ttl=56 time=54.5 ms ^C --- google.com ping statistics --- 4 packets transmitted, 3 received, 25% packet loss, time 3009ms rtt min/avg/max/mdev = 44.965/48.719/54.524/4.163 ms
但是,當我使用 將相同的重定向輸出重定向到日誌文件時
tee
,不會顯示摘要:$ ping google.com | tee log PING google.com (74.125.131.113) 56(84) bytes of data. 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=1 ttl=56 time=34.1 ms 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=2 ttl=56 time=57.0 ms 64 bytes from lu-in-f113.1e100.net (74.125.131.113): icmp_seq=3 ttl=57 time=50.9 ms ^C
使用 重定向輸出時,我也可以獲得摘要
tee
嗎?
事實證明,有一個選項可以忽略按下+
tee
時發送的中斷信號。來自man tee:CTRL``C
-i, --ignore-interrupts ignore interrupt signals
當整個管道被 中斷時
SIGINT
,該信號被發送到管道中的所有程序。問題是tee
通常是SIGINT
先接收ping
然後ping
用SIGPIPE
. 如果SIGINT
在 中被忽略tee
,它只會被傳遞到ping
並顯示摘要:$ ping google.com | tee --ignore-interrupts log PING google.com (142.250.150.101) 56(84) bytes of data. 64 bytes from la-in-f101.1e100.net (142.250.150.101): icmp_seq=1 ttl=104 time=48.8 ms 64 bytes from la-in-f101.1e100.net (142.250.150.101): icmp_seq=2 ttl=104 time=51.0 ms 64 bytes from la-in-f101.1e100.net (142.250.150.101): icmp_seq=3 ttl=107 time=32.2 ms ^C --- google.com ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 32.198/44.005/50.973/8.394 ms
因此
ping
接收SIGINT
最終將終止,導致tee
看到管道編寫器已經死亡,最終也導致tee
終止(在到目前為止“消化”輸入之後)。
ping
當它被 殺死時顯示摘要SIGINT
,例如作為 的結果Ctrl``C
,或者當它已經傳輸了請求數量的數據包(-c
選項)。Ctrl``C
導致SIGINT
被發送到前台程序組中的所有程序,即在這種情況下,管道中的所有程序(ping
和tee
)。tee
沒有捕捉SIGINT
到(在 Linux 上,查看SigCgt
in/proc/$(pgrep tee)/status
),所以當它接收到信號時,它會死掉,關閉管道的末端。接下來發生的是一場比賽:如果ping
仍在輸出,它將SIGPIPE
在獲得SIGINT
;之前死亡。如果它SIGINT
在輸出任何東西之前得到了,它會嘗試輸出它的摘要並死掉SIGPIPE
. 在任何情況下,輸出都無處可去。要獲得摘要,請安排僅
ping
使用以下命令殺死SIGINT
:killall -INT ping
或使用預定數量的數據包執行它:
ping -c 20 google.com | tee log
或(將最好的保留在最後),如您所見,
tee
忽略。SIGINT