我想创建一个并行运行多个命令的脚本。我想让它在我使用CTRL+C时退出所有这些命令
我遇到的问题是,当我将第一个ping命令的输出通过管道传输到bash函数时,它不会打印退出日志,即包含"rtt min/avg/max/mdev = 6.808/6.855/6.906/0.040 ms"
的日志
我怎么才能让这个工作呢?谢谢:)
# !/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
以下是日志:
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$
谢谢你:)
下面是这个问题的一个简单版本:
$ 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
$
上面的两次运行几乎同时被中断。为什么第一个版本直接调用sed,打印ping的最终统计信息,而第二个版本通过函数调用sed,却没有呢?
3条答案
按热度按时间zpf6vheq1#
您在向
ping
发送SIGINT的同时向sed
发送SIGINT。sed
在看到ping
的最终消息之前就已终止。一个简单的解决方法是使用可以忽略SIGINT的
sed
版本。例如:至于@EdMorton提出的那些精彩的问题,我只想说shell中的信号处理(通常在Unix中)是变化无常的,其行为在很大程度上取决于事件的顺序。
qacovj5a2#
看起来除了@WilliamPursell的观点,您可以在中断ping过程的同时中断sed过程,您还需要在将命令放在后台时对它们进行分组:
为什么这是必要的,为什么当管道连接到一个函数时会出现这种差异,而当管道直接连接到sed时却不会出现这种差异--我可以猜到,但我宁愿有一个知道的人告诉我们这一点。
blpfk2vs3#
强制GNU Parallel忽略SIGINT,这样它将接收来自即将终止的
ping
s的输入:或者:
-o
是在版本20220522中引入的。