리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 37 / 50 · Part 4. 프로세스·서비스·리소스
실습 환경: Rocky Linux 9 (10.0.0.200) / Ubuntu 22.04 (10.0.0.210)
이전 글: 36. systemd 구조 이해

1. 들어가며

36편에서 systemd의 구조(Unit, 파일 위치, target, cgroup)를 봤다. 이번 글은 그 구조를 다루는 명령 systemctl을 정리한다.

systemctl start나 stop은 누구나 쓰지만, 관제에서 자주 틀리는 부분은 따로 있다.

  • active와 enabled를 같은 뜻으로 읽는 것
  • restart와 reload를 구분하지 않는 것
  • status의 Main PID ... code=killed, signal=KILL 같은 종료 원인 을 놓치는 것

서비스가 멈췄을 때 이것이 장애인지, 사람의 조작인지, 공격인지 를 가르는 단서가 systemctl status 한 화면에 다 들어 있다.


2. 핵심 개념

2-1. 두 개의 축: 지금 vs 부팅 시

축명령바뀌는 것
지금 (runtime)start, stop, restart, reload현재 실행 여부 → Active
부팅 시 (install)enable, disable*.wants/ 링크 → Loaded 줄의 enabled/disabled
둘 다enable --now, disable --now한 번에
완전 차단mask, unmaskUnit을 /dev/null로 링크 → 수동 start도 불가

그래서 이런 조합이 모두 가능하다.

Active부팅 설정의미
activeenabled정상 운영 중인 서비스
activedisabled누군가 수동으로 켰다 → 재부팅하면 꺼짐
inactiveenabled부팅 후 죽었거나 누군가 stop → 확인 필요
inactivemasked의도적으로 차단

2-2. restart / reload / daemon-reload

명령동작PID연결
restart종료 후 다시 시작바뀜끊김
reload설정만 다시 읽음 (Unit의 ExecReload, 대개 SIGHUP)유지유지
try-restart / reload-or-restart실행 중일 때만 / reload 불가하면 restart
daemon-reloadUnit 파일 자체 를 systemd가 다시 읽음서비스와 무관

Unit 파일을 수정하고 daemon-reload 없이 restart만 하면, systemd는 예전 설정 으로 서비스를 다시 띄운다(경고 메시지가 나온다).

2-3. Active 상태

상태의미
active (running)실행 중
active (exited)일회성 작업이 성공하고 끝남 (Type=oneshot)
inactive (dead)정지
activating (auto-restart)죽어서 재시작 대기 중 — 반복되면 크래시 루프
failed실패 상태로 멈춤. Result: 에 원인

3. 동작 원리

systemctl — 지금 상태(active)와 부팅 설정(enabled)은 별개다

systemctl은 스스로 서비스를 실행하지 않는다. D-Bus를 통해 PID 1(systemd)에 요청 을 보낼 뿐이다. 실제 fork·exec, cgroup 생성, 재시작 판단은 systemd가 한다. 그래서:

  • 일반 사용자는 시스템 서비스를 조작할 수 없다(polkit이 권한 확인). sudo가 필요하다.
  • 요청과 결과는 journal에 systemd[1]: Started ..., Stopped ... 형태로 남는다.

status의 종료 원인 표기는 34편의 시그널·종료 코드와 그대로 이어진다.

status 표기의미
code=exited, status=0/SUCCESS정상 종료
code=exited, status=1/FAILURE프로그램 오류 종료 — 설정 오류가 흔함
code=killed, signal=TERMSIGTERM으로 종료 (stop 이면 정상)
code=killed, signal=KILLSIGKILL — 강제 종료 또는 OOM Killer(39편)
code=dumped, signal=SEGV크래시 (코어 덤프)
Result: exit-code / signal / timeout / oom-kill실패 분류

4. 실습

# 1) 상태
systemctl status sshd
systemctl is-active sshd; systemctl is-enabled sshd; systemctl is-failed sshd

# 2) 조작
sudo systemctl restart httpd
sudo systemctl reload httpd              # 지원 서비스만
sudo systemctl enable --now chronyd
sudo systemctl disable --now cups
sudo systemctl mask cups                 # 완전 차단

# 3) Unit 파일 수정 후
sudo systemctl edit sshd                 # 드롭인 생성 (/etc/systemd/system/sshd.service.d/override.conf)
sudo systemctl daemon-reload

# 4) 목록
systemctl --failed
systemctl list-units --type=service --state=running
systemctl list-unit-files --state=enabled

# 5) 서비스 로그 (48편)
journalctl -u sshd --since "1 hour ago" --no-pager

