私は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
デフォルト値ですSIGTERM
。SIGKILL
これは通常、ターゲットプロセスがクリーンアップする機会を許可しないため、悪い選択です。プロセスを終了する一般的な方法ではなく、間違いと見なされます。この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()
これは、あなたの仕事が期待どおりに機能しないという信号です。