아래와 같이 LCD 화면에 쓰는 시스템 서비스가 있습니다.
[Unit]
Description=LCD Screen
[Service]
Type=simple
User=admin
WorkingDirectory=/lcd
ExecStart=sudo /run_lcd.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=lcd-service
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
LCD가 컴퓨터에 연결되어 있을 때만 서비스가 실행되기를 원합니다. 패널은 직렬 포트를 통해 연결되어 있으므로 이를 알 수 있는 유일한 방법은 특정 메시지를 LCD 화면에 보내는 것입니다. 이 메시지는 연결되면 값을 반환합니다. 이것을 스크립트에서 실행하는 경우 스크립트의 출력을 얻고 그 출력에 따라 서비스를 실행하는 방법이 있습니까?
나는 본 적이systemd의 조건 및 주장하지만 내가 원하는 것을 할 수 있는 옵션은 표시되지 않습니다. 어떤 도움이라도 대단히 감사하겠습니다.
답변1
Edgar의 답변은 ExecStartPre=
나쁘지 않지만 실행이 차단되면 ExecStart=
서비스에 플래그가 지정됩니다 failed
.
당신은 또한 그것을 시도할 수 있습니다 ExecCondition=
. 이 동작은 ExecStartPre=
및 의 Condition*=
혼합 과 같습니다 .
종료 코드 | 행동 |
---|---|
0 | 장치가 계속 시작됩니다. |
1-254 | 시작은 포기되고 유닛은 계속된다inactive (dead) |
255 | 버려지기 시작하고 유닛은failed |
간단한 예는 다음과 같습니다.
$ cat condition.service
[Service]
ExecCondition=/bin/false
ExecStart=/bin/sleep 20
$ systemctl --user start condition.service
$ systemctl --user status condition.service
● condition.service
Loaded: loaded
Active: inactive (dead)
Starting condition.service...
condition.service: Control process exited, code=exited, status=1/FAILURE
condition.service: Skipped due to 'exec-condition'.
당신은 restart=always
질문을 제기합니다. 부팅이 비활성화 되면 ExecCondition=
다시 시도합니다...영원히...( RestartSec=
부팅 제한에 도달하는 것을 방지) 이것은 당신이 원하는 것이 아닐 수도 있습니다.
restart=on-failure
귀하의 서비스가 반환되면 EXIT_SUCCESS
아마도 해당 작업이 완료된 것이므로 해당 작업을 다시 요청할 필요가 없을 것입니다 . 그러나 return EXIT_FAILURE;
오류가 발생하면 언제든지 다시 시작할 수 있습니다. ExecCondition=
이것을 가능하게 만드십시오.
를 사용하면 ExecStartPre=
스크립트가 서비스를 비활성화하려고 시도하면 서비스가 실패하고 종료됩니다. 이는 restart=on-failure
귀하가 사용할 수 없으며 유일한 옵션 restart=on-success
일 수 있음을 의미합니다 .restart=no
기타 팁:
User=admin
sudo
스크립트에서 사용하고 있습니다 . 이는NOPASSWD:
sudoeradmin
에 의존할 뿐만 아니라root
. 이 스크립트를 실행하기 위해 루트 권한이 필요한 경우 서비스를 루트로 직접 실행하고 이 줄을 제거하십시오.
ExecStart=sudo /run_lcd.py
run_lcd.py
일반적으로 에 설치하면 안 됩니다/
. 직접 작성한(또는 수동으로 설치한) 스크립트라면 에 넣으세요/usr/local/bin
. 이와 같은 조직은 새 서버를 다시 만들 때 "모든 로컬 콘텐츠"를 찾는 데 정말 도움이 될 수 있습니다. 하드웨어.
Type=simple
- 명시적으로 표현해도 나쁠 것이 없다고 생각하지만 이것이 기본값입니다
Type=
. 파일이 복잡해지기 때문에 이것을 추가하지 않겠습니다.
- 명시적으로 표현해도 나쁠 것이 없다고 생각하지만 이것이 기본값입니다
Standard{Output,Error}=syslog
- 이
syslog
옵션은 systemd에서 제거되었습니다. 여전히 이전 버전과 호환될 수 있지만 다음에서 제거되었습니다.문서. 기본 로그를 사용하려면 이 줄을 제거하십시오(필요에 따라 전달됨). 문서(Debian Buster 확인)에서는 다음과 같이 말했습니다.
시스템 로그로깅 외에도 표준 출력은 syslog(3) 시스템 syslog 서비스에 연결됩니다. 로깅 데몬은 일반적으로 수신한 모든 것을 syslog로 전달하도록 구성되며, 이 경우 이 옵션은 로깅과 다르지 않습니다.
- 이
RestartSec=10
- 이것은 사람들이 재시작 제한에 도달하는 것을 피하기 위해 사용하는 트릭입니다.
multi-user.target
시작 후 그래픽 응용 프로그램을 시작하는 사람들에게 특히 유용합니다 . 더 나은 해결책은 리소스가 준비된 후에만 장치를 시작하는 것입니다. 일반적으로 사용하는 것이WantedBy=graphical.target
올바른 해결책입니다.After=graphical.target
또한 모든 것이 준비될 때까지 서비스가 시작되지 않도록 합니다. 귀하의 서비스는 그래픽과 관련된 것으로 보이므로 이러한 내용이 도움이 될 것으로 생각됩니다. 그럼에도 불구하고 마침내 잘 작동하는 서비스를 갖게 되면RestartSet=
그럴 필요가 없습니다.
- 이것은 사람들이 재시작 제한에 도달하는 것을 피하기 위해 사용하는 트릭입니다.
그것을 합치려면 다음을 사용합니다.
[Unit]
Description=LCD Screen
After=graphical.target
[Service]
WorkingDirectory=/lcd
ExecCondition=/usr/bin/python3 /usr/local/bin/checkScreen.py
ExecStart=/usr/local/bin/run_lcd.py
SyslogIdentifier=lcd-service
Restart=on-failure
[Install]
WantedBy=graphical.target
답변2
@Panki가 말했듯이 Restart=always
로 변경해야 합니다 .Restart=on-success
ExecStartPre
따라서 다른 스크립트(Python으로 가정)를 사용하여 화면이 연결되어 있는지 확인하는 것이 좋습니다. 예를 들어 간단한 Python 스크립트는 다음과 같습니다.
/checkScreen.py
#you will have to add before this lines the code
#used for getting the status of screen
if screenIsConnected:
exit(0)
else:
exit(1)
귀하의 시스템 서비스는 다음과 같습니다:
[Unit]
Description=LCD Screen
[Service]
Type=simple
User=admin
WorkingDirectory=/lcd
ExecStartPre=/usr/bin/python3 /checkScreen.py
ExecStart=sudo /run_lcd.py
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=lcd-service
Restart=on-success
RestartSec=10
[Install]
WantedBy=multi-user.target