일시 중지하기 전에 systemd 서비스를 중지하고 재개 후 다시 시작

Nov 17 2020

내가 원하는 것

일시 중지 / 종료 전에 중지하고 재개 한 후 다시 시작하고 싶은 시스템 서비스가 있습니다.

시스템 세부 정보

아래 시스템 세부 정보.

$ lsb_release -dc
Description:    Ubuntu 20.04.1 LTS
Codename:   focal

$ systemd --version
systemd 245 (245.4-4ubuntu3.3)
+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid

내가 지금까지 가지고있는 것

두 가지 서비스가 myservice-resume.service있으며 myservice-suspend.service각각 일시 중지 및 재개시 Python 프로세스를 시작 및 중지합니다. Python 스크립트는 RGB 조명을 제어하는 ​​SDK 서버에 명령을 실행합니다. on이 인수로 전달되면 (ExecStart에서와 같이), 루프의 일부로 명령을 계속 실행하려면 프로세스를 백그라운드에서 실행해야합니다. 프로세스가 SIGINT 신호를 포착하면 조명이 꺼지고 정상적으로 종료됩니다. 이 설정에서 myservice-suspend.service는 일시 중지 전에 트리거 myservice-resume.service되며 충돌로 인해 중지 됩니다.

myservice-resume.service

[Unit]
Description=Start myservice-resume.service after suspend and shutdown

[Service]
Type=simple
ExecStart=/path/to/python3 /path/to/script.py on

myservice-suspend.service
[Unit]
Description=Stop myservice-resume.service before suspend and shutdown
Before=suspend.target shutdown.target
Conflicts=myservice-resume.service

[Service]
Type=oneshot
ExecStart=/bin/true

[Install]
WantedBy=suspend.target shutdown.target

이 설정에서, 나는 사용하여 서비스 (조명)을 시작 systemctl start myservice-resume.service하고 성공적으로 사용하는 조명 끄기 systemctl start myservice-suspend.service, systemctl stop myservice-resume.service또는 사용 일시 중단 시스템을 수행하여 systemctl suspend. myservice-resume.service시스템 재개시 첫 번째 서비스 인을 (를 ) 자동으로 다시 시작 하고 싶습니다 . [Unit] 및 [Install] 섹션에 영리한 After / Before / WantedBy 대상을 추가하는 것이 포함될 것이라고 생각하지만이를 설정하는 적절한 방법을 결정할 수 없습니다.

조사 / 내가 시도한 것

관련 게시물 ( Systemd : 중지 전 서비스 중지, 다시 시작 후 다시 시작 )은의 단위 섹션 에 추가 하여 일시 중지에서 다시 시작 서비스를 실행하도록 구성 할 수 있음을 암시했습니다 . 나는 이것을 시도했지만 systemctl 로그는 장치가 다시 시작될 때 다시 시작되지 않았 음을 보여줍니다.After=suspend.targetmyservice-resume.service

이 게시물 ( Writing systemd unit file for suspend / resume )은 OP를 systemd man 페이지에 연결하여 해결책을 제시했지만 (After / WantedBy의 목적을 명확히 함) 여기서 해결책을 찾을 수 없었습니다.

답변

meuh Nov 18 2020 at 01:50

After=or에 대한 필요성 Before=은 마침내 archlinux (평소와 같이 놀라운 도움이되는 소스)의 예제에서 볼 수 있습니다 . 해당 링크를 기반으로 일시 중단 및 재개시 명령을 실행하는 두 가지 솔루션이 있습니다.

한 가지 방법은 두 개의 단위 (예 : mysyssuspend및 )를 사용하는 것 mysysresume입니다. 다음 예제 date는 syslog에 대한 명령을 실행하여 활성화 된시기를 확인할 수 있습니다.

/etc/systemd/system/mysyssuspend.service

[Unit]
Before=suspend.target
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/date +'mysyssuspend start %%H:%%M:%%S'
[Install]
WantedBy=suspend.target

/etc/systemd/system/mysysresume.service

[Unit]
After=suspend.target
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/date +'mysysresume start %%H:%%M:%%S'
[Install]
WantedBy=suspend.target

평소 systemctl daemon-reloadsystemctl enable mysyssuspend mysysresume같이 단위 파일을 만든 후 a를 수행 합니다.

첫 번째 장치는 Before일시 중단 대상에 종속되어 있으며 컴퓨터가 일시 중단 상태가되면 실행됩니다. 두 번째 단위는 유사하게 After종속성이 있으며 재개시 실행됩니다.

