unix 为什么当我通过bash函数传输命令exit log时没有显示它呢?

vcirk6k6  于 2022-11-04  发布在  Unix
关注(0)|答案(3)|浏览(140)

我想创建一个并行运行多个命令的脚本。我想让它在我使用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,却没有呢?

zpf6vheq

zpf6vheq1#

您在向ping发送SIGINT的同时向sed发送SIGINT。sed在看到ping的最终消息之前就已终止。
一个简单的解决方法是使用可以忽略SIGINT的sed版本。例如:

perl -p -e 'BEGIN{$SIG{INT}="IGNORE";} s/^/['"$1]: /"

至于@EdMorton提出的那些精彩的问题,我只想说shell中的信号处理(通常在Unix中)是变化无常的,其行为在很大程度上取决于事件的顺序。

qacovj5a

qacovj5a2#

看起来除了@WilliamPursell的观点,您可以在中断ping过程的同时中断sed过程,您还需要在将命令放在后台时对它们进行分组:

$ 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

为什么这是必要的,为什么当管道连接到一个函数时会出现这种差异,而当管道直接连接到sed时却不会出现这种差异--我可以猜到,但我宁愿有一个知道的人告诉我们这一点。

blpfk2vs

blpfk2vs3#

强制GNU Parallel忽略SIGINT,这样它将接收来自即将终止的ping s的输入:

$ parallel -o --lb --tag ping {='$SIG{INT}=sub {}'=} ::: 1.1.1.1 8.8.8.8 9.9.9.9

1.1.1.1 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
1.1.1.1 64 bytes from 1.1.1.1: icmp_seq=1 ttl=57 time=11.6 ms
8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
8.8.8.8 64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=19.0 ms
9.9.9.9 PING 9.9.9.9 (9.9.9.9) 56(84) bytes of data.
9.9.9.9 64 bytes from 9.9.9.9: icmp_seq=1 ttl=57 time=18.2 ms
9.9.9.9 64 bytes from 9.9.9.9: icmp_seq=2 ttl=57 time=38.4 ms
1.1.1.1 64 bytes from 1.1.1.1: icmp_seq=2 ttl=57 time=38.1 ms
8.8.8.8 64 bytes from 8.8.8.8: icmp_seq=2 ttl=117 time=43.3 ms
9.9.9.9 64 bytes from 9.9.9.9: icmp_seq=3 ttl=57 time=18.5 ms
1.1.1.1 64 bytes from 1.1.1.1: icmp_seq=3 ttl=57 time=12.2 ms
8.8.8.8 64 bytes from 8.8.8.8: icmp_seq=3 ttl=117 time=19.2 ms
9.9.9.9 64 bytes from 9.9.9.9: icmp_seq=4 ttl=57 time=36.6 ms
1.1.1.1 64 bytes from 1.1.1.1: icmp_seq=4 ttl=57 time=3.19 ms
8.8.8.8 64 bytes from 8.8.8.8: icmp_seq=4 ttl=117 time=19.1 ms
^C
9.9.9.9
9.9.9.9 --- 9.9.9.9 ping statistics ---
9.9.9.9 5 packets transmitted, 4 received, 20% packet loss, time 4005ms
9.9.9.9 rtt min/avg/max/mdev = 18.166/27.903/38.404/9.611 ms
1.1.1.1 64 bytes from 1.1.1.1: icmp_seq=5 ttl=57 time=10.1 ms
1.1.1.1
1.1.1.1 --- 1.1.1.1 ping statistics ---
1.1.1.1 5 packets transmitted, 5 received, 0% packet loss, time 4004ms
1.1.1.1 rtt min/avg/max/mdev = 3.189/15.042/38.147/11.991 ms
8.8.8.8
8.8.8.8 --- 8.8.8.8 ping statistics ---
8.8.8.8 5 packets transmitted, 4 received, 20% packet loss, time 4003ms
8.8.8.8 rtt min/avg/max/mdev = 18.992/25.157/43.299/10.474 ms

或者:

$ parallel -o --lb --tagstring '[{}_log]:' ping {='$SIG{INT}=sub {}'=} ::: 1.1.1.1 8.8.8.8 9.9.9.9

-o是在版本20220522中引入的。

相关问题