스스로 다시 시작하는 작업 중지하기

LinuxBeginner
지금 연습하기

소개

Status Desk는 보통 작은 캐시를 매분 갱신합니다. 그런데 낯선 업로더도 내부 수집기로 합성 실습 요청을 보냅니다. 중지하면 나아진 듯하지만 다시 돌아옵니다. 정상 상태 갱신은 유지하면서 반복 실행 원인을 제거해야 합니다.

기본 터미널 사용법만 알면 됩니다. Status Server는 대상 컨테이너 안의 허가된 관리자 셸이며 /srv/status에서 시작합니다. Status Desk는 수집기의 실제 카운터를 표시합니다. 두 컨테이너는 실습 인스턴스의 커널을 공유합니다. 데이터와 요청은 모두 무해합니다. 이 실습은 cron 반복 실행을 다루며 운영 호스트 전체 조사에 해당하지 않습니다.

다시 나타나는 프로그램 관찰하기

이 단계에서는 실행 중인 업로더를 중지하고 인스턴스 하나를 종료해도 원인이 사라지지 않는 이유를 살펴봅니다.

Status Desk를 엽니다. refreshes는 성공한 캐시 갱신 요청 수이며 매분 늘어나야 합니다. uploads는 원치 않는 실습 요청 수이며 보통 5초마다 하나씩 늘어납니다. 복구 후에도 과거 카운터는 남습니다. 페이지를 새로 고쳐 현재 값을 확인하세요.

Status Server로 전환합니다. 프로세스는 실행 중인 프로그램입니다. PID는 특정 인스턴스를 식별하고 경로와 인수는 실행 내용을 알려 줍니다. ps는 프로세스를 나열합니다. -e는 전체를 선택하고 -o는 PID, 부모 PID(PPID), 인수를 포함한 전체 명령 열을 지정합니다.

ps -eo pid,ppid,args

/usr/bin/python3 /opt/status/uploader.py upload를 찾습니다. Python은 인터프리터, /opt/status/uploader.py는 프로그램 파일이며 upload는 실습 동작을 선택합니다. 근처의 flock 프로세스는 cron이 여러 복사본을 동시에 만들지 못하도록 잠금을 유지합니다. 캐시 갱신 프로그램은 건드리지 마세요.

시그널은 프로세스에 보내는 요청입니다. TERM은 정상 종료를 요청합니다. 다음 pkill은 -f로 전체 명령줄을 선택합니다. 따옴표 안 패턴의 ^와 $는 시작과 끝을 고정하여 부모나 현재 셸 대신 이 Python 작업 프로세스만 선택합니다. 한 번 실행하세요.

pkill -TERM -f '^/usr/bin/python3 /opt/status/uploader.py upload$'

출력이 없어도 정상입니다. 일치 항목이 없으면 모든 Python 프로세스로 패턴을 넓히지 말고 목록을 다시 확인합니다. 종료할 시간을 1초 준 뒤 목록을 다시 표시합니다.

sleep 1
ps -eo pid,ppid,args

Python 업로더가 없어야 합니다. 체크포인트는 원래 인스턴스가 종료되었음을 확인할 뿐, 호스트 정리가 끝났음을 뜻하지 않습니다.

sleep은 지정한 초만큼 기다립니다. 실제 분 경계를 적어도 한 번 지나도록 80초 기다린 뒤 목록을 표시합니다.

sleep 80
ps -eo pid,ppid,args

같은 경로와 upload 인수가 새 PID로 돌아와야 합니다. 부모 연결에는 스케줄러의 작업 실행 프로세스인 CRON이 포함됩니다. 새 PID는 새 실행이라는 뜻이며 기반 작업이 달라진 것은 아닙니다. 환경이 바빠 실행이 지연되면 20초 더 기다려 다시 나열합니다. Status Desk를 새로 고치면 업로드가 재개되고 정상 갱신도 계속됩니다. 이제 무엇이 프로그램을 시작하는지 찾아야 합니다.

반복 실행 원인을 찾아 비활성화하기

이 단계에서는 돌아온 프로세스를 특정 일정과 연결하고 정상 작업을 남기면서 해당 항목만 비활성화합니다.

Cron은 데몬, 즉 백그라운드에서 예약 명령을 시작하는 서비스입니다. 사용자 crontab은 계정 하나의 작업을 담습니다. 이 터미널은 실습 컨테이너 내부의 root이므로 crontab -l은 그 대상 계정의 일정을 표시하며 플랫폼 계정에는 영향을 주지 않습니다.

crontab -l

다음과 같이 표시됩니다.

* * * * * /usr/bin/flock -n /run/uploader.lock /usr/bin/python3 /opt/status/uploader.py upload

처음 다섯 필드는 분, 시, 일, 월, 요일입니다. *는 모든 값을 뜻하므로 * * * * *는 매분 실행합니다. 그 뒤는 명령입니다. flock -n은 기다리지 않고 잠금을 얻습니다. 다른 업로더가 이미 잠금을 소유하면 중복 호출은 종료됩니다. 실행 대상이 중지한 프로세스와 일치합니다.