다른 방법은 모든 명령을 단일 단위에 넣습니다. /etc/systemd/system/mysuspendresume.service

[Unit]
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
StandardOutput=syslog
RemainAfterExit=yes
ExecStart=/bin/date +'mysuspendresume start %%H:%%M:%%S'
ExecStop=/bin/date +'mysuspendresume stop %%H:%%M:%%S'
[Install]
WantedBy=sleep.target

이는에서 작동 StopWhenUnneeded=yes하므로 활성 서비스가 필요하지 않으면 서비스가 중지됩니다. 수면 대상도를 가지고 StopWhenUnneeded있으므로 완료되면 ExecStop유닛 이 실행됩니다 . 은 RemainAfterExit우리 부대는 여전히 후에도, 활성 상태로 볼 수 있도록 필요가 ExecStart완료되었습니다.

시스템 버전 237을 사용하여 Ubuntu 18.04.5에서이 두 가지 방법을 모두 테스트했는데 둘 다 올바르게 작동하는 것 같습니다.


요구 사항을 위의 작동 메커니즘에 병합하려고하는 것보다 그중 하나를 사용하여 독립 장치를 중지 / 시작하는 것이 더 실용적 일 수 있습니다. 예를 들어 두 번째 방법을 사용하고 mylongrun서비스를 추가합니다 .

/etc/systemd/system/mysuspendresume.service

[Unit]
Before=sleep.target
StopWhenUnneeded=yes
[Service]
Type=oneshot
StandardOutput=syslog
RemainAfterExit=yes
ExecStart=-/bin/date +'my1 %%H:%%M:%%S' ; /bin/systemctl stop mylongrun ; /bin/date +'my2 %%H:%%M:%%S'
ExecStop=-/bin/date +'my3 %%H:%%M:%%S' ; /bin/systemctl start mylongrun ; /bin/date +'my4 %%H:%%M:%%S'
[Install]
WantedBy=sleep.target

/etc/systemd/system/mylongrun.service

[Unit]
Description=Long Run
[Service]
Type=simple
StandardOutput=syslog
ExecStart=/bin/bash -c 'date +"my11 %%H:%%M:%%S"; while sleep 2; do date +"my12 %%H:%%M:%%S"; done'
ExecStop=/bin/bash -c 'date +"my13 %%H:%%M:%%S"; sleep 10; date +"my14 %%H:%%M:%%S"'
[Install]
WantedBy=multi-user.target

mylongrun덮개 를 시작 하고 닫아서 테스트 하면 다음과 같은 journalctl 항목이 제공됩니다.

09:29:19 bash[3626]: my12 09:29:19
09:29:21 bash[3626]: my12 09:29:21
09:29:22 systemd-logind[803]: Lid closed.
09:29:22 systemd-logind[803]: Suspending...
09:29:22 date[3709]: my1 09:29:22
09:29:22 systemd[1]: Stopping Long Run...
09:29:22 bash[3715]: my13 09:29:22
09:29:23 bash[3626]: my12 09:29:23
09:29:25 bash[3626]: my12 09:29:25
09:29:27 bash[3626]: my12 09:29:27
09:29:29 bash[3626]: my12 09:29:29
09:29:31 bash[3626]: my12 09:29:31
09:29:32 bash[3715]: my14 09:29:32
09:29:32 systemd[1]: Stopped Long Run.
09:29:32 date[3729]: my2 09:29:32
09:29:32 systemd[1]: Reached target Sleep.
09:29:33 systemd[1]: Starting Suspend...

장기 실행 중지 명령 ( sleep 10)이 올바르게 완료된 것을 볼 수 있습니다 . 재개시 장기 실행 명령이 다시 시작됩니다.

09:35:12 systemd[1]: Stopped target Sleep.
09:35:12 systemd[1]: mysuspendresume.service: Unit not needed anymore. Stopping.
09:35:12 systemd[1]: Reached target Suspend.
09:35:12 date[3813]: my3 09:35:12
09:35:12 systemd[1]: Started Long Run.
09:35:12 date[3817]: my4 09:35:12
09:35:12 bash[3816]: my11 09:35:12
09:35:14 bash[3816]: my12 09:35:14
09:35:16 bash[3816]: my12 09:35:16
09:35:18 bash[3816]: my12 09:35:18