나는 FIFO의 명령을 수신하고 라즈베리 파이에서 디버깅을 위해 몇 가지 파일을 수집하는 스크립트를 작성했습니다.잘 작동내가 시스템 단위 파일을 작성하기로 결정하기 전까지는 말이죠. 실행하면 systemctl start crashcollector
스크립트가 시작되지만 실행 중인 파이프에서 아무 것도 읽지 않지만 아무것도 하지 않고 systemctl stop crashcollector
서비스를 중지하는 데 시간이 오래 걸립니다. 따라서 많은 작업 일반 파일을 작성했음에도 불구하고 내 유닛 파일에 문제가 있는 것으로 추측됩니다.
배시 스크립트:
#!/bin/bash
collectCrashReport() {
# teleport to cache dir
cd /mnt/cache
# remove any previous report
rm -rf crash/crashreport_*
# create report directory
directory=crashreport_`cat /etc/hostname`_$(date +%Y%m%d%H%M%S)
mkdir $directory
cd $directory
# snatch all the logs
cp -r /var/log/ .
ps --no-headers -ax > processes.dump
# dump dmesg to file
dmesg > dmesg.dump
# create crash dir
mkdir crash
# zip the whole thing
zip -qr /mnt/cache/crash/"$directory.zip" .
# remove collection dir
rm -rf /mnt/cache/crashreport_*
# done and done
}
# check if already running and kill
PIDFILE=/var/run/crashcollector.pid
# check if already running
if [ -f $PIDFILE ]; then
kill `cat $PIDFILE`
fi
echo $$ > $PIDFILE
cleanup() {
rm -f $PIDFILE
exit 0
}
# trap them signals
trap "cleanup" INT TERM EXIT
that_awesome_pipe="CCPipe"
[ -p $that_awesome_pipe ] || mkfifo $that_awesome_pipe
chmod 766 $that_awesome_pipe
while :; do
if read line; then
case $line in
"collect")
collectCrashReport
;;
*)
log "Received bad command $line, ignoring..."
;;
esac
fi
done <"$that_awesome_pipe"
시스템 단위 파일:
[Unit]
Description=Crash report collector
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/crashCollector
ExecStop=/usr/bin/kill -9 `cat /var/run/crashcollector.pid`
KillMode=process
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
여기서 정확히 무엇을 놓치고 있는지 잘 모르겠습니다. 해당 if read line
블록을 제거하면 모든 것이 작동했습니다.
답변1
거기에는 많은 문제가 있습니다.
ExecStart
및를ExecStop
쉘 명령줄로 생각하지 마십시오 . 그렇지 않습니다. systemd 매뉴얼은 이에 대해 경고합니다. 명령 대체와 같은 쉘 확장은 다음과 같습니다.아니요이러한 서비스 단위 파일 설정에서 사용할 수 있습니다. 이것은아니요쉘 언어.- 시작하는 실제 서비스 관리자가 있는 경우 PID 파일 메커니즘을 생성하지 마십시오. PID 파일은 1980년대 이후 손상된 메커니즘이므로 적절한 서비스 관리를 통해 PID 파일의 필요성이 완전히 사라졌습니다. 서비스 관리자가 있습니다. 그것언제든지 최대 하나의 서비스 인스턴스가 실행되도록 보장합니다. 그것프로세스 ID가 추적됩니다. 그것서비스가 종료되면 서비스 프로세스에 종료 신호를 보내는 작업이 처리됩니다.
- FIFO 생성 및 서버 측 열기와 같은 기본적인 서버 측 항목을 서버 프로세스에 넣지 마십시오.
이 방법:
- 서비스 유닛과 함께 소켓 유닛을 생성합니다.
- 에서 FIFO의 모든 명시적 처리를 제거합니다
crashCollector
. ListenFIFO
소켓 장치 에 사용됩니다 . 물론 절대 경로 이름이 필요합니다.StandardInput=socket
서비스 단위에 사용됩니다.crashcollector
표준 입력에서만 스크립트를 읽도록 하세요 .- .
crashCollector
- 모든 신호 캡처 및
cleanup()
항목을crashCollector
. - 사용된 명시적인 살인 과 서비스 유닛 외부
ExecStop
에서 수행하려는 후속 조치를 모두 취하십시오.KillMode
StandardError=journal
서비스 단위에 사용됩니다.log
단순 오류에서echo 1>&2
표준 오류로 대체되었습니다 .
추가 읽기
- 조나단 드보인 폴라드(2001). Unix 데몬을 설계할 때 피해야 할 실수. 일반적인 답변.
- Lennart Potlinget al.시스템 소켓. 시스템 매뉴얼 페이지. freedesktop.org.
- FIFO 소켓에서 서비스를 읽는 방법
답변2
fifo를 옮긴 후 모든 것이 수정되었습니다 /tmp
. 무엇이 변경되었는지는 확실하지 않지만 지금은 모든 것이 원활하게 실행되고 있습니다.