Linux

為什麼重定向輸出時’ping’不輸出摘要?

  • January 26, 2022

我可以 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 teeCTRL``C

  -i, --ignore-interrupts
         ignore interrupt signals

當整個管道被 中斷時SIGINT,該信號被發送到管道中的所有程序。問題是tee通常是SIGINT先接收ping然後pingSIGPIPE. 如果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被發送到前台程序組中的所有程序,在這種情況下,管道中的所有程序(pingtee)。tee沒有捕捉SIGINT到(在 Linux 上,查看SigCgtin /proc/$(pgrep tee)/status),所以當它接收到信號時,它會死掉,關閉管道的末端。接下來發生的是一場比賽:如果ping仍在輸出,它將SIGPIPE在獲得SIGINT;之前死亡。如果它SIGINT在輸出任何東西之前得到了,它會嘗試輸出它的摘要並死掉SIGPIPE. 在任何情況下,輸出都無處可去。

要獲得摘要,請安排僅ping使用以下命令殺死SIGINT

killall -INT ping

或使用預定數量的數據包執行它:

ping -c 20 google.com | tee log

或(將最好的保留在最後),如您所見tee忽略。SIGINT

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