bash - 当我通过 bash 函数进行管道传输时,为什么不显示命令退出日志?

标签 bash unix pipe

我想创建一个并行运行多个命令的脚本。我希望它在我 git 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)则不会?

最佳答案

您在将 SIGINT 发送到 sed 的同时,也将其发送到 pingsed 在看到 ping 的最终消息之前终止。

一个简单的解决方法是使用可以忽略 SIGINT 的 sed 版本。例如:

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

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

关于bash - 当我通过 bash 函数进行管道传输时,为什么不显示命令退出日志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73089579/

相关文章:

mysql - 在 spring security unix 中,即使详细信息正确,也重定向到authentication-failure-url

c - 需要实现一个pipe,dup2函数来执行 "ls | tr a-z A-Z > file.txt"

c++ - Hadoop管道(wordcount)示例失败(hadoop 0.21.0)

PHP脚本被杀死没有解释

linux - 使用排除从 jar 存档中删除文件

bash - 如何从站点获取 csrf token?

linux - 在制表符后插入文本

bash - Docker cp 与 Unix cp 的工作方式不同的原因是什么?

c - 如何在 C 中正确写入 bash fifo?

bash - 如何在 Mac 上将 $PATH 更改为默认值?