I want to create a script that runs multiple commands in parallel. I want it to exit all those commands when I git CTRL C
The problem I am having is when I pipe the output of the first ping command to a bash function it does not print the exit logs. i.e. the logs containing "rtt min/avg/max/mdev = 6.808/6.855/6.906/0.040 ms"
How can I get this working? thanks :)
#!/bin/bash
trap terminate SIGINT
terminate(){
echo "terminating started"
pkill -SIGINT -P $$
echo "terminating finished"
exit
}
log () {
sed -e "s/^/[$1]: /"
}
#the rest of your code goes here
ping 1.1.1.1 |& log "first_log" &
ping bbc.com |& sed -e "s/^/[bbc_log]: /"&
wait
Here are the logs:
dewi@pop-os:~/tmp/bashtest$ bash bashtest
[first_log]: PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
[first_log]: 64 bytes from 1.1.1.1: icmp_seq=1 ttl=56 time=9.37 ms
[first_log]: 64 bytes from 1.1.1.1: icmp_seq=2 ttl=56 time=9.31 ms
[bbc_log]: PING bbc.com(2a04:4e42::81 (2a04:4e42::81)) 56 data bytes
[bbc_log]: 64 bytes from 2a04:4e42::81 (2a04:4e42::81): icmp_seq=1 ttl=250 time=7.82 ms
[first_log]: 64 bytes from 1.1.1.1: icmp_seq=3 ttl=56 time=9.42 ms
[bbc_log]: 64 bytes from 2a04:4e42::81 (2a04:4e42::81): icmp_seq=2 ttl=250 time=6.32 ms
[first_log]: 64 bytes from 1.1.1.1: icmp_seq=4 ttl=56 time=9.32 ms
^C[bbc_log]: 64 bytes from 2a04:4e42::81: icmp_seq=3 ttl=250 time=6.66 ms
[bbc_log]:
[bbc_log]: --- bbc.com ping statistics ---
[bbc_log]: 3 packets transmitted, 3 received, 0% packet loss, time 2001ms
[bbc_log]: rtt min/avg/max/mdev = 6.317/6.930/7.816/0.641 ms
terminating started
terminating finished
dewi@pop-os:~/tmp/bashtest$
Mant thanks :)
Edit: here is a simpler version of the problem:
$ cat tst.sh
#!/usr/bin/env bash
log() {
sed 's/^/[log]: /'
}
if [[ $1 == 1 ]]; then
ping 1.1.1.1 2>&1 | sed 's/^/[log]: /' &
else
ping 1.1.1.1 2>&1 | log &
fi
wait
$ ./tst.sh 1
[log]:
[log]: Pinging 1.1.1.1 with 32 bytes of data:
[log]: Reply from 1.1.1.1: bytes=32 time=20ms TTL=55
[log]:
[log]: Ping statistics for 1.1.1.1:
[log]: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
[log]: Approximate round trip times in milli-seconds:
[log]: Minimum = 20ms, Maximum = 20ms, Average = 20ms
[log]: Control-C
$ ./tst.sh 2
[log]:
[log]: Pinging 1.1.1.1 with 32 bytes of data:
[log]: Reply from 1.1.1.1: bytes=32 time=59ms TTL=55
$
Both runs above were interrupted at about the same time. Why does the first version, calling sed directly, print the final stats from the ping while the 2nd version, calling sed through a function, doesn't?
CodePudding user response:
You are sending a SIGINT to sed
at the same time that you are sending it to ping
. The sed
is terminating before it sees ping
's final message.
CodePudding user response:
Looks like in addition to @WilliamPursell's point that you're interrupting your sed process at the same time as you're interrupting your ping process, you also need to group your commands when putting them in the background:
$ cat tst.sh
#!/usr/bin/env bash
log() {
sed 's/^/[log]: /'
}
if [[ $1 == 1 ]]; then
{ ping 1.1.1.1 2>&1 | sed 's/^/[log]: /'; } &
else
{ ping 1.1.1.1 2>&1 | log; } &
fi
wait
$ ./tst.sh 1
[log]:
[log]: Pinging 1.1.1.1 with 32 bytes of data:
[log]: Reply from 1.1.1.1: bytes=32 time=21ms TTL=55
[log]:
[log]: Ping statistics for 1.1.1.1:
[log]: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
[log]: Approximate round trip times in milli-seconds:
[log]: Minimum = 21ms, Maximum = 21ms, Average = 21ms
[log]: Control-C
$ ./tst.sh 2
[log]:
[log]: Pinging 1.1.1.1 with 32 bytes of data:
[log]: Reply from 1.1.1.1: bytes=32 time=29ms TTL=55
[log]:
[log]: Ping statistics for 1.1.1.1:
[log]: Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
[log]: Approximate round trip times in milli-seconds:
[log]: Minimum = 29ms, Maximum = 29ms, Average = 29ms
[log]: Control-C
Why that's necessary and why that difference shows up when piping to a function but not when piping directly to sed - beats me.