# 6) 한 번에 여러 속성
systemctl show auditd -p ActiveState,SubState,Result,ExecMainStatus,NRestarts,ActiveEnterTimestamp

5. 결과 분석

아래 출력은 형식 설명용 예시다.

① 크래시 루프

Active: activating (auto-restart) (Result: exit-code) since ...
Process: 2211 ExecStart=/usr/sbin/httpd ... (code=exited, status=1/FAILURE)
...
httpd[2211]: AH00526: Syntax error on line 42 of /etc/httpd/conf/httpd.conf

status=1/FAILURE와 하단 로그의 설정 문법 오류 → 장애 다. 누가 언제 설정 파일을 바꿨는지(변경 관리, ls -l --time-style=full-iso)를 확인한다.

② 보안 서비스 강제 종료 (그림의 예)

Loaded: loaded (...auditd.service; enabled; ...)
Active: failed (Result: signal) since Tue 02:33:05 KST
Main PID: 812 (code=killed, signal=KILL)
단서해석
enabled 인데 failed계속 떠 있어야 할 서비스가 멈춤
signal=KILL스스로 죽은 게 아니라 외부에서 SIGKILL (또는 OOM)
시각 02:33새벽, 변경 작업 일정 없음

OOM이었다면 journalctl -k에 Out of memory: Killed process 812 (auditd)가 남는다(39편). 그 기록이 없다면 사람(또는 악성코드)의 행위 로 보고 그 시각의 로그인·sudo 기록을 확인한다.


6. 보안 관점

행위systemctl 흔적의미
보안 서비스 중지 (T1562.001)auditd, firewalld, EDR 에이전트 inactive / masked탐지 회피
방화벽 해제systemctl disable --now firewalld외부 접근 확대 (46편)
악성 서비스 등록enable --now 후 새 Unit active지속성 (36편)
서비스 설정 변조systemctl edit으로 드롭인 → ExecStart 교체정상 서비스 이름으로 악성 실행
크래시 루프NRestarts 증가장애 또는 공격 트래픽

auditd는 설계상 systemctl stop auditd를 거부하도록 되어 있다(RefuseManualStop=yes, service auditd stop을 사용). 그래서 공격자는 kill -9를 쓰는 경우가 많고, 이것이 ② 같은 signal=KILL 흔적으로 남는다.


7. SOC / 보안관제 활용

7-1. 보안 서비스 상태 일괄 점검

for s in auditd rsyslog firewalld sshd crond; do
  printf '%-10s %-9s %-9s %s\n' "$s" \
    "$(systemctl is-active $s 2>/dev/null)" \
    "$(systemctl is-enabled $s 2>/dev/null)" \
    "$(systemctl show $s -p Result --value 2>/dev/null)"
done

Ubuntu에서는 firewalld 대신 ufw, crond 대신 cron, rsyslog는 동일하다.

7-2. 서비스 상태 변경 로그

journalctl _PID=1 --since today | grep -Ei 'Stopped|Started|Failed|killed' | tail -30
journalctl --since today | grep -E 'systemctl (stop|disable|mask)'   # sudo 로 실행했다면 sudo 로그에도 남음

7-3. 분석 흐름

[Alert]   SIEM: 서버 A audit 로그 수신 중단 02:33
   ↓
[status]  auditd: enabled / failed / Main PID code=killed, signal=KILL
   ↓
[OOM?]    journalctl -k 02:30~02:35 → Out of memory 기록 없음
   ↓
[누가]    secure 02:31 devuser sudo 성공(ALL) → 02:33 kill -9 812 (sudo 로그 COMMAND=)
   ↓
[Response] auditd 재시작, devuser 세션 종료·잠금, 02:31 이후 행위 전수 조사

8. 핵심 정리

  • Active(지금) 와 enabled(부팅 시) 는 별개다. start/stop ↔ enable/disable.
  • mask는 수동 시작까지 막는다. restart는 PID가 바뀌고, reload는 설정만 다시 읽는다.
  • Unit 파일을 고친 뒤에는 daemon-reload.
  • status에서 볼 곳: Loaded 경로·enabled, Active 상태·시각, Main PID 종료 원인, 하단 로그.
  • enabled + failed + signal=KILL → OOM 기록이 없으면 외부 강제 종료 를 의심한다.

9. 다음 글

다음 글 「38. cron 작업 스케줄링」 에서는 정해진 시각에 명령을 실행하는 cron과 systemd timer를 다룬다. crontab 문법, 설정 파일 위치(사용자·시스템·cron.d), 실행 로그 위치(RHEL /var/log/cron, Ubuntu syslog), 그리고 cron을 이용한 지속성 탐지를 정리한다.


참고 자료

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

0개의 댓글