I want to ping a remote system, and have the date show up in my output, and then feed it along the pipeline to another program. I used cat
in my examples below only to be a simple example.
I can use the -D
option of the ping command to include the unix timestamp, and I can use a quick perl command to convert that timestamp into a readable time. But if I use perl to give me a easy to read time, it is somehow breaking the pipe, and the command I am sending the results to doesn't get anything. When I use set -x
and run the broken command perl seems to run first for some reason, but I don't understand why.
Broken
testip=8.8.8.8
echo trace $testip
ping -W 1 -D -i 5 -t 3 -n $testip |
perl -p -e 's/^\[([0-9.]+)\]/"[".localtime($1)."]"/e' |
cat
# No output
# Output with set -x
+ perl -p -e 's/^\[([0-9.]+)\]/"[".localtime($1)."]"/e'
+ ping -W 1 -D -i 5 -t 3 -n 8.8.8.8
+ cat
But these work?
# working ping piping into cat
testip=8.8.8.8
echo trace $testip
ping -W 1 -D -i 5 -t 3 -n $testip |
cat
# Output
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
[1494968389.152046] From 169.204.238.1 icmp_seq=1 Time to live exceeded
[1494968394.156976] From 169.204.238.1 icmp_seq=2 Time to live exceeded
# working ping with perl fixing the time
testip=8.8.8.8
echo trace $testip
ping -W 1 -D -i 5 -t 3 -n $testip |
perl -p -e 's/^\[([0-9.]+)\]/"[".localtime($1)."]"/e'
# Output
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
[Tue May 16 14:02:02 2017] From 169.204.238.1 icmp_seq=1 Time to live exceeded
[Tue May 16 14:02:07 2017] From 169.204.238.1 icmp_seq=2 Time to live exceeded
ping -c 2
so it doesn't go on indefinitely. See this question about the issue in general and this question for Perl.$| = 1;
– ilkkachu May 16 '17 at 21:27$| = 1
to make Perl flush the output after every write. See the perlvar man page.unbuffer
in particular seems a bit of a heavy hammer. – ilkkachu May 17 '17 at 10:07$| = 1
to work right for some reason in my quick testing, but theunbuffer
worked right way. – Zoredache May 17 '17 at 17:56