시스템 일정은 /etc/cron.d/에도 있습니다. ls는 파일 목록, cat은 짧은 파일 내용을 표시합니다. 디렉터리 뒤의 *는 그 안의 파일들로 확장됩니다.

ls /etc/cron.d
cat /etc/cron.d/*

status-cache 파일에는 다음 내용이 있습니다.

* * * * * root /usr/bin/python3 /opt/status/cache-refresh.py refresh

사용자 crontab과 달리 시스템 cron 파일은 시간 필드 다섯 개와 명령 사이에 계정 필드가 있으며 여기서는 root입니다. 이 허가된 명령이 Status Desk를 갱신합니다. 일정이 비슷하다는 이유만으로 허가되지 않은 작업은 아닙니다. 패키지가 제공한 다른 유지보수 항목은 남겨도 됩니다.

안전하게 편집하려면 먼저 현재 사용자 일정을 작업용 텍스트 파일로 복사합니다. >는 목록을 파일에 쓰며 기존 복사본은 덮어씁니다. 편집 전에 한 번만 실행하세요. 반복하면 편집한 초안을 덮어씁니다.

crontab -l > /srv/status/root.cron

nano는 텍스트 편집기를 엽니다. 업로더 행 맨 앞에 #를 추가합니다. Cron은 #로 시작하는 주석을 무시합니다. 복구를 위해 내용은 남기고 다른 항목은 바꾸지 않습니다.

nano /srv/status/root.cron

방향키로 행 맨 앞으로 이동하고 #를 입력합니다. Ctrl+O, Enter로 저장하고 Ctrl+X로 나옵니다. 편집한 파일 경로를 crontab에 전달하여 설치합니다.

crontab /srv/status/root.cron
crontab -l

업로더 행은 #로 시작해야 합니다. Cron은 변경을 자동으로 다시 읽으므로 재시작할 필요가 없습니다. 작업 복사본만 주석 처리해서는 부족하며 설치해야 합니다. 다른 행을 잘못 바꿨다면 초안을 다시 열어 복구하고 재설치합니다. 일정 제거는 이미 실행 중인 프로세스를 종료하지 않으므로 현재 업로더는 계속 동작할 수 있습니다.

실행 중인 복사본을 제거하고 복구 확인하기

이 단계에서는 정리를 완료하고 온전한 일정 간격 동안 원치 않는 활동과 업무 기능을 비교합니다.

동일한 정확한 패턴으로 현재 Python 업로더를 중지합니다.

pkill -TERM -f '^/usr/bin/python3 /opt/status/uploader.py upload$'

이미 없다면 일치 항목 없이 종료되는 것은 예상된 결과이므로 계속합니다. 작업 프로세스가 종료되도록 1초 기다립니다.

sleep 1

curl은 네트워크 요청을 보냅니다. -sS는 진행 표시를 숨기고 오류는 보여 줍니다. 이 URL은 Status Server에서 접근 가능한 내부 수집기 컨테이너를 가리킵니다. /state는 현재 카운터와 최신 요청의 Unix 타임스탬프를 반환합니다.

curl -sS http://collector:8080/state

uploads, refreshes, last_refresh를 확인한 뒤 실제 cron이 실행되도록 기다립니다.

sleep 80
curl -sS http://collector:8080/state

uploads는 같아야 하고 refreshes와 last_refresh는 증가해야 합니다. Status Desk를 새로 고치면 같은 사실을 볼 수 있습니다. 이전 업로드는 증거로 남습니다. 카운터를 지우면 이력이 숨겨질 뿐 반복 실행이 해결되지는 않습니다.

프로세스를 다시 나열합니다.

ps -eo pid,ppid,args

cron -f는 계속 있어야 합니다. -f는 이 컨테이너의 데몬을 포그라운드로 유지합니다. 업로더는 없는 상태를 유지해야 합니다. 체크포인트는 독립적으로 80초를 더 관찰하므로 채점에 약 90초가 걸립니다. 설정과 실제 상태만 읽습니다.

업로드가 늘면 cron 위치 두 곳과 주석 처리한 사용자 crontab의 설치 여부를 다시 확인합니다. 갱신이 멈추면 허가된 status-cache 항목을 복원합니다. 증상을 숨기려고 cron을 중지하거나 모든 일정을 지우지 마세요. 상태 서비스에 필요한 작업입니다. 이 복구는 실습한 cron 메커니즘을 제거하며 실제 호스트에 다른 지속성 메커니즘이 전혀 없다는 증거는 아닙니다.

요약

프로세스 인스턴스와 실행 주체를 구별하고 부모 연결을 따라 cron을 찾았습니다. 사용자 및 시스템 일정을 살펴보고 원치 않는 실행 항목 하나를 비활성화했으며, 새 업로드가 없는 1분 동안 실제 업무 갱신이 계속됨을 확인했습니다.