컴퓨터를 부팅할 때마다 Docker 데몬/colima 같은 서비스를 수동으로 실행하는게 번거로웠습니다. 이번 글에서는 macOS의 Launch Daemon을 이용하여 시스템이 시작될 때 지정한 스크립트를 자동 실행하는 방법을 알아보겠습니다.
셸이란 무엇인가?
셸은 사용자가 터미널에 입력하는 명령어를 해석하고 실행하는 프로그램입니다.
- macOS의 경우, Catalina(10.15) 이후부터 기본 셸은 zsh로 변경되었으며, 이전에는 bash가 사용되었습니다.
- 현재 사용 중인 셸은 echo $SHELL 명령어로 확인할 수 있습니다.
- 터미널이 명령어를 입력하는 화면같은 존재라면, 셸은 그 명령어를 해석하는 프로그램입니다.
Launch Daemon과 plist 파일
macOS에서는 Launch Daemon을 통해 시스템 부팅 시 특정 스크립트를 자동으로 실행할 수 있습니다. 이를 위해 설정 파일인 plist 파일을 사용합니다.
plist 파일 주요 구성 요소
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.flrefly.startup</string>
<key>UserName</key>
<string>flrefly</string>
<key>ProgramArguments</key>
<array>
<string>/Users/flrefly/computer-start-script/start.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/Users/flrefly/computer-start-script/error.log</string>
<key>StandardOutPath</key>
<string>/Users/flrefly/computer-start-script/output.log</string>
</dict>
</plist>
- Label: 데몬의 고유 이름을 지정합니다.
- UserName: 해당 스크립트를 실행할 사용자 계정을 명시합니다.
- ProgramArguments: 실행할 스크립트와 그 인자들을 배열 형식으로 지정합니다.
- RunAtLoad: 시스템 부팅 시(또는 데몬이 로드될 때) 자동으로 실행되도록 설정합니다.
- StandardErrorPath / StandardOutPath: 오류 및 출력 로그 파일의 위치를 지정해, 실행 결과를 확인할 수 있도록 합니다.
데몬 등록 및 제어
# 데몬 등록 옵션은 영구적으로 적용한다는 의미
sudo launchctl load -w /Library/LaunchDaemons/com.flrefly.startup.plist
# 데몬 해제
sudo launchctl unload -w /Library/LaunchDaemons/com.startup.plist
# 문법 검사
plutil -lint /Library/LaunchDaemons/com.flrefly.startup.plist
# 수동 실행
sudo launchctl start com.startup
# 수동 중지
sudo launchctl stop com.startup
[주의사항] 환경 변수와 PATH
터미널을 실행할 때, zsh나 bash는 ~/.zshrc 혹은 ~/.bashrc 파일을 읽어 사용자 정의 환경 변수(예: PATH)를 설정합니다.
그러나 Launch Daemon은 이와 같은 사용자 셸 설정을 읽지 않습니다.
- 명령어 찾기: 예를 들어, 도커 데몬을 실행시키는 명령어가 PATH라는 환경변수에 포함된 디렉토리에 있을 경우, 터미널에서는 정상 실행되지만(터미널에서는 특정 파일을 읽어 환경변수를 알지만), Launch Daemon에서는 환경변수 값들을 모르니 경로를 모르게 되고 결국 command not found 오류가 발생합니다.
- 해결 방법: 스크립트 내에 export PATH=/opt/homebrew/bin:$PATH와 같이 직접 PATH를 설정하거나, plist 파일 내에서 EnvironmentVariables 키를 통해 환경 변수를 지정할 수 있습니다.
이 과정에서 데몬이란 무엇인가? 에 대해 생각을 해봤습니다
백그라운드 프로세스 vs. 데몬
백그라운드 프로세스와 데몬은 모두 터미널과 직접 상호작용하지 않고 실행되지만, 몇 가지 중요한 차이가 있습니다.
백그라운드 프로세스
- 셸에 속함: 터미널에서 & 기호로 실행한 프로세스는 여전히 해당 셸의 제어 하에 있습니다.
- 입출력 연결: 표준 입력, 출력, 에러 스트림이 기본적으로 터미널에 연결됩니다.
- 부모 프로세스 영향: 셸이 종료되면, SIGHUP(세션 종료 신호) 등의 영향으로 프로세스가 종료될 위험이 있습니다.
데몬
- 독립적 실행: 데몬은 제어 터미널 없이 실행되며, 셸의 환경에 의존하지 않습니다.
- 시스템 관리: 일반적으로 시스템 초기 프로세스(init 또는 systemd)의 자식으로 생성되어, 시스템 레벨에서 관리됩니다.
- 입출력 리다이렉션: 표준 입출력은 /dev/null이나 지정한 로그 파일로 리다이렉션되어, 터미널과 완전히 분리됩니다.
- 장기 실행: 네트워크 서비스, 백그라운드 작업 등 지속적이고 안정적인 실행이 요구되는 서비스에 적합합니다.
참고
'문제해결' 카테고리의 다른 글
| S3 다운로드 최적화 시도기 — Mountpoint를 도입하지 않은 이유 (0) | 2026.04.16 |
|---|---|
| 트레이싱 어노테이션 140개를 지우며 들었던 생각 (0) | 2025.02.26 |
| ProcessBuilder를 활용한 표준 출력 및 로그 파일 관리 (0) | 2023.12.23 |
| JUnit 5 의존성 주입 과정에서의 문제 (0) | 2023.11.20 |
| Reddisson을 활용한 동시성 문제 해결 (1) | 2023.10.04 |