root
service/timer/etc/systemd/system/<name>.<timer | service>
로 파일을 만든다.$USER
service/timer$HOME/.config/systemd/user/<name>.<timer | service>
로 파일 만든다.ssh.service
를 살벼 보면서, service 제작법을 본다.ssh.service
의 위치는 /usr/lib/systemd/system/ssh.service
에 있다.Requires
, Wants
를 가진 유닛을 활성화하면, systemd는 첫 번째 유닛과 동시에 이들 모든 종속성들을 활성화한다.ssh.service
와 같이 multi-user.target
다음에 시작되도록 설정된 것도 있다. 이럴 경우는 After
를 사용한다. network.target
, auditd.service
가 실행되어야한다./usr/lib/systemd/system/network.target
After=network-pre.target
/usr/lib/systemd/system/network-pre.target
에 존재하나.Before
에 명시된 Unit '이전에' 실행된다.!/etc/ssh/sshd_not_to_be_run
이 되어 있음!
때문에, 여기에 /etc/ssh/sshd_not_to_be_run
파일이 없어야 실행되는 조건Requires
는 의존 관계(强)Requires
에 설정된 Unit의 목록이 하나라도 시작되지 않으면, 이 Unit은 실행되지 않는다.Requires
에 설정한다.Requires
종속성을 갖게할 시,RequiredBy=B
로 할 것Requires
를 추가할 필요 XWants
는 의존 관계(弱)Wants
는 의존관계는 있지만 설령 서비스가 시작되지 않더라도, 현재 실행되는 Unit 서비스 실행에 영향 XRequires
보다는 약하다.Wants
종속성을 갖게할 시,WantedBy=B
로 할 것Wants
를 추가할 필요 XRequisite
의 유닛의 '상태'를 점검한다.Requisite
의 유닛이 활성화되어 있지 않으면, 현재 유닛을 활성화 XConflicts
의 유닛을 비활성화 시킨다.XXX.service
이므로, [Service] 섹션이 있어야한다.XXX.socket
이라면, [Socket] 섹션이 있어야한다./usr/lib/systemd/system/ssh.service
)의 [Service] 섹션Type 값 | 설명 |
---|---|
simple | Default. 프로세스가 실행할 때 ExecStart에 있는 값이 main 프로세스라는 것 의미 즉, fork 되지 않는다. |
forking | ExecStart에서 시작된 프로세스는 서비스의 주요 프로세스가 되는 하위 프로세스를 생성한다. 부모 프로세스는 시작이 완료되면 종료된다. 즉, 서비스는 fork되고, systemd는 처음 서비스 프로세스가 종료될 것으로 기대한다. 종료가 되자마자 systemd는 해당 서비스가 준비가 된 것으로 추정한다. |
oneshot | simple과 유사하지만, '서비스 프로세스가 멈출 때' 사실상, 그 프로세스는 완전히 종료한다. 이런 Type을 위해, RemainAfterExit=yes 라는 옵션을 두어 프로세스가 종료되더라도 systemd가 여전히 서비스가 활성화된 것으로 간주할 수 있다. |
dbus | simple과 유사하지만, 결과 단위는 main 프로세스가 D-Bus라는 이름을 얻은 후에야 시작 서비스가 준비되면 D-bus(Desktop Bus)에 자신을 등록한다. |
notify | (지연 역할) simple과 유사하지만, 서비스가 준비 되면, sd_notify()함수를 통해 systemd에 맞게 메시지가 통지되고 시작된다. |
idle | simple과 유사하지만, 이진 바이너리의 실제 실행은 모든 프로세스 작업이 끝날 때까지 지연됨으로써, 상태 출력을 서비스의 쉘 출력과 혼용되지 않게 도와준다. 즉, 활성화된 작업이 없을 때까지 systemd가 서비스를 시작하지 않도록 지시하는 것이다. 시스템을 계속 로딩하거나 서비스가 다른 서비스의 출력에 방해하는 일이 없도록 다른 서비스들이 시작할 때까지 서비스의 시작을 지연시키는 개념이다. 한번 서비스가 시작되면 서비스를 시작한 systemd 작업은 종료된다는 점에 유의한다. |
EnvironmentFile=-/etc/default/ssh
가 있다./etc/default/ssh
파일 /etc/init.d/ssh
가 /bin/sh
에 의해 sourced된다.ExecStartPre=/usr/sbin/sshd -t
가 있다.ExecStart=/usr/bin/python /home/pi/bin/myexec.py
[Service]
$ sudo systemctl reload
할 때, 실행하는 것ExecStartPre
에서 지정한 동작을 다시 수행케 하고, $MAINPID
에 HUP
시그널을 보낸다.ssh.service의 경우
systemctl 명령어 참고
service 파일을 수정하면 systemctl restart
systemctl reload
를 해야하기 때문!!!
$ sudo systemctl restart
할 때, 하는 동작Restart=Value | Description |
---|---|
Restart=on-failure | Unit 프로세스가 어떤 문제로 exit != 0으로 종료/중지 될 경우 -> 그 서비스를 다시 시작하라는 의미 |
Restart=on-success | Unit 프로세스가 exit == 0 인 경우 -> 다시 그 서비스 시작하라는 의미 |
[Service]
KillMode=Process
는 주 프로세스만 중지하라는 의미ssh.service의 경우
/usr/lib/systemd/system
의 유닛 파일 /media.mount
를 보면 /media
tmpfs
파일 시스템을 나타낸다.[Unit]
Description=Media Directory
Before=local-fs.target
[Mount]
What=tmpfs
Where=/media
Type=tmpfs
Options=mode=755,nosuid,nodev,noexec
/media.mount
에서 What
은 tmpfs
라고 되어 있는데, 이는 파일 시스템이 아직, 'device file'을 갖고있지 않기 때문이다.$ sudo systemctl enable
, $ sudo systemctl disable
과 관련[Install]
섹션을 무시한다.[Install]
섹션을 읽는다.sshd.service
유닛을 가동하면, systemd는 multi-user.target
의 WantedBy
종속성을 본다./etc/systemd/system
)에서 multi-user.target.wants/sshd/service
경로의 심볼릭 링크를 만든다.$ sudo systemctl enable
명령어로 Unit을 enable할 때, 등록에 필요한 유닛을 지정한다./etc/systemd/system/지명.target.wants
에 들어간다.default.target
WantedBy=
default.targetAlias
에 등록한 이름으로 링크 파일 생성 Xsystemd --user
로 작성된 서비스/타이머를 대상으로 한 것systemd --system
으로 작성한 서비스도 똑같다./etc/systemd/system/rsync_sstate.service
, WantedBy=defulat.target
$ sudo systemctl enable rsync_sstate.service
/etc/systemd/ssytem/default.target.wants
에 rsync_sstate.service 심볼릭 링크 생성됨multi-user.target
ssh.service
의 위치: /usr/lib/systemd/system/ssh.service
ssh.service
에서 [Install] 내용/etc/systemd/system/multi-user.target.wants/
에 ssh.service 소프트링크 생성/etc/systemd/system/
에 systemd
가 알아먹을 수 있게, Alias=sshd.service
대로multi-user.target.wants
내용$ sudo systemctl enable 'alias'
접근 가능[Alias Name].service
$OPTIONS
, $MAINPID
등이 있다.$OPTIONS
: systemctl
로 유닛을 활성화시킬 때, sshd
로 전송할 수 있는 옵션들$MAINPID
: 서비스에 대한 프로세스를 추적한 것%n
: 현재의 유닛 명getty
프로세스 처럼, 한 가지 서비스에 대해 여러 개의 복사본을 생성하기 위해, 하나의 유닛 파일을 매개변수화할 수 있다.@
표시를 넣는다.getty
의 경우, getty@.service
라는 이름의 유닛 파일을 생성한다.getty@tty1
과 getty@tty2
처럼, 유닛들을 참조할 수 있게 해준다.@
다음에 무엇이 오든지 instance로 불린다. 그리고 유닛 파일을 처리할 때, systemd는 %I
specifier를 인스턴스로 확장한다. 이것이 systemd를 실행하는 대부분의 배포판에 포함되어 있는 getty@.service
유닛 파일과 함께 동작하는 것을 볼 수 있다.%H
: 현재의 호스트 명$HOME/workspace/systemd_service/helloworld/helloworld.sh
스크립트 제작# ==== helloworld.sh ==== #
#!/bin/bash
echo "Hello World!"
/etc/systemd/system/exec_helloworld.service
제작$ sudo systemctl exec_helloworld.service
4-1. $ sudo systemctl exec_helloworld.service
로 조희
$ sudo systemctl exec_helloworld.service
● exec_helloworld.service - Simple execute helloworld script service
Loaded: loaded (/etc/systemd/system/exec_helloworld.service; disabled; vendor preset: enabled)
Active: inactive (dead)
7월 23 16:55:22 dhyang systemd[1]: Started Simple execute helloworld script service.
7월 23 16:55:22 dhyang helloworld.sh[1051298]: Hello World!
7월 23 16:55:22 dhyang systemd[1]: exec_helloworld.service: Succeeded.
pid: 1051298
로 helloworld.sh
가 실행되어 Hello World!
를 stdout
으로 출력4-2. $ journalctl -r -u exec_hellowrold.service
로 조희
➜ default.target.wants journalctl -r -u exec_helloworld.service
-- Logs begin at Wed 2021-06-02 16:36:14 KST, end at Fri 2021-07-23 17:35:40 KST. --
7월 23 17:34:54 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:55:23 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:55:22 dhyang systemd[1]: exec_helloworld.service: Succeeded.
7월 23 16:55:22 dhyang helloworld.sh[1051298]: Hello World!
7월 23 16:55:22 dhyang systemd[1]: Started Simple execute helloworld script service.
7월 23 16:55:22 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:55:11 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:55:02 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:54:58 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:53:53 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:53:36 dhyang systemd[1]: exec_helloworld.service: Succeeded.
7월 23 16:53:36 dhyang helloworld.sh[1044548]: Hello World!
7월 23 16:53:36 dhyang systemd[1]: Started Simple execute helloworld script service.
7월 23 16:53:36 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:53:33 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
7월 23 16:53:33 dhyang systemd[1]: /etc/systemd/system/exec_helloworld.service:6: Failed to parse service type, ignoring: Simple
test1.target
/etc/systemd/system
test1.target
/etc/systemd/system/test1.target
test2.target
/etc/systemd/system
test2.target
/etc/systemd/system/test2.target
Wants
종속성에 test1.target
을 걸어둔다.$ sudo systemctl start test2.target
test2.target
의 Wants
에 의해 systemd는 test1.target
을 활성화한다.[Install]
섹션을 갖고 있다면, 이를 활성화시키기 전에 유닛을 "이용 가능하게" 한다.$ sudo systemctl enable <unit>
$ system sudo systemctl status test1.target
● test1.target - test 1
Loaded: loaded (/etc/systemd/system/test1.target; static; vendor preset: enabled)
Active: active since Mon 2021-09-27 14:43:09 KST; 15s ago
Sep 27 14:43:09 ubuntu-linux-20-04-desktop systemd[1]: Reached target test 1.
$ system sudo systemctl status test2.target
● test2.target - test 2
Loaded: loaded (/etc/systemd/system/test2.target; static; vendor preset: enabled)
Active: active since Mon 2021-09-27 14:43:09 KST; 20s ago
Sep 27 14:43:09 ubuntu-linux-20-04-desktop systemd[1]: Reached target test 2.
/etc/systemd/system
test1.target
/etc/systemd/system/test1.target
/etc/systemd/system
test2.target
/etc/systemd/system/test2.target
[Install]
부분에 등록시켰기 때문에 systemctl enable
해야 이 명령이 먹힌다.$ sudo systemctl enable test1.target
/etc/systemd/system/
에 'test2.target.wants' 에 symlink test1.target 생성$ sudo systemctl status test1.target
● test1.target - test 1
Loaded: loaded (/etc/systemd/system/test1.target; enabled; vendor preset: >
Active: inactive (dead)
Sep 27 15:05:37 ubuntu-linux-20-04-desktop systemd[1]: Reached target test 1.
$ sudo systemctl status test2.target
● test2.target - test 2
Loaded: loaded (/etc/systemd/system/test2.target; static; vendor preset: >
Active: inactive (dead)