拔掉网络时退出脚本

eyb*_*yid 6 shell-script raspberry-pi

我正在尝试使用 Raspberry Pi 通过 eth0 记录来自传感器的数据。当我运行我的代码(以及 sigterms、kills、exit 等大约 100 个变体)时,集合在拔掉插头后不会消失,并且我的文件不会刷新。这是我的(大部分)代码的当前迭代。

blink是一个我已排除的函数,但它可以工作并且不能以编程方式交互。

有谁知道如何成功地使用断开网络电缆作为信号来刷新文件并终止我的脚本?

#!/bin/bash

# Function to check if the Ethernet interface is active
eth_active() {
    if ip link show eth0 up >/dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}


dt=$(date '+%Y_%m_%d_%H_%M')
umask 0111
touch $dt.pcap

sleep 5

# Main script
if eth_active; then
# Ethernet active, execute the command
    dumpcap -i eth0 -P -w $dt.pcap &
    pid=$!
    if eth_active; then
        echo "working"
        sleep 2
    else
        kill -9 $pid
        echo "Ethernet interface is severed. Exiting..."
        blink
        shutdown -h now
    fi
else
# Ethernet interface is severed, exit the script
    echo "Not getting data"
    blink
    exit 0
fi
Run Code Online (Sandbox Code Playgroud)

roa*_*ima 5

\n

有谁知道我如何成功地使用拔出插头作为信号来刷新文件并终止我的脚本?

\n
\n

首先,该函数eth_active无法正确识别接口链路是否已连接。运行一点代码可以测试这一点:

\n
iface=enxb827eb315364    # Interface name\nwhile sleep 3; do date; ip link show "$iface" up; echo SS=$?; echo; done\n
Run Code Online (Sandbox Code Playgroud)\n

退出状态显示为SS=\xe2\x80\xa6,您将看到它始终返回 0(“ok”),无论以太网连接如何:

\n
Tue 10 Oct 09:52:41 BST 2023\n2: enxb827eb315364: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000\n    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff\nSS=0\n\nTue 10 Oct 09:52:44 BST 2023\n2: enxb827eb315364: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000\n    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff\nSS=0\n\n[\xe2\x80\xa6]\n\nTue 10 Oct 09:52:53 BST 2023\n2: enxb827eb315364: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000\n    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff\nSS=0\n
Run Code Online (Sandbox Code Playgroud)\n

那么让我们解决这个问题:

\n
# Check if the Ethernet interface is active.\n# Usage: eth_active [<interface_name>]\n# Omitting the <interface_name> will default to eth0\n#\neth_active() {\n    ip link show "${1:-eth0}" up 2>&1 | grep -qF "state UP"\n}\n
Run Code Online (Sandbox Code Playgroud)\n

函数的返回值可以从grep状态派生(0=文本匹配成功),因此不需要返回if \xe2\x80\xa6 then显式值。

\n

接下来,您需要一个循环来检查这一点,否则程序将简单地从上到下运行,dumpcap作为子进程启动,然后退出。

\n

我不明白您试图在问题描述中体现的逻辑,因此我在这里进行了简化以说明您如何编写循环。它并不是为了替换您的代码,而是为了帮助您了解如何自己编写代码:

\n
# Set the interface name\niface=eth0\n\n# Start the packet capture\ndumpcap -i "$iface" -P -w "$(date +'%Y-%m-%d_%H%M').pcap" &\npid=$!  \n\n# Do nothing until either the network cable is pulled or dumpcap dies\nwhile eth_active "$iface" && kill -0 "$pid" 2>/dev/null\ndo\n    sleep 3\ndone\n\n# Kill dumpcap if it's still around\nkill "$pid" 2>/dev/null && ( sleep 3; kill -KILL "$pid" 2>/dev/null ) &\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,我们最初并没有使用kill -9( SIGKILL) ,而是使用默认的SIGTERM。通常SIGKILL这是一个糟糕的选择,因为它不允许目标进程有任何清理的机会;将其视为一个大坏锤,而不是终止进程的常规方法。在dumpcap这种情况下,它会SIGTERM告诉它退出 - 更重要的是,将任何未完成的输出刷新到捕获文件中。然而,为了防止它发生扭曲,我们等待三秒钟,然后用大锤子敲击它。如果它已经消失了,那么我们只会收到一个错误kill,但这在这里不是问题。

\n