소개
이 새 환경의 DAYMARK에는 이미 안전한 게시 래퍼가 있습니다. 이제 팀에는 전용 보고서 계정으로 실행되는 실제 일정이 필요합니다. 터미널에서 수동으로 성공했다고 예약 작업이 입력을 찾거나 읽을 수 있다는 뜻은 아닙니다.
대응하는 systemd service와 timer를 구성하고 반복되는 실제 트리거를 관찰한 뒤, 마지막 보고서를 잃지 않으면서 디렉터리 및 입력 오류에서 복구합니다. Daymark는 업무 웹사이트이고 Workstation은 /srv/daymark-sales에서 시작합니다. 기본 터미널 사용 능력이면 충분하며 이전 가이드 실습의 셸 래퍼 개념을 다시 사용합니다. 계산기와 래퍼는 설치할 필요 없이 제공됩니다.
실제 timer에서 내보내기 실행하기
이 단계에서는 정확한 업무 결과를 확인하고 systemd가 내보내기를 두 번 실행하게 합니다. Daymark에서 Records를 엽니다. 초기 원본에는 11개, 3450센트의 데이터가 있습니다. Reports는 여전히 이전 마감인 TOTAL,1,100을 제공합니다. 작업은 이 파일을 실제 마감 결과로 교체해야 합니다.
Workstation으로 전환합니다. 이 환경은 독립적입니다. 올바른 래퍼는 준비되어 있지만 보고서 timer는 설치되지 않았습니다. cat은 파일을 출력하고 pwd는 현재 디렉터리를 출력합니다.
pwd
cat publish.sh
래퍼는 대상 옆에 쓰고 계산이 성공한 뒤에만 이름을 바꿉니다. 입력과 출력 인수를 받습니다. id는 계정 신원을 표시하고 ls -ld는 디렉터리 소유자와 접근 비트를 표시합니다. 디렉터리를 통과하려면 검색 권한, 파일을 만들려면 쓰기 권한이 필요합니다.
id daymark-report
ls -ld reports
준비된 시스템 계정이 reports/를 소유합니다. 입력의 읽기 권한과 상위 디렉터리의 검색 권한으로 orders.csv를 읽을 수 있으며 보고서 디렉터리 소유권으로 게시할 수 있습니다. root나 모두의 쓰기 권한을 지름길로 사용하지 마세요.
systemd는 이 instance의 서비스 관리자입니다. .service 파일은 한 번의 실행을, 같은 이름의 .timer는 실행 요청 시점을 설명합니다. Type=oneshot은 유한 작업이 끝나기를 기다립니다. User는 실제 실행 계정, WorkingDirectory는 상대 경로 orders.csv의 해석 위치를 선택합니다. ExecStart는 실행 파일, 래퍼와 출력에 절대 경로를 사용합니다. 터미널의 현재 디렉터리와 대화형 셸 설정은 시스템 서비스에 전달되지 않습니다. RemainAfterExit는 설정하지 마세요. 완료된 작업이 inactive가 되어야 다음 timer 이벤트가 다시 실행할 수 있습니다.
sudo tee FILE은 보호된 파일을 쓰면서 내용도 출력합니다. <<'UNIT'는 따옴표로 감싼 here-document입니다. 대응하는 끝 단어까지 붙여넣으세요. 지정된 D10 units만 만듭니다.
sudo tee /etc/systemd/system/d10-sales.service <<'UNIT'
[Unit]
Description=Daymark sales export
[Service]
Type=oneshot
User=daymark-report
WorkingDirectory=/srv/daymark-sales
ExecStart=/bin/bash /srv/daymark-sales/publish.sh orders.csv /srv/daymark-sales/reports/sales.csv
UNIT
이 연습 timer는 활성화 5초 뒤 시작하고 이전 활성화 20초 뒤 다음 실행을 요청합니다. AccuracySec=1s는 작은 일정 시간 창을 허용하며 머신이 추가 지연을 만들 수도 있습니다. 짧은 연습이지 실제 일일 운영 일정은 아닙니다. 매일 정해진 시각에 실행하려면 서버 시간대를 의도적으로 선택하고 두 상대 시간 지시문 대신 OnCalendar=*-*-* 23:00:00을 사용할 수 있습니다. 여기서는 실제 실행을 관찰하기 위해 짧은 일정을 유지합니다.
sudo tee /etc/systemd/system/d10-sales.timer <<'UNIT'
[Unit]
Description=Daymark short training schedule
[Timer]
OnActiveSec=5s
OnUnitActiveSec=20s
AccuracySec=1s
[Install]
WantedBy=timers.target
UNIT
daemon-reload는 unit 정의를 다시 읽습니다. enable --now는 다음 부팅을 위해 timer를 timers.target에 연결하고 지금도 시작합니다. 수동 내보내기가 아니라 timer를 시작합니다.
sudo systemctl daemon-reload
sudo systemctl enable --now d10-sales.timer
sleep 50은 작업을 실행하지 않고 기다립니다. service를 수동으로 시작하거나 셸 루프로 timer를 대신하지 마세요.
sleep 50
list-timers는 실제 LAST와 NEXT 트리거를 표시합니다. --no-pager는 스크롤 뷰어를 열지 않고 바로 출력합니다.
systemctl list-timers d10-sales.timer --no-pager
journal은 systemd의 실제 이벤트 로그입니다. -u는 이 unit을 선택하고 -n 20은 출력 수를 제한합니다. uid=... cwd=/srv/daymark-sales, 보고서 해시, 성공적인 완료가 있는 완전한 실행 두 번 이상이 보여야 합니다.
sudo journalctl -u d10-sales.service -n 20 --no-pager
숫자 uid를 id daymark-report와 비교합니다. 성공한 oneshot이 끝난 뒤 inactive (dead)가 되는 것은 정상이며 활성 timer가 다음 실행을 요청합니다. show -p는 특정 상태 속성을 선택합니다.
systemctl show d10-sales.service -p User -p WorkingDirectory -p Result -p ExecMainStatus --no-pager
User=daymark-report, 정확한 디렉터리, Result=success, ExecMainStatus=0이 나와야 합니다. 트리거가 없으면 systemctl status d10-sales.timer --no-pager를 읽고 이 unit 파일만 수정한 뒤 daemon-reload를 다시 실행하고 d10-sales.timer만 재시작합니다. restart는 해당 timer를 멈추고 시작하여 timer 편집을 적용합니다. 다시 기다린 뒤 journal을 살펴보세요. CHDIR는 WorkingDirectory를, Permission denied는 입력과 보고서 디렉터리 소유권을 확인하며 권한을 넓히지 마세요.
Daymark로 돌아가 Reports를 새로 고치고 새 CSV를 다운로드합니다. 합계는 TOTAL,11,3450입니다. Records를 다시 열고 홈으로 돌아가 정상 업무 페이지가 계속 제공되는지 확인합니다.
다음 예약 실행으로 복구하기
이 단계에서는 실제 예약 실패를 관찰하고 이전 보고서를 보존한 뒤 복구 후 새 마감을 게시합니다. Workstation에서 시작합니다. D10 units와 이 실습 입력만 다루며 무관한 서비스를 멈추지 마세요.
먼저 작업 디렉터리 오류를 만듭니다. sed -i는 지정 파일을 제자리에서 편집하고 s|old|new|는 일치하는 텍스트를 교체합니다. 의도적인 장애입니다.
sudo sed -i 's|WorkingDirectory=/srv/daymark-sales|WorkingDirectory=/tmp|' /etc/systemd/system/d10-sales.service
sudo systemctl daemon-reload
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager
프로세스는 여전히 보고서 계정으로 실행되지만 orders.csv가 /tmp에서 해석되어 Export failed: ... No such file ...로 실패합니다. 작업 디렉터리 자체가 없으면 래퍼 실행 전 CHDIR가 발생합니다. daemon-reload는 정의만 갱신하고 작업을 실행하지 않습니다. 이 실패는 timer가 일으킨 실제 시도입니다.
cat reports/sales.csv
보고서의 마지막은 여전히 TOTAL,11,3450이어야 합니다. Daymark에서 Reports를 새로 고치고 다운로드하여 같은 바이트가 여전히 사용 가능한지 확인합니다. Workstation으로 돌아와 디렉터리를 수정합니다.
sudo sed -i 's|WorkingDirectory=/tmp|WorkingDirectory=/srv/daymark-sales|' /etc/systemd/system/d10-sales.service
sudo systemctl daemon-reload
이제 입력 실패를 연습합니다. cp는 준비된 잘못된 fixture로 orders.csv만 덮어씁니다. 계산기는 0이 아닌 상태를 반환하고 래퍼는 마지막 보고서를 그대로 두어야 합니다.
cp fixtures/broken.csv orders.csv
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager
의도한 잘못된 숫자 오류가 나와야 합니다. show는 journal 보기 명령의 성공 여부와 독립적으로 실제 마지막 종료 상태를 표시합니다.
systemctl show d10-sales.service -p Result -p ExecMainStatus --no-pager
Result=exit-code와 ExecMainStatus=1이 나와야 합니다. 이전 보고서가 유지되는지 확인합니다.
cat reports/sales.csv
Tea가 두 개 추가된 유효한 새 마감으로 복구합니다. 다음 트리거에서 13개와 3950센트로 합계가 갱신되어야 합니다.
cp fixtures/next.csv orders.csv
sleep 30
sudo journalctl -u d10-sales.service -n 15 --no-pager
cat reports/sales.csv
Tea,5,1250과 TOTAL,13,3950이 나오고 journal에는 그 이후의 실제 게시가 있어야 합니다. 여전히 예전 결과라면 최신 오류를 읽고 디렉터리, 입력 이름이나 래퍼를 수정한 뒤 다음 timer 이벤트를 기다립니다. CSV를 손으로 교체하거나 service를 수동으로 시작하지 마세요. 실패한 oneshot도 이 timer에서 다시 실행될 수 있습니다.
Daymark에서 Records와 Reports를 새로 고치고 다시 다운로드하여 바뀐 원본을 TOTAL,13,3950과 비교합니다. 평가를 위해 timer를 활성 상태로 유지하세요. 이 실습은 재부팅 복구, 시간대 정책, 여러 머신의 동시 실행 또는 누락된 날짜의 정산을 시험하지 않습니다.
요약
완전한 CSV 게시, 의미 있는 실패 상태와 복구를 연습했습니다. 예약 보고서는 실제 실행 신원, 트리거, 업무 합계가 일치해야 유용합니다. 단일 instance 에서 가상 데이터와 짧은 연습 일정을 사용하는 실습이며 완전한 운영 보고서 플랫폼은 아닙니다.



