배경
이전에 서비스 담당자로부터 리눅스 서버가 시작될 때 특정 서비스가 실행되도록 설정해달라는 요청을 받은 적이 있었습니다. 당시 서비스 담당자가 요청 내역에 rc.local로 설정해달라고 적어두긴 했으나, systemd service로 등록하는 방법을 이전에 개인적으로 써본 적이 있었기 때문에 이 기회에 한 번 두 방법을 비교해보았습니다.
systemd 환경인 최근 리눅스에서는 service unit 파일로 등록하는 방식이 더 권장되고 rc.local 파일 상단에도 systemd service를 권장한다고 적혀있습니다. 왜냐하면 rc.local은 오래된 SysV 시스템에서 사용되던 방식이고, 현대 리눅스에서는 호환성을 위해 남아있는 기능이기 때문입니다.
다만, 당시에는 rc.local 방식으로 진행했습니다. 왜냐하면 (1) 요청자가 rc.local 방식을 명시적으로 요청하였고 (2) 사전 점검으로 /etc/rc.local 파일을 확인해봤을 때 이미 다른 스크립트도 등록해서 사용 중이었기 때문에 서비스 담당자에게 익숙한 방법이라고 판단했기 때문입니다.
이번 글에서는 두 방식을 어떻게 쓰는지, 어떤 차이가 있는지에 대해 당시 찾아본 내용을 정리합니다.
rc.local
실행 권한 부여: 먼저, RHEL7부터
rc.local은 기본적으로 실행 권한이 제거되어 있을 수 있습니다. 권한 확인 후 추가가 필요하다면 부여해줍니다.1> ls -alh /etc/rc.d 2... 3-rw-r--r--. 1 root root 473 Sep 27 2018 rc.local 4 5> chmod 744 /etc/rc.d/rc.local 6> ls -alh /etc/rc.d/rc.local 7-rwxr--r--. 1 root root 473 Sep 27 2018 /etc/rc.d/rc.local- 참고:
/etc/rc.local은/etc/rc.d/rc.local을 가리키는 심볼릭 링크입니다. 위 명령어에서/etc/rc.local을 사용해도 동작은 동일합니다.
- 참고:
부팅 시 실행할 명령어 추가: 이 때는 PATH나 사용자 환경 변수에 의존하지 않도록 절대경로를 사용하는 것이 안전합니다.
1> vi /etc/rc.d/rc.local 2... 3su - appuser -c "/app/myapp/bin/start.sh" >> /var/log/myapp-boot.log 2>&1 &rc-local.service상태 확인:rc.local파일에 실행 권한(+x)을 부여한 후 서비스를 직접 켜서 확인할 수 있습니다.1# `+x` 실행 권한 부여 전 2> systemctl status rc-local 3● rc-local.service - /etc/rc.d/rc.local Compatibility 4Loaded: loaded (/usr/lib/systemd/system/rc-local.service; static; vendor preset: disabled) 5Active: inactive (dead) 6 7# `+x` 실행 권한 부여 후 8systemctl daemon-reload 9systemctl start rc-local.service 10systemctl status rc-local 11● rc-local.service - /etc/rc.d/rc.local Compatibility 12 Loaded: loaded (/usr/lib/systemd/system/rc-local.service; enabled-runtime; preset: disabled) 13 Active: active (exited) since Tue 2026-10-13 21:39:23 KST; 2min 35s ago 14 Docs: man:systemd-rc-local-generator(8) 15 CPU: 5ms 16 17Oct 13 21:39:23 ansible-dev-lr-vm08 systemd[1]: Starting /etc/rc.d/rc.local Compatibility... 18Oct 13 21:39:23 ansible-dev-lr-vm08 systemd[1]: Started /etc/rc.d/rc.local Compatibility.- 다만, 이 방법이 제대로 동작하는지 검증하려면 재부팅을 해보는 것이 가장 확실하니 reload & start보다 재부팅을 바로 해보는 것이 나을 수도 있습니다.
systemd service
systemd 서비스 유닛은 Windows OS에서 ‘서비스’와 유사한 개념으로, 리눅스에서는 보통 ‘데몬(daemon)‘이라고도 부릅니다. (예: httpd, vsftpd 등)
현대 리눅스에서는 서비스 유닛으로 등록하는 이 방법을 더 권장합니다. 아래와 같은 장점을 활용할 수 있기 때문입니다.
systemctl명령어로 표준화된 관리 가능- 부팅 시 자동 실행 뿐 아니라 프로세스 다운 시에도 설정에 따라 자동 재시작 가능
- 네트워크가 준비된 후 실행하도록 순서 보장 가능
journalctl으로 로그 관리 가능
등록 방법
/etc/systemd/system경로 아래에my_app_name.service와 같은 이름의 파일을 만듭니다.1[Unit] 2Description=My startup script 3Wants=network-online.target 4After=network-online.target 5 6[Service] 7Type=oneshot 8User=appuser 9Group=appuser 10ExecStart=/app/myapp/bin/start.sh 11RemainAfterExit=yes 12 13[Install] 14WantedBy=multi-user.targetreload로 이 서비스 파일을 인식한 후 실행합니다.
1systemctl daemon-reload 2systemctl enable --now my_app_name.service
마무리
두 방식을 비교하면 다음과 같습니다.
| rc.local | systemd service | |
|---|---|---|
| 설정 위치 | /etc/rc.d/rc.local 파일 하나 | /etc/systemd/system/*.service |
| 실행 순서 | network.target 이후, 다른 서비스와 병렬 실행 | After=, Wants=로 직접 지정 |
| 프로세스 종료 시 | 별도 처리 없음 | Restart= 설정으로 자동 재시작 |
| 로그 | 직접 리다이렉션 필요 | journalctl -u <서비스명> |
| 관리 | 파일 직접 편집 | systemctl로 표준화 |
다음에 비슷한 요청이 왔을 때 rc.local을 사용하지 않고 새로 구성하는 서버라면 systemd 서비스로 등록하는 것을 고려할 것입니다. 다만 이번에 요청받은 것과 같이 이미 rc.local을 사용하고 있는 서버에 하나만 systemd 서비스로 등록하면, 부팅 시 실행되는 항목을 확인해야 할 곳이 두 군데로 나뉘게 됩니다. 서버를 관리하는 담당자 입장에서는 일관성도 중요한 기준이라고 판단했습니다.
개인 환경이었다면 큰 고민 없이 systemd 방식을 사용했을테지만, 이번에는 요청받은 방식이 있는 상황에서 어떻게 하는 것이 좋을지 고민하면서, 단순히 좋은 방법을 고르는 것이 아니라 두 방식의 차이를 직접 비교해 볼 수 있는 계기가 되었습니다.
Comments