ネットワーク接続を切断したときにスクリプトを終了する

ネットワーク接続を切断したときにスクリプトを終了する

私はRaspberry Piを使ってeth0を介してセンサーのデータを記録したいと思います。私のコード(そして約100のバリエーションのsigterms、kills、exitなど)を実行すると、コレクションを切り離してもコレクションが消えず、私のファイルが更新されません。以下は私のコードの(ほとんど)現在の反復です。

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

答え1

ファイルをフラッシュしてスクリプトを終了するためのシグナルで切断を正常に使用する方法を知っている人はいますか?

まず、この機能はeth_activeインターフェイスリンクが接続されているかどうかを正しく識別しません。簡単なコードを実行してこれをテストできます。

iface=enxb827eb315364    # Interface name
while sleep 3; do date; ip link show "$iface" up; echo SS=$?; echo; done

終了ステータスは次のように表示されますSS=…。イーサネット接続に関係なく、常に0( "ok")を返すことがわかります。

Tue 10 Oct 09:52:41 BST 2023
2: enxb827eb315364: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff
SS=0

Tue 10 Oct 09:52:44 BST 2023
2: enxb827eb315364: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff
SS=0

[…]

Tue 10 Oct 09:52:53 BST 2023
2: enxb827eb315364: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether b8:27:eb:31:53:64 brd ff:ff:ff:ff:ff:ff
SS=0

それでは、この問題を解決してみましょう。

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

関数の戻り値は状態(0 =テキスト一致成功)から派生する可能性があるため、明示的な値を返すgrep必要はありません。if … then

次に、これを確認するにはループが必要です。それ以外の場合は、プログラムは単に上から下に実行され、dumpcap子プロセスで始まり、終了します。

問題の説明に実装したいロジックを理解できないので、ループの作成方法を説明するためにここで簡単にしました。これはコードを置き換えるのではなく、自分で書く方法を理解するのに役立ちます。

# Set the interface name
iface=eth0

# Start the packet capture
dumpcap -i "$iface" -P -w "$(date +'%Y-%m-%d_%H%M').pcap" &
pid=$!  

# Do nothing until either the network cable is pulled or dumpcap dies
while eth_active "$iface" && kill -0 "$pid" 2>/dev/null
do
    sleep 3
done

# Kill dumpcap if it's still around
kill "$pid" 2>/dev/null && ( sleep 3; kill -KILL "$pid" 2>/dev/null ) &

kill -9最初は()を使わずにSIGKILLデフォルト値ですSIGTERMSIGKILLこれは通常、ターゲットプロセスがクリーンアップする機会を許可しないため、悪い選択です。プロセスを終了する一般的な方法ではなく、間違いと見なされます。このdumpcap場合、SIGTERM終了するように指示します。さらに重要なのは、未解決の出力をキャプチャファイルにフラッシュすることです。しかし、ねじれを防ぐために3秒ほど待ってから大きなハンマーで叩きます。それが消えるとエラーが発生しますkillが、ここでは問題ではありません。

答え2

次のように試すことができます(テストされていません)。

if eth_active; then
    # Ethernet active, execute the command
    dumpcap -i eth0 -P -w "$dt.pcap" &
    pid=$!

else
    # Ethernet interface is severed, exit the script
    echo "Not getting data"
    blink
    exit 0
fi

## run until eth_active is false
while eth_active; do
    echo "working"
    sleep 2
done

## Only kill the PID if the $pid variable is not empty
[ -n "$pid" ] && kill -9 "$pid"

echo "Ethernet interface is severed. Exiting..."
blink
shutdown -h now

インターフェイスが動作しているかどうかをテストし、その場合はコマンドを開始してから2秒ごとにインターフェイスを再テストし、残りのスクリプトを続行します。インターフェイスが停止している場合は、マシンをシャットダウンします。

しかし、私はあなたが望むロジックをよく理解していません。このスクリプトを実行してもインターフェイスが機能しない場合は、システムがシャットダウンされます。これが欲しいですか?


重要:バラよりクリス・デイビスの答えeth_active()これは、あなたの仕事が期待どおりに機能しないという信号です。

関連情報