저는 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()
이는 귀하의 작업이 예상대로 작동하지 않는다는 신호입니다 .