Yocto recipe에 systemd 서비스, 어떻게 설치하나
Yocto systemd recipe로 앱 유닛을 넣으려면 세 가지만 맞추면 됩니다. (1) recipe에서 inherit systemd와 SYSTEMD_SERVICE, (2) do_install에서 유닛 파일을 ${D}${systemd_system_unitdir}(또는 ${D}${systemd_unitdir}/system)에 설치, (3) 배포판/이미지 쪽에서 systemd init을 켭니다. 이 글은 공식 systemd 클래스·init manager 문서 기준의 최소 howto입니다. 회사 전용 레이어·가격 이야기는 없습니다.
어떤 inherit?
한 줄 답: 유닛을 패키징하는 recipe에 inherit systemd를 넣고, SYSTEMD_SERVICE:${PN}에 서비스 파일 이름을 적습니다. 클래스 동작은 DISTRO_FEATURES에 systemd가 있을 때만 살아 있습니다.
Yocto Project Reference Manual의 systemd class 요지:
inherit systemdSYSTEMD_SERVICE:${PN} = "mydaemon.service"(공백으로 여러 개 가능)- 기본으로 부팅 시 enable. 끄려면
SYSTEMD_AUTO_ENABLE:${PN} = "disable" - 유닛이 메인 패키지가 아니면
SYSTEMD_PACKAGES로 패키지를 지정
최소 recipe 골격:
SUMMARY = "Example daemon with systemd unit"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://mydaemon.service"
inherit systemd
SYSTEMD_SERVICE:${PN} = "mydaemon.service"
# SYSTEMD_AUTO_ENABLE:${PN} = "enable" # default
do_install() {
install -d ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/mydaemon.service ${D}${systemd_system_unitdir}/
}
connman 등 OE 예시도 SYSTEMD_SERVICE:${PN} = "connman.service" 형태입니다. 구식 SYSTEMD_SERVICE_${PN} 밑줄 문법은 새 릴리스에서는 : 오버라이드를 쓰는 편이 안전합니다.
파일은 어디에?
한 줄 답: do_install에서 유닛을 ${D}${systemd_system_unitdir} 아래 두세요. 문서는 ${D}${systemd_unitdir}/system으로도 설명합니다. 클래스와 검색 경로가 그 위치를 전제로 FILES·프리셋·패키지 스크립트를 채웁니다.
실무 체크:
SRC_URI에file://foo.service를 넣고WORKDIR에서 설치합니다.- 설치 경로를 틀리면 packaging 단계에서
Didn't find service unit '…'로 fatal 납니다(systemd.bbclass검색 실패). - 템플릿 유닛(
foo@.service)도SYSTEMD_SERVICE에 이름을 맞추고, 인스턴스 enable은 클래스 프리셋 규칙을 따릅니다. - user 유닛이 필요하면 클래스·검색 경로가 system/user를 나누므로, 문서/클래스 주석의 user unitdir을 확인합니다(대부분 보드 데몬은 system 유닛).
예시 유닛:
[Unit]
Description: Example daemon
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/mydaemon
Restart=on-failure
[Install]
WantedBy=multi-user.target
바이너리 경로는 recipe의 bindir 설치 위치와 일치시켜야 합니다.
IMAGE 기능 플래그는?
한 줄 답: systemd 선택은 보통 IMAGE_FEATURES가 아니라 배포/설정단의 INIT_MANAGER = "systemd"(또는 동등한 DISTRO_FEATURES/VIRTUAL-RUNTIME_init_manager)입니다. recipe의 inherit systemd만으로는 이미지 init이 systemd가 되지 않습니다.
Selecting an Initialization Manager 기준:
# distro conf 또는 local.conf
INIT_MANAGER = "systemd"
이렇게 하면 systemd가 켜지고 sysvinit 구성 요소가 빠지는 방향의 init-manager-systemd include가 잡습니다. 구형 문서/블로그에 보이던 수동 세트는 대략 다음 축입니다.
DISTRO_FEATURES:append = " systemd"
VIRTUAL-RUNTIME_init_manager = "systemd"
# 필요 시 DISTRO_FEATURES에서 sysvinit 정리
정리 표:
| 목적 | 어디서 | 무엇 |
|---|---|---|
| 유닛 패키징 | recipe | inherit systemd, SYSTEMD_SERVICE |
| 유닛 파일 위치 | do_install | ${D}${systemd_system_unitdir} |
| 이미지 init | distro / local.conf | INIT_MANAGER = "systemd" |
| 클래스 활성화 | DISTRO_FEATURES | systemd feature 필요 |
이미지 recipe에 앱 패키지가 들어가 있는지도 확인합니다(IMAGE_INSTALL / packagegroup). init만 systemd여도 패키지를 안 넣으면 유닛은 루트fs에 없습니다.
마무리
Yocto systemd recipe는 inherit systemd + SYSTEMD_SERVICE:${PN} + 올바른 unitdir 설치가 한 세트이고, 이미지 쪽은 **INIT_MANAGER = "systemd"**로 init을 고릅니다. 자세한 변수는 systemd class, init 선택은 Initialization Manager를 보시면 됩니다.