유닛과 프로세스의 관계
110분 안팎
학습 목표
이전 웹 앱에 User·WorkingDirectory·ExecStart를 지정한 실습 전용 유닛을 작성합니다.
개념
실행 책임을 셸에서 서비스 관리자로 옮깁니다
앞 모듈에서는 로그인한 사람이 Python을 실행하고 PID와 응답을 관찰했습니다. 터미널이 바뀌면 현재 디렉터리와 환경 변수도 달라집니다. 이번 목표는 누가 로그인했는지와 관계없이 실행 계정·경로·설정을 명시하는 것입니다. systemd 유닛은 프로그램을 실행할 규칙을 담은 파일이며 실제 프로세스는 그 규칙으로 만들어지는 실행 인스턴스입니다. 유닛 파일이 존재하는 것만으로 프로세스가 생기지는 않습니다.
이 모듈의 시스템 명령은 systemd가 PID 1인 앞 Linux VM에서 실행합니다. ZIP은 관리자 로그인 홈에 풀고 실습 폴더에서 bash check.sh를 실행합니다. Python 로그 집계와 설정 보관 기능은 이 맥에서도 확인하지만 VM 기동 검사를 대신하지 않습니다. 앞 모듈의 bcweb·bcops·bcapp 및 /srv/bootcamp-m02/lab-root를 유지합니다. 관리자 작업은 설치와 유닛 적용에 한정하며 서비스 계정에 sudo 권한을 추가하지 않습니다.
먼저 실행 경계를 고정합니다
서비스는 127.0.0.1:18080의 이전 앱을 그대로 사용합니다. bcweb가 읽을 수 있는 데이터와 읽을 수 없는 설정 쓰기 권한도 유지합니다. 기존 데이터나 app.conf를 새 예제 값으로 덮어쓰지 않습니다. 다른 프로세스가 이 포트를 사용한다면 그 소유자와 용도를 먼저 확인합니다. 포트 충돌을 해결하려고 임의의 PID를 종료하는 것은 이 과제의 절차가 아닙니다. 격리된 VM에서 실습 전용 서비스만 추가합니다.
다운로드 폴더 전체를 서비스에 공개하지 않습니다. prepare.sh는 app.py와 새 service.py만 기존 실습 경로에 배치합니다. m03의 Store·HTTP 처리 함수와 회귀 테스트는 보존하며 service.py가 환경 검증과 제한된 수명을 담당합니다. 이전 프로그램을 새 파일 서버로 교체하면 /items의 의미와 접근 범위가 달라지므로 올바른 확장이 아닙니다. 서비스 계정은 홈 폴더를 통과할 필요 없이 /srv의 앱을 읽습니다.
세 개의 섹션을 구분합니다
[Unit]에는 서비스의 설명을, [Service]에는 실제 실행 방법을, [Install]에는 enable할 때 연결할 대상을 적습니다. Description은 관리자가 목적을 알아보는 문장입니다. Type=simple은 전경에서 유지되는 Python 프로세스에 맞습니다. 앱은 스스로 백그라운드로 분리되지 않으므로 forking을 사용하지 않습니다. ExecStart 끝에 앰퍼샌드를 넣거나 nohup으로 다시 분리하면 관리자가 추적할 실행 관계가 흐려집니다.
User=bcweb와 Group=bcapp는 프로세스의 실행 주체를 고릅니다. WorkingDirectory=/srv/bootcamp-m02/lab-root는 상대 경로의 기준이며 ExecStart의 인터프리터와 스크립트 경로는 절대 경로로 씁니다. 설치된 /usr/bin/python3를 먼저 확인합니다. 셸에서 쓰는 물결표나 파이프를 ExecStart에 그대로 적는다고 셸 명령처럼 처리되는 것은 아닙니다. 이 앱에 셸 래퍼를 추가할 이유는 없습니다.
서비스 환경은 명시적으로 전달합니다
로그인 셸에서 export한 DATA_FILE이 시스템 서비스에도 전달된다고 기대하지 않습니다. EnvironmentFile은 /srv/bootcamp-m02/lab-root/config/service.env를 읽고 DATA_FILE과 RUN_SECONDS를 전달합니다. 파일에는 KEY=value 줄을 적으며 셸의 source 스크립트처럼 명령을 넣지 않습니다. DATA_FILE은 기존 items.json의 절대 경로이고 RUN_SECONDS=20은 교육용 실행 시간을 뜻합니다. 필수 환경 파일이므로 경로 앞에 누락을 무시하는 기호를 붙이지 않습니다.
환경 파일은 root:bcapp 소유와 0640 모드로 설치합니다. 서비스 관리자는 파일에서 변수를 읽고 bcweb 프로세스를 시작합니다. 앱의 데이터 읽기는 이후 bcweb 권한으로 수행됩니다. UMask=0027은 새 파일의 기본 허용 범위를 좁히지만 이미 있는 파일 권한을 고치지는 않습니다. 비밀값은 이 실습에 넣지 않으며 나중에 실제 설정을 다룰 때는 환경 파일과 그 보관 사본 모두의 접근 권한을 검토합니다.
기동 성공과 준비 완료는 다릅니다
Type=simple의 시작 처리는 HTTP 요청 준비 완료를 기다리는 약속이 아닙니다. systemctl start가 성공했다고 바로 /items가 정상이라고 적지 않습니다. 관리 상태는 systemctl is-active로, 프로세스 주체는 MainPID와 ps로, 기능은 /health의 상태·본문 및 /items의 실제 데이터로 나누어 검사합니다. MainPID가 0이면 실행 인스턴스가 없는지 상태와 함께 봅니다. 이전 PID가 지금도 같은 앱인지 시각과 명령을 함께 확인합니다.
이 서비스는 20초 뒤 서버의 shutdown·server_close·thread join으로 자연 종료합니다. Restart=no를 사용해 실패 사례의 재시작 소음을 줄이며 자동 시작 등록은 실습 검증에서 하지 않습니다. 검증 중에는 active와 HTTP를 확인하고 종료 뒤에는 inactive가 예상 상태입니다. 실제 장기 운영이라면 앱 수명 제한을 없애고 Restart 정책과 재시작 간격·시작 제한을 함께 설계합니다. 이 예제를 그대로 운영 유닛으로 복사하지 않습니다.
파일 변경과 실행 변경을 나눕니다
유닛 파일을 /etc/systemd/system/bootcamp-systems.service에 설치한 뒤 systemd-analyze verify로 문법과 실행 경로 관련 진단을 읽습니다. 경고가 없다는 사실은 HTTP 정상이나 데이터 권한을 보장하지 않습니다. daemon-reload는 관리자가 유닛 정의를 다시 읽도록 하고 start는 현재 기동을 요청합니다. 이미 실행 중인 서비스에 start를 다시 호출해도 새 설정으로 교체하는 명령이 아닙니다. 이 실습은 자연 종료를 기다린 뒤 다음 기동을 수행합니다.
enable은 이후 부팅 대상에 연결하고 지금 실행하는 start와 별개의 동작입니다. WantedBy=multi-user.target를 썼다고 파일 복사만으로 자동 시작이 등록되지 않습니다. 실습에서는 is-enabled로 상태를 조회하는 데 그칩니다. 앱은 설정을 실시간 다시 읽는 기능을 제공하지 않아 reload 지원을 가정할 수 없습니다. 유닛 변경에는 daemon-reload가 필요하고 앱 환경 값 변경은 다음 프로세스 기동 때 반영됩니다.
흔한 실패와 완료 증거
Unit not found는 이름 철자·설치 경로·관리자의 정의 재읽기를 확인할 단서입니다. Failed to determine user credentials는 계정이 실제로 있는지 확인할 단서이며 앱의 PermissionError와 같은 단계가 아닙니다. 유닛 검증이 TODO 실행 계정을 지적하면 기존 bcweb를 지정합니다. 문제를 없애려고 User=root로 바꾸면 앞 권한 설계가 무너집니다. 권한을 올리는 대신 어느 파일을 어느 계정이 읽어야 하는지 설명합니다.
완료 기록에는 유닛 경로와 관측 시각, 실행 계정, MainPID, active 관측, 두 HTTP 응답, 자연 종료 결과를 남깁니다. check.sh의 검사 범위는 유닛 계약과 앱 경계값, VM의 실제 기동과 응답입니다. 상태 한 줄만 제출하면 앱 준비를 설명하지 못합니다. 세부 옵션은 systemd.service 공식 문서에서 확인하고 명령 목록의 확장은 더 읽기로 연결합니다.
따라하기
유닛의 실행 계약 읽기
유닛 ZIP의 User·WorkingDirectory·ExecStart를 아래 계약으로 완성합니다. 이 코드는 유닛 내용 분석이며 VM 기동 출력이 아닙니다.
import configparser
p=configparser.ConfigParser();p.read_string('[Service]\nUser=bcweb\nWorkingDirectory=/srv/bootcamp-m02/lab-root\nExecStart=/usr/bin/python3 -u /srv/bootcamp-m02/lab-root/service.py\n')
for k in ['User','WorkingDirectory','ExecStart']:print(k+'='+p['Service'][k])실행 결과
User=bcweb WorkingDirectory=/srv/bootcamp-m02/lab-root ExecStart=/usr/bin/python3 -u /srv/bootcamp-m02/lab-root/service.py
VM 배치 전 확인
앞 모듈을 끝낸 VM에서 계정·인터프리터·데이터를 조회합니다. 결과는 bcweb가 존재하고 기존 데이터 읽기가 허용되어야 합니다.
id bcweb
command -v python3
sudo -u bcweb test -r /srv/bootcamp-m02/lab-root/data/items.json
ss -ltn sport = :18080정의 설치와 기동
prepare.sh는 설치와 문법 검사·정의 재읽기만 합니다. 자연 종료한 이전 실행이 없을 때 start합니다. 20초 안에 상태와 응답을 관찰합니다. 출력은 VM에서 직접 기록합니다.
bash prepare.sh
sudo systemctl start bootcamp-systems.service
systemctl is-active bootcamp-systems.service
systemctl show bootcamp-systems.service -p MainPID -p User
curl -fsS http://127.0.0.1:18080/health
curl -fsS http://127.0.0.1:18080/items자동 확인과 종료 기록
유닛 starter TODO를 완성하고 실행합니다. 검증기는 자연 종료까지 기다리며 active 관측과 응답을 evidence에 남깁니다.
bash check.sh
cat evidence/service.md
systemctl is-enabled bootcamp-systems.service
systemctl is-active bootcamp-systems.service확인 문제
실습
유닛과 환경 파일의 TODO를 완성합니다. 실행 계정·작업 디렉터리·실행 경로·환경 전달을 명시하고 기동 중 active와 HTTP 응답을 각각 확인합니다. Linux VM external 검사이며 자연 종료 뒤 inactive가 예상됩니다.
실행 명령
bash check.sh
기대 결과
PASS unit: unit, account, HTTP, journal, backup hashes, restore; natural exit
모범 답안
모범 답안 내려받기더 읽기
면접 질문
- 프로세스와 systemd 서비스 상태의 차이를 설명합니다.