나는애플리케이션매일 유지 관리되는 시작 시 데이터베이스에서 읽습니다.별도의 업데이터, systemd
다음 단위로 설명됩니다.
application.service
:
[Unit]
Description=Application reading database
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
[Service]
User=application
Group=application
WorkingDirectory=/var/lib/application
ExecStart=/var/lib/application/application-exec --database /var/db/database.db
StandardOutput=file:/var/lib/application/application.stdout.log
StandardError=file:/var/lib/application/application.stderr.log
StartLimitInterval=60
StartLimitBurst=10
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
updater.service
:
[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/var/lib/updater
ExecStart=/var/lib/updater/updater-exec --database /var/db/database.db
StandardOutput=file:/var/lib/updater/updater.stdout.log
StandardError=file:/var/lib/updater/updater.stderr.log
[Install]
WantedBy=multi-user.target
updater.timer
:
[Unit]
Description=Timer for database updater
[Timer]
OnCalendar=*-*-* 03:00:00
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
내 질문:
어떻게 만들 수 있나요?업데이트 서비스재시작응용 서비스업데이트가 성공적으로 실행되었습니까?(응용 프로그램이 현재 업데이트된 데이터베이스를 다시 읽습니다. 성공/실패는 업데이트 프로그램의 종료 코드로 표시됩니다.)
이 문제존재하다서버 장애비슷하지만 불행히도 내 사용 사례에 적합한 답변이 없습니다.
답변1
해결책은 예상보다 훨씬 간단했습니다. 다음 줄을 추가해야 합니다 updater.service
.
ExecStartPost=+/usr/bin/systemctl restart application.service
결과 updater.service
:
[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/var/lib/updater
ExecStart=/var/lib/updater/updater-exec --database /var/db/database.db
StandardOutput=file:/var/lib/updater/updater.stdout.log
StandardError=file:/var/lib/updater/updater.stderr.log
ExecStartPost=+/usr/bin/systemctl restart application.service
[Install]
WantedBy=multi-user.target
관련 발췌 man 5 systemd.service
:
├───────┼────────────────────────────────────────┤
│"+" │ If the executable path is prefixed │
│ │ with "+" then the process is executed │
│ │ with full privileges. In this mode │
│ │ privilege restrictions configured with │
│ │ User=, Group=, CapabilityBoundingSet= │
│ │ or the various file system namespacing │
│ │ options (such as PrivateDevices=, │
│ │ PrivateTmp=) are not applied to the │
│ │ invoked command line (but still affect │
│ │ any other ExecStart=, ExecStop=, ... │
│ │ lines). │
├───────┼────────────────────────────────────────┤
ExecStartPost= commands are only run after the commands specified in ExecStart= have been invoked
successfully, as determined by Type= (i.e. the process has been started for Type=simple or Type=idle,
the last ExecStart= process exited successfully for Type=oneshot, the initial process exited
successfully for Type=forking, "READY=1" is sent for Type=notify, or the BusName= has been taken for
Type=dbus).
설명하다:
ExecStartPost=
이전 이유로 인해 명령은 루트 권한으로 실행됩니다 ( 첫 번째 발췌 참조+
)application.service
.systemctl
User=
Group=
ExecStartPost=
성공한 경우에만 명령을 실행합니다ExecStart=
(두 번째 발췌 참조). 그러면 조건부 재시작이 허용됩니다.application.service
답변2
이것을 알아내는 것은 재미있었습니다!
세 번째 서비스를 혼합에 추가한 다음 및 사이의 종속성을 다음과 같이 restart-application.service
정렬합니다 .restart-applicationservice
updater.service
restart-application.service
시작 하다updater.service
restart-application.service
updater.service
완료될 때까지 실제로 실행되지 않습니다.restart-application.service
updater.service
성공하지 않으면 실행되지 않습니다.
우리는 restart-application.service
이것을 다음과 같이 만듭니다:
[Unit]
Description=Restart application
BindsTo=updater.service
After=updater.service
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl restart application
우리는BindsTo
여기에 종속성이 있습니다. 문서의 주요 부분은 다음과 같습니다.
BindsTo=의 동작은 동일한 셀에서 After=와 함께 사용될 때 더욱 강력해집니다. 이 경우 엄격하게 바인딩된 유닛이 활성화되어야 하며, 이 유닛도 활성화됩니다.
이제 Unit
부품을 updater.service
다음과 같이 수정합니다.
[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
StopWhenUnneeded=true
그리고 Service
포함할 부분은 다음과 같습니다.
RemainAfterExit=true
이러한 변경은 (a) updater.service
명령이 완료된 후에도 "활성" 상태로 유지된다는 것을 의미합니다. 이는 명령이 활성화된 경우에만 실행되기 ExecStart
때문입니다 . restart-application.service
이 옵션은 StopWhenUnneeded=true
다른 어떤 것도 의존하지 않을 때(즉, 정지되었을 때 ) restart-application.service
장치가 비활성화된다는 것을 의미합니다.
마지막으로 타이머가 restart-application.service
대신 시작되도록 수정해야 합니다 updater.service
.
application.service
나는 (간단한 웹서버를 실행하는) 더미 와 updater.service
무작위로 성공하거나 실패하는 더미를 만들었습니다.
[Unit]
Description=Database updater
Wants=network-online.target
After=local-fs.target network-online.target nss-lookup.target
StopWhenUnneeded=true
[Service]
Type=oneshot
User=updater
Group=updater
WorkingDirectory=/home/updater
ExecStart=/bin/bash -c 'rc=$(( RANDOM % 2 )); echo "rc=$rc"; exit $rc'
RemainAfterExit=true
로그를 살펴보겠습니다 systemctl start restart-application.service
. updater.service
실패하면 어떤 일이 발생합니까 ?
... systemd[1]: Starting updater.service - Database updater...
... bash[1253]: rc=1
... systemd[1]: updater.service: Main process exited, code=exited, status=1/FAILURE
... systemd[1]: updater.service: Failed with result 'exit-code'.
... systemd[1]: Failed to start updater.service - Database updater.
... systemd[1]: Dependency failed for restart-application.service - Restart application.
... systemd[1]: restart-application.service: Job restart-application.service/start failed with result 'dependency'.
updater.service
성공하면 다음이 발생합니다.
... systemd[1]: Starting updater.service - Database updater...
... systemd[1]: Finished updater.service - Database updater.
... darkhttpd[1193]: darkhttpd/1.13, copyright (c) 2003-2021 Emil Mikulic.
... darkhttpd[1193]: listening on: http://0.0.0.0:8080/
... systemd[1]: Starting restart-application.service - Restart application...
... bash[1262]: rc=0
... systemd[1]: Stopping application.service - Application reading database...
... systemd[1]: application.service: Deactivated successfully.
... systemd[1]: Stopped application.service - Application reading database.
... systemd[1]: Started application.service - Application reading database.
... systemd[1]: restart-application.service: Deactivated successfully.
... systemd[1]: Finished restart-application.service - Restart application.
... systemd[1]: updater.service: Deactivated successfully.
... systemd[1]: Stopped updater.service - Database updater.
현재 모든 상황:
# systemctl status application.service updater.service restart-application.service
● application.service - Application reading database
Loaded: loaded (/etc/systemd/system/application.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2022-09-17 20:48:27 UTC; 1min 53s ago
Main PID: 1264 (darkhttpd)
Tasks: 1 (limit: 4661)
Memory: 172.0K
CPU: 1ms
CGroup: /system.slice/application.service
└─ 1264 /usr/sbin/darkhttpd /home/application/htdocs --port 8080
○ updater.service - Database updater
Loaded: loaded (/etc/systemd/system/updater.service; disabled; vendor preset: disabled)
Active: inactive (dead)
○ restart-application.service - Restart application
Loaded: loaded (/etc/systemd/system/restart-application.service; static)
Active: inactive (dead)
나는 이것이 당신이 원하는 모든 것을 할 것이라고 생각합니다.