서비스 · 프로세스 관리 21 / 50 · Part 3. systemd와 서비스
실습 환경: Rocky Linux 9.8 · Ubuntu 24.04.5 (systemd로 부팅한 Docker 격리 컨테이너, 테스트 계정 analyst)

1. 들어가며

Part 3 「systemd와 서비스」를 시작한다. Part 1·2를 지나오는 동안 PID 1은 여러 번 등장했다. 모든 프로세스의 조상(03편), 고아의 새 부모(08편), 서비스를 멈추고 다시 띄우는 주체(13편), cgroup을 만드는 관리자(18편). 그 PID 1의 정체가 systemd 다.

이번 글에서는 PID 1이 어떤 프로그램인지 확인하고, systemd가 관리하는 대상(unit)의 전체 규모를 살펴본 뒤, systemctl이 PID 1과 어떻게 통신하는지, 사용자마다 따로 뜨는 systemd --user는 무엇인지 정리한다.

「리눅스 시스템 기초 8편(부팅 과정)」과 「36편(systemd 구조)」에서 개괄한 내용을, 이번 Part에서는 10편에 걸쳐 실무 수준으로 다룬다.


2. 핵심 개념

2-1. init 시스템의 변천

세대방식특징
SysV init/etc/init.d/ 셸 스크립트 + runlevel순차 시작, 단순하지만 느림
Upstart이벤트 기반Ubuntu 6.10~14.10
systemdunit 파일 + 의존성 그래프병렬 시작, cgroup, 로그·로그인·타이머 통합 (RHEL 7+, Ubuntu 15.04+)

2-2. PID 1의 역할

역할내용관련 편
부팅default.target까지 필요한 unit을 의존성 순서로 시작27편
서비스 관리시작·중지·재시작·상태 추적23·24편
프로세스 관리고아 입양, 좀비 회수08편
cgroup 관리서비스·세션별 cgroup 생성, 자원 제한18편
부가 데몬journald(로그), logind(로그인 세션), udevd(장치)31편
특수 동작PID 1이 종료되면 커널 패닉. 시그널도 명시적으로 처리하는 것만 받는다—

2-3. unit이란

systemd가 관리하는 모든 대상을 unit 이라 한다. 서비스(.service)만이 아니라 소켓, 타이머, 마운트, target 등 11종이 있다(22편).


3. 동작 원리

PID 1 (systemd) 이 맡는 일과 systemctl 의 통신 구조

systemctl restart atd
  → /run/systemd/private (또는 D-Bus system bus) 로 PID 1 에 요청
  → PID 1: 권한 확인(root 또는 polkit 허가) → atd.service 중지 → 시작
  → 결과(job 완료/실패)를 systemctl 에 반환

systemctl은 스스로 서비스를 띄우지 않는다. 요청만 보내는 클라이언트 다. 실제 프로세스를 fork·exec하는 것은 PID 1이다. 그래서 systemctl로 시작한 서비스의 부모는 항상 PID 1이고, 셸과는 관계가 없다(10편의 nohup 문제가 생기지 않는 이유).


4. 명령어 실습

# 1) PID 1 의 정체
ps -o pid,ppid,user,lstart,cmd -p 1
readlink /proc/1/exe; ls -l /sbin/init
systemctl --version | head -1
pstree -p 1 | head -12

# 2) systemd 가 관리하는 unit 규모
systemctl list-units --type=service --state=running --no-pager --no-legend
systemctl list-units --no-pager --no-legend | awk '{print $1}' | sed 's/.*\.//' | sort | uniq -c | sort -rn
systemctl is-system-running
ls -l /run/systemd/private /run/dbus/system_bus_socket

# 3) (Ubuntu, analyst) 사용자별 systemd
ps -o pid,ppid,user,cmd -C systemd
systemctl --user is-system-running
systemctl --user list-units --type=socket --no-pager --no-legend | head -5
loginctl user-status analyst --no-pager | head -8

5. 실행 결과

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — PID 1 의 정체

실제 실행 결과 — Rocky Linux 9.8 · root@rocky9-lab — systemd 가 관리하는 것들

실제 실행 결과 — Ubuntu 24.04.5 · analyst@ubuntu-lab — 사용자별 systemd (--user)

텍스트 원본(실제 출력):

[root@rocky9-lab ~]# ps -o pid,ppid,user,lstart,cmd -p 1
    PID    PPID USER                      STARTED CMD
      1       0 root     Thu Sep 24 11:48:18 2026 /usr/sbin/init
