저는 systemd
현재 서비스업에 종사하고 있습니다. 예를 들어, init 6
또는 을 실행할 때 reboot
모든 서비스의 상태 변경 순서는 무엇입니까?init 0
이 문제가 발생하는 시나리오는 다음과 같습니다.
A
종료하고 다시 시작할 때 활성화되는 서비스가 있습니다. 그 목적은 서비스를 호출하여 다른 서비스에서 정보를 검색하는 것입니다 B
. B
시작 시 활성화되고 지속적으로 실행됨을 의미합니다.
reboot
or 가init 0
실행되면 어떤 상태에서 찾을 A
수 있나요 B
?
나는 이 주제에 대한 이 단락이 흥미롭다고 생각했지만 자세히 설명하지는 않았습니다.
ActiveState 장치가 현재 활성 상태인지 여부를 반영하는 상태 값을 포함합니다. 현재 정의된 상태는 활성, 다시 로드, 비활성, 실패, 활성화, 비활성화입니다. active는 장치가 활성 상태임을 의미합니다(분명히...). 다시 로드는 장치가 활성 상태이고 현재 구성을 다시 로드하고 있음을 나타냅니다. 비활성은 비활성 상태이고 이전 실행이 성공했거나 이전 실행이 아직 발생하지 않았음을 의미합니다. 실패함은 비활성 상태이고 이전 실행이 실패했음을 의미합니다(이 이유에 대한 자세한 내용은 결과 속성의 서비스와 같은 장치 유형별 인터페이스에서 찾을 수 있습니다. 아래 참조). 활성이란 해당 장치가 이전에 비활성 상태였지만 현재 활성화되고 있음을 의미합니다. 이와 대조적으로 비활성화됨은 장치가 현재 비활성화되는 과정에 있음을 나타냅니다.
답변1
systemd 설정에서 reboot
및 poweroff
모두 다음과 같은 다양한 하위 명령으로 변환 halt
됩니다 .init N
systemctl
. systemctl
지금부터 이야기하겠습니다 .
그렇다면 systemctl reboot
(예를 들어) 명령을 실행하면 어떻게 될까요? ~하지 않는 한polkit/logind 추상화 계층(루트 권한을 사용할 수 있는 경우에는 사용되지 않음) 이 명령은 로 변환되며 systemctl isolate reboot.target
이는 와 동일합니다 systemctl start --job-mode=isolate reboot.target
.
시스템적 용어로 단위(대상, 서비스 등)를 "격리"한다는 것은 다음을 의미합니다.IgnoreOnIsolate=yes
지정된 장치와 모든 종속성을 시작(활성화)하고 지정 되지 않은 다른 모든 장치를 중지(비활성화)합니다.. 따라서 다시 시작 명령을 실행하면 장치 reboot.target
(및 해당 종속성)는 시작 대기열에 추가되고 다른 모든 장치는 중지 대기열에 추가됩니다.
이러한 대상의 종속성을 수동으로 확인하지는 않습니다( systemctl list-dependencies
명령을 사용할 수는 있음). 우리에게 보여줘시작(7), 시스템 제어 시스템이 시작/종료될 때 어떤 일이 발생하는지 설명하는 매뉴얼 페이지입니다.
해당 ASCII 다이어그램은 여기에 복사하여 붙여넣습니다(FTR, systemd 221을 반영함).
(conflicts with (conflicts with
all system all file system
services) mounts, swaps,
| cryptsetup
| devices, ...)
| |
v v
shutdown.target umount.target
| |
\_______ ______/
\ /
v
(various low-level
services)
|
v
final.target
|
_____________________________________/ \_________________________________
/ | | \
| | | |
v v v v
systemd-reboot.service systemd-poweroff.service systemd-halt.service systemd-kexec.service
| | | |
v v v v
reboot.target poweroff.target halt.target kexec.target
이 프로그램은 꽤 자명합니다. 기본적으로 특수 shutdown.target
대상은 모든 서비스 단위와 충돌합니다(설정되지 않은 경우 DefaultDependencies=no
).
따라서 첫 번째 접근 방식은 서비스 가 종료될 때마다 활성화되도록 A
서비스를 종속성으로 만드는 것입니다. shutdown.target
(만드는 데도 이 과정이 필요하다는 점에 유의하세요 DefaultDependencies=no
.)
그러나 systemd의 모든 작업은 기본적으로 병렬로 수행되므로 A
서비스도 정렬해야 합니다. 즉, 서비스 가 시작되고 데이터 검색이 완료될 때까지 B
종료를 지연해야 합니다 . 존재하다B
A
시스템 유닛(5)우리는 다음을 읽을 수 있습니다:
한 장치가 다른 장치에 대해 순차 종속성을 갖고 있고 후자가 시작 시 종료되는 경우 순차 종속성이 실제로 After= 또는 Before= 유형인지 여부에 관계없이 시작 전에 종료가 발생합니다.
안타깝게도 A를 하든 After=B.service
B 를 하든 Before=B.service
차단됩니다.앞으로A가 시작했습니다.
그래서 우리는 다른 길로 가야 합니다. Type=oneshot
활성화되면 아무 작업도 수행 /bin/true
하지 않지만( ) 비활성화되면 원하는 작업을 수행 하는 일반 서비스를 만들 수 있습니다 . (이것도 설정해야 합니다 RemainsAfterExit=yes
. 그렇지 않으면 서비스가 /bin/true
종료된 후 자동으로 비활성 상태로 표시됩니다.) B.service
이러한 서비스는 필요에 따라 주문할 수 있습니다.
순차 종속성을 갖는 두 장치가 종료되면 시작 순서가 반대가 됩니다. 즉, 한 장치가 다른 장치에 After=를 구성한 경우 두 장치가 모두 종료되면 전자가 후자보다 먼저 중지됩니다.
이 모든 것을 종합하면 유닛 파일은 A.service
다음과 같습니다.
[Unit]
Description=Collect information about B
# we want to deactivate together with B
Requisite=B.service
# we want to deactivate before B deactivates
After=B.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/true
ExecStop=/path/to/B
[Install]
# replace with whatever is needed
WantedBy=B.service
또한 최신(≥ 217) 버전의 systemd를 사용하는 경우ExecStart=/bin/true
완전히 제외될 수 있습니다.
추가 읽기
- 시스템(1)매뉴얼 페이지, "개념" 섹션.
- 시스템 유닛(5)매뉴얼 페이지의 "[Unit] 섹션 옵션" 섹션.
- 시작(7)맨 페이지.
- systemd.special(5)맨 페이지.