저는 최근에 네트워크 가동 시간을 테스트할 수 있는 Ubuntu LTS 서버에 서비스를 만들었습니다. 스크립트 자체는 예상대로 작동하지만 이를 서비스로 전환하려고 할 때 몇 가지 문제가 발생하면 서비스가 시작되자마자 (stop 명령을 통해) 자체적으로 중지됩니다.
제어 파일:
#!/bin/bash
case "$1" in
start)
/home/user/network_script/network_script.sh &
echo $!>/var/run/network_script.pid
;;
stop)
kill `cat /var/run/network_script.pid`
rm /var/log/network_output.status
rm /var/run/network_script.pid
;;
restart)
$0 stop
$0 start
;;
status)
if [ -e /var/run/network_script.pid ]; then
echo network_script.sh is running, pid=`cat /var/run/network_script.pid`
echo /var/log/network_script.status
else
echo network_script.sh is NOT running
exit 1
fi
;;
*)
echo "Usage: $0 {start|stop|status|restart}"
esac
exit 0
시스템 파일:
[Unit]
Description=Network Script
[Service]
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status
[Install]
WantedBy=multi-user.target
상태 출력:
network_script.service - Network Script
Loaded: loaded (/etc/systemd/system/network_script.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Tue 2023-01-03 14:07:46 EST; 8s ago
Process: 25131 ExecStart=/home/user/network_script/network_script_controls.sh start (code=exited, status=0/S>
Process: 25133 ExecStop=/home/user/network_script/network_script_controls.sh stop (code=exited, status=0/SUC>
Main PID: 25131 (code=exited, status=0/SUCCESS)
CPU: 9ms
Jan 03 14:07:46 greengoblin systemd[1]: Started Network Script.
Jan 03 14:07:46 greengoblin network_script_controls.sh[25136]: rm: cannot remove '/var/log/network_output.status>
Jan 03 14:07:46 greengoblin systemd[1]: network_script.service: Deactivated successfully.
답변1
Type=forking
섹션 에 추가하세요 [Service]
. ,
~에서매뉴얼 페이지:
분기로 설정된 경우 ExecStart=로 구성된 프로세스는 시작의 일부로 분기()를 호출해야 합니다. 시작이 완료되고 모든 통신 채널이 설정되면 상위 프로세스가 종료될 것으로 예상됩니다. 하위 프로세스는 계속해서 기본 서비스 프로세스로 실행되며, 상위 프로세스가 종료되면 서비스 관리자는 해당 유닛이 시작된 것으로 간주합니다. 이는 기존 UNIX 서비스의 동작입니다. 이 설정을 사용하는 경우 systemd가 서비스의 기본 프로세스를 안정적으로 식별할 수 있도록 PIDFile= 옵션도 사용하는 것이 좋습니다. 상위 프로세스가 종료되면 systemd는 계속해서 후속 유닛을 시작합니다.
또한 프로세스가 아직 실행 중인지 또는 충돌이 발생했는지 확인할 수 있도록 systemd에 PID 파일을 알려주는 것이 좋습니다.
매뉴얼 페이지에는 다음과 같이 나와 있습니다 PIDFile=
.
서비스를 참조하는 PID 파일의 경로를 사용합니다. 이 옵션은 Type=이 분기로 설정된 서비스에 권장됩니다. 지정된 경로는 일반적으로 /run/ 아래의 파일을 가리킵니다. 상대 경로를 지정하면 앞에 /run/이 붙습니다. 서비스가 시작된 후 서비스 관리자는 이 파일에서 서비스 기본 프로세스의 PID를 읽습니다. 서비스 관리자는 여기에 구성된 파일에 쓰지 않지만 파일이 여전히 존재하는 경우 서비스가 종료된 후 파일을 삭제합니다. PID 파일은 권한이 있는 사용자가 소유할 필요는 없지만 권한이 없는 사용자가 소유한 경우 추가 보안 제한이 적용됩니다. 파일은 소유한 파일에 대한 심볼릭 링크(직접 또는 간접적)가 될 수 없습니다. 다른 사용자의 PID 파일과 이미 해당 서비스에 속한 프로세스를 참조해야 합니다.
최신 프로젝트에서는 PID 파일을 피해야 합니다. 서비스의 주요 프로세스를 결정하고 불필요한 포크를 피하기 위해 PID 파일을 사용할 필요가 없도록 가능하면 Type=notify 또는 Type=simple을 사용하십시오.
이는 귀하의 서비스가 다음과 같아야 함을 의미합니다.
[Service]
Type=forking
PIDFile=/var/run/network_script.pid
ExecStart=/home/user/network_script/network_script_controls.sh start
ExecStop=/home/user/network_script/network_script_controls.sh stop
ExecRestart=/home/user/network_script/network_script_controls.sh restart
ExecStatus=/home/user/network_script/network_script_controls.sh status
즉, 마지막 단락을 자세히 살펴보십시오 PIDFile=
. systemd를 사용하고 있으므로 PID를 직접 추적할 필요는 없습니다. 이렇게 하면 스크립트를 분기할 필요가 없습니다. Systemd는 이 작업을 자동으로 수행합니다.
나는 포기 /home/user/network_script/network_script_controls.sh
하고 이 유닛 파일을 사용할 것입니다:
[Unit]
Description=Network Script
[Service]
Type=simple
ExecStart=/home/user/network_script/network_script.sh
[Install]
WantedBy=multi-user.target