29

I can ping google.com for several seconds and when I press Ctrl + C, a brief summary is displayed at the bottom:

$ 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

However, when I do the same redirecting output to log file with tee, the summary is not displayed:

$ 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

Can I get the summary as well when redirecting output with tee?

2 Answers 2

60

ping shows the summary when it is killed with SIGINT, e.g. as a result of CtrlC, or when it has transmitted the requested number of packets (the -c option). CtrlC causes SIGINT to be sent to all processes in the foreground process group, i.e. in this scenario all the processes in the pipeline (ping and tee). tee doesn’t catch SIGINT (on Linux, look at SigCgt in /proc/$(pgrep tee)/status), so when it receives the signal, it dies, closing its end of the pipe. What happens next is a race: if ping was still outputting, it will die with SIGPIPE before it gets the SIGINT; if it gets the SIGINT before outputting anything, it will try to output its summary and die with SIGPIPE. In any case, there’s no longer anywhere for the output to go.

To get the summary, arrange to kill only ping with SIGINT:

killall -INT ping

or run it with a pre-determined number of packets:

ping -c 20 google.com | tee log

or (keeping the best for last), have tee ignore SIGINT, as you discovered.

0
28

Turns out that there is an option in tee to ignore interrupt signals which are sent when CTRL+C is pressed. From man tee:

   -i, --ignore-interrupts
          ignore interrupt signals

When whole pipeline is interrupted by SIGINT, this signal is sent to all processes in pipeline. The problem is that tee is usually receiving SIGINT earlier than ping and then killing ping with SIGPIPE. If SIGINT is ignored in tee, it will be delivered only to ping and the summary will be displayed:

$ 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

So ping receiving SIGINT will terminate eventually, causing tee to see the pipe writer had died, eventually causing tee to terminate, too (after having "digested" the input so far).

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.