[root@rocky9-lab ~]# readlink /proc/1/exe; ls -l /sbin/init
/usr/lib/systemd/systemd
lrwxrwxrwx 1 root root 22 Sep 16 04:40 /sbin/init -> ../lib/systemd/systemd
[root@rocky9-lab ~]# systemctl --version | head -1
systemd 252 (252-67.el9_8.6.rocky.0.1)
[root@rocky9-lab ~]# pstree -p 1 | head -12
systemd(1)-+-agetty(39)
           |-anacron(2396)
           |-atd(37)
           |-crond(38)
           |-dbus-broker-lau(41)---dbus-broker(46)
           |-sshd(31)---sshd-session(2419)---sshd-session(2432)---bash(2433)-+-head(2463)
           |                                                                 `-pstree(2462)
           |-systemd(2423)---(sd-pam)(2425)
           |-systemd-journal(21)
           `-systemd-logind(32)
[root@rocky9-lab ~]# systemctl list-units --type=service --state=running --no-pager --no-legend
  atd.service              loaded active running Deferred execution scheduler
  crond.service            loaded active running Command Scheduler
  dbus-broker.service      loaded active running D-Bus System Message Bus
  getty@tty1.service       loaded active running Getty on tty1
  sshd.service             loaded active running OpenSSH server daemon
  systemd-journald.service loaded active running Journal Service
  systemd-logind.service   loaded active running User Login Management
  user@0.service           loaded active running User Manager for UID 0
[root@rocky9-lab ~]# systemctl list-units --no-pager --no-legend | awk '{print $1}' | sed 's/.*\.//' | sort | uniq -c | sort -rn
     15 target
     14 service
     11 mount
      7 slice
      4 socket
      2 timer
      2 scope
      2 path
      1 device
[root@rocky9-lab ~]# systemctl is-system-running
running
[root@rocky9-lab ~]# ls -l /run/systemd/private /run/dbus/system_bus_socket
srw-rw-rw- 1 root root 0 Sep 24 11:48 /run/dbus/system_bus_socket
srwx------ 1 root root 0 Sep 24 11:48 /run/systemd/private
analyst@ubuntu-lab:~$ ps -o pid,ppid,user,cmd -C systemd
    PID    PPID USER     CMD
      1       0 root     /sbin/init
    860       1 analyst  /usr/lib/systemd/systemd --user
analyst@ubuntu-lab:~$ systemctl --user is-system-running
running
analyst@ubuntu-lab:~$ systemctl --user list-units --type=socket --no-pager --no-legend | head -5
  dbus.socket loaded active listening D-Bus User Message Bus Socket
analyst@ubuntu-lab:~$ loginctl user-status analyst --no-pager | head -8
analyst (1001)
   Since: Thu 2026-09-24 12:10:30 UTC; 181ms ago
   State: active
Sessions: *96
  Linger: no
    Unit: user-1001.slice
          ├─session-96.scope
          │ ├─856 "sshd: analyst [priv]"

6. 결과 해석

관찰의미
PID 1 /usr/sbin/init, PPID 0커널이 직접 실행했다. 명령 줄에는 init으로 보인다
readlink /proc/1/exe → /usr/lib/systemd/systemd실제 실행 파일은 systemd 다. /sbin/init은 호환용 심볼릭 링크
systemd 252 (252-67.el9_8.6...)Rocky 9.8의 systemd 버전. 기능 차이를 확인할 때 버전이 중요하다
pstree -p 1에 agetty, atd, crond, sshd, journald, logind...모든 서비스가 PID 1의 직계 자식이다
systemd(2423)---(sd-pam)root 로그인으로 생긴 사용자별 systemd 인스턴스
running 서비스 8개최소 설치 서버는 이 정도다. 운영 서버에서 이 목록이 기준선 이 된다
unit 종류별 개수: target 15, service 14, mount 11 ...서비스는 전체 unit의 일부일 뿐이다. 타이머 2개, 소켓 4개도 부팅 후 자동 동작한다
is-system-running → running실패한 unit이 없는 정상 상태. 하나라도 실패하면 degraded
/run/systemd/private 권한 srwx------ rootsystemctl ↔ PID 1 전용 통신 소켓. root만 쓸 수 있다
/run/dbus/system_bus_socket srw-rw-rw-일반 사용자도 D-Bus로 요청할 수 있지만, 권한 있는 작업은 polkit이 막는다
Ubuntu systemd --user (PID 860, analyst)analyst 로그인 시 생성된 사용자 서비스 관리자
loginctl: Unit: user-1001.slice, session-96.scope사용자 → slice, 로그인 → scope. 18편의 cgroup 구조 그대로다

