systemd : Enabled but inactive??

TL;DR

이런 상황에 부딪힌다면, Unit 파일의 Install 항목에 default.target 또는 multi-user.target 을 넣어보라!


얼마 전, 이에 관한 내용을 정리했었다. 최근 서버를 우분투 18.04 에서 20.04 로 바꾸면서, 이 설정을 그대로 옮겼더랬다.

그런데!!!
틀림없이 sudo systemctl enable mpd-pause.service 를 해줬음에도 불구하고, 재부팅해보면 inactive 상태가 나온다.
inactive 라고 해도, 내가 원한 결과가 나온다면 아무 문제가 없겠지만, 그렇지 않으니 짜증이 날 수 밖에.

 sudo systemctl status mpd-pause.service                                                                                                              
● mpd-pause.service - mpd/mpc pause if playing when poweroff
     Loaded: loaded (/etc/systemd/system/mpd-pause.service; enabled; vendor preset: enabled)
     Active: inactive (dead)

정상 상태라면 이렇게 나와야 한다.

☺  sudo systemctl status mpd-pause.service                                                                                                              
● mpd-pause.service - mpd/mpc pause if playing when poweroff
     Loaded: loaded (/etc/systemd/system/mpd-pause.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2020-09-01 21:53:55 KST; 1s ago
    Process: 1513 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
   Main PID: 1513 (code=exited, status=0/SUCCESS)

Sep 01 21:53:55 mpd-server systemd[1]: Starting mpd/mpc pause if playing when poweroff...
Sep 01 21:53:55 mpd-server systemd[1]: Finished mpd/mpc pause if playing when poweroff.

다시 말하면, systemctl start mpd-pause.service 를 해도, 그 때 뿐, 시스템이 재시작되면 저 상태가 유지되지 않는다는 상황인데..

왜 이러는지 근본 원인을 찾아내진 못했지만, 적어도 피해가는 방법은 알아낼 수 있었다. 무려 8시간쯤을 허비했지만, (허비는 좀 미안한 표현인 듯?) 그래도 답을 찾았으니 기쁘긴 하네.

내가 참고한 글 그대로 넣으면 제대로 작동하질 않는다.
그 글의 설정은 이렇다.

[Unit]
Description=Run my custom task at shutdown
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/tmp/startup_script.sh
TimeoutStartSec=0

[Install]
WantedBy=shutdown.target

문제는 [Install] 항목에 있다. 여기서 WantedBy 로 shutdown.target 만이 지정되어 있다. 이렇게만 되면, enable 되어도 재시작된 후 Active 상태가 되진 않는다.

글쓴이의 실수였는지(내 경우는 그야말로 소 뒷걸음질치다가 쥐 잡은 격이었고.. 뒤에 이에 대해 설명한다.), 아니면 그 사람 시스템에선 제대로 작동했는지는 모르겠으나, 적어도 우분투 18.04 / 20.04 에선 저렇게만 해선 되질 않는다.

여기에 default.target 이나 multi-user.target 을 추가해줘야만 시동이 된다.

즉,

[Unit]
Description=Run my custom task at shutdown
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
ExecStart=/tmp/startup_script.sh
TimeoutStartSec=0

[Install]
WantedBy=shutdown.target multi-user.target (또는 default.target)

이렇게 되어야만 한다.

그런데, 왜 난 이전 글에서는 multi-user.target 을 빼고 했는데도 됐다고 당당하게 올렸었을까?

당당한 실수?
[Unit]
Description=mpd/mpc pause if playing when poweroff
Before=poweroff.target halt.target shutdown.target

[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/bin/true
ExecStop=/usr/bin/chk_mpd_is_running

[Install]
WantedBy=poweroff.target halt.target

이렇게만 했는데 됐다고 정리를 해놨는데, 왜 저게 성공을 했을까?

systemctl enable 작업은 해당 Unit 파일을 각각 targets 디렉토리로 링크시켜주는 역할을 한다.
위와 같은 경우, /etc/systemd/system/mpd-pause.service 파일을 아래와 같이 링크시켜준다.

$ sudo systemctl enable mpd-pause.service    
Created symlink /etc/systemd/system/poweroff.target.wants/mpd-pause.service → /etc/systemd/system/mpd-pause.service.
Created symlink /etc/systemd/system/halt.target.wants/mpd-pause.service → /etc/systemd/system/mpd-pause.service.

Systemd 를 그저 수박 겉핥기 식으로밖에 모르지만(그리고 이제 조금 이해가 되기 시작하는 듯 하지만..), 지금와 생각하면 저렇게 때문에 Active 가 되지 않았던 게 아닌가하는 추측을 해볼 수 있겠다.

무슨 말인가 하면, halt.target, poweroff.target 모두, 평상 시에는 활성화되어 있지 않은 서비스다.

$ systemctl list-units --type=target --all
생략..
  halt.target                                                                          loaded    inactive dead   Halt
  multi-user.target                                                                    loaded    active   active Multi-User System
  poweroff.target                                                                      loaded    inactive dead   Power-Off
  reboot.target                                                                        loaded    inactive dead   Reboot
  shutdown.target                                                                      loaded    inactive dead   Shutdown

몇개만 모아봤다. multi-user.target 만 active 이고, 나머지는 모두 inactive 가 되었다.

아마도.. Wantedby poweroff.target 이라 되어 있으면, poweroff.target 이 활성화될 때에 이것도 같이 활성화가 되는 모양인데… 내가 만든 Unit 파일의 종속성등에서 뭔가 문제가 있는 모양인지, Wantedby poweroff.target halt.target 만으로는 제대로 작동하지 않았다. (원랜 작동해야 하는 건지도 모른다.)

8시간 여 여기 저기를 뒤지다가 마지막에, 잘 됐던 우분투 18.04 시스템으로 돌아가보았다. 거기서 뭔가 단서를 찾다가!!! /etc/systemd/system/multi-user.target.wants/mpd-pause.service 이 있음을 발견했다!!!

워낙엔 저 파일(링크)는 있을 수가 없다. Wantedby 로 poweroff.target 과 shutdown.target 만 지정했으므로, 저 디렉토리엔 링크가 없어야만 한다.

그러나, 저 Unit 을 만들면서 이런 저런 꽃삽질을 하던 차에 mult-user.target 쪽에 링크가 걸렸었나보다. 그걸 모른 상태에서 엉뚱한 설정을 해놓고는 성공했다고 좋아했었으니..

다시 시험해본 결과, Install 항목에는 오히려 poweroff.target 과 halt.target 은 없어도 된다. multi-user.target 만 있으면 active 되고, 잘 작동한다. 물론 있어도 작동엔 이상이 없다.

따라서 최종 후보(?)는 이렇게 된다.

[Unit]
Description=mpd/mpc pause if playing when poweroff
After=mpd.service
Conflicts=reboot.target
Before=poweroff.target halt.target shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/usr/bin/chk_mpd_is_running

[Install]
WantedBy=multi-user.target

아직까지는 이게 최종 후보고, 작동에도 이상이 없다.

** 만약, 정말 종료 바로 직전에 실행할 명령이라면 WantedBy 에 poweroff.target(또는 final.target) 이 유용할런지도 모르겠다. 그러나, 내 명령이 실행될 상황은 종료가 시작되고 mpd 가 죽기 전이라는 전제가 있으므로, multi-user.target 이 맞다고 생각한다.

Systemd 를 좀 더 알게되면, 추후에 정리를 더 해보기로..


그런데, 왜 이걸 systemctl start 로 실행했을 땐 Active 상태로 됐을까?
그 때는 WantedBy 에 영향을 받지 않는 건가??
이거.. 확실한 걸 알지는 못하고 그저 실험에 의해 추측을 할 수 밖에 없으니..

그래도, 역시 막힐 때는 ArchLinux Wiki. 역시 이번에도 많은 도움을 받았다.

안녕하세요. 글 남겨주셔서 고맙습니다.