Ubuntu의 analyst UID가 1001인 것은 Ubuntu 공식 이미지에 ubuntu 계정(UID 1000)이 미리 있기 때문이다.


7. 보안 관점

주제내용
지속성의 목적지systemd에 unit을 등록하면 재부팅 후에도 PID 1이 자동 실행 한다. 공격자가 가장 선호하는 지속성 기법이다 (MITRE ATT&CK T1543.002)
사용자 레벨 지속성root가 아니어도 ~/.config/systemd/user/에 unit을 두면 systemd --user가 실행한다. 일반 계정 탈취만으로 가능한 지속성 이다 (46편)
제어 권한systemctl로 서비스를 제어하려면 root나 polkit 허가가 필요하다. sudoers에 systemctl 전체를 허용하면 사실상 root 권한을 준 것과 같다
무결성/sbin/init이나 systemd 바이너리가 바뀌면 부팅 전체가 장악된다. 패키지 무결성 검증(rpm -V systemd) 대상이다

8. 보안관제 관점

[기준선 수집 — 평소에]
  systemctl list-units --type=service --state=running --no-legend > baseline_running.txt
  systemctl list-unit-files --state=enabled --no-legend > baseline_enabled.txt
     ↓
[점검 — 정기적으로 또는 경보 시]
  diff baseline_running.txt <(systemctl list-units --type=service --state=running --no-legend)
  diff baseline_enabled.txt <(systemctl list-unit-files --state=enabled --no-legend)
     ↓
[판단]  새로 enabled 된 unit, 설명(Description)이 비어 있거나 그럴듯한 이름(systemd-update-*)
     ↓
[확인]  systemctl cat <unit> · 실행 파일 경로 · 생성 시각 (46편)
관점확인
시스템 상태systemctl is-system-running이 degraded면 실패 unit 확인
사용자 managerps -C systemd -o user,cmd로 어떤 계정의 사용자 systemd가 떠 있는지
lingerloginctl show-user USER -p Linger — yes면 로그아웃 후에도 사용자 서비스가 계속 실행된다

9. 실무에서 자주 발생하는 실수

실수결과예방
/etc/init.d/ 스크립트만 찾음systemd 서버에서 서비스 정의를 놓침systemctl cat, unit 파일 경로 확인
systemd 서비스 프로세스를 kill로 조작systemd가 재시작하거나 상태가 어긋남systemctl 사용
degraded를 무시실패한 서비스(보안 에이전트일 수도)를 방치systemctl --failed 확인
사용자 systemd를 점검에서 제외사용자 레벨 지속성 누락systemctl --user와 홈 디렉터리 unit 점검

10. 실습 체크리스트

[ ] PID 1 의 실제 실행 파일이 systemd 인 것을 확인했다
[ ] systemctl --version 으로 버전을 확인했다
[ ] 실행 중인 서비스 목록(기준선)을 저장했다
[ ] unit 종류별 개수를 집계했다
[ ] /run/systemd/private 소켓의 권한을 확인했다
[ ] systemd --user 인스턴스와 user slice / session scope 를 확인했다

11. 핵심 정리

  • PID 1은 systemd이며, 부팅·서비스·cgroup·고아 관리를 모두 맡는다.
  • systemctl은 PID 1에 요청을 보내는 클라이언트다. 서비스를 실제로 실행하는 것은 PID 1이다.
  • systemd는 서비스 외에도 소켓·타이머·마운트·target 등 다양한 unit을 관리한다.
  • 로그인한 사용자마다 systemd --user가 따로 동작한다.
  • systemd unit은 공격자의 대표적인 지속성 수단이므로 실행·활성 unit 목록을 기준선으로 관리한다.

12. 다음 편 예고

다음 글 「22. Unit 종류와 Unit 파일 위치」 에서는 11가지 unit 종류와, unit 파일이 놓이는 여러 디렉터리의 우선순위 를 정리한다. /usr/lib, /etc, /run 중 어디의 파일이 이기는지, enabled·static·alias 같은 상태가 무엇을 뜻하는지 확인한다.


참고 자료


시리즈 이동

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글