ssh nohup exit 255 와 pgrep 완료 감시 함정 해결

요약

겪은 일: ssh 로 nohup 작업을 띄우면 exit 255 로 자주 실패하고, pgrep -f 로 감시하면 작업이 끝나도 계속 "진행 중"으로 보입니다.

원인: 백그라운드로 떼어 내는 순간 ssh 채널이 비정상으로 닫히고, pgrep -f 명령은 자기 명령줄에 든 패턴으로 자기 자신을 찾습니다.

이렇게 풀었다: ssh 는 원격 명령이 끝날 때까지 붙잡고 그 ssh 호출을 로컬에서 백그라운드로 돌리며, 완료는 로그 끝의 표식으로 확인합니다.

원격 서버에 몇십 분, 몇 시간 걸리는 작업을 띄우는 일은 흔합니다. 그런데 "띄우기"와 "끝났는지 알기" 둘 다에서 실수가 나왔습니다. 특히 완료 판정을 틀리면 이미 끝난 작업을 한참 기다리게 됩니다.

띄우기도 실패하고 끝났다는 판정도 틀렸다

한 일 본 것 실제
ssh "nohup cmd &" exit 255 여러 번 다시 해도 반복, 시작조차 안 된 경우도 있음
pgrep -f 로 완료 감시 계속 진행 중 작업은 진작 끝났고 18분 넘게 헛기다림
로그 마지막 줄 확인 정상 가동 중이라고 판단 2시간 45분 전에 이미 죽어 있었음
로그의 flock ... skip 7시간 정지라고 판단 겹침을 막는 정상 동작

연결 자체는 되었습니다. 같은 ssh 로 echo 를 하면 출력이 나왔습니다. 문제는 백그라운드로 떼어 내는 명령에서만 생겼습니다.

떼어 내는 순간 ssh 가 비정상 종료한다

ssh "nohup cmd &" 나 setsid ... </dev/null & 처럼 원격에서 프로세스를 분리하면, 그 시점에 ssh 세션이 비정상으로 끝나며 255 를 돌려주는 일이 잦았습니다. 원격 프로세스가 아예 시작되지 않았거나, 시작됐더라도 로컬에서는 언제 끝나는지 추적할 길이 없었습니다.

이 실패는 다시 해 본다고 사라지지 않았습니다. 같은 명령을 여러 번 되풀이해도 255 가 반복됐고, 그때마다 원격에서 작업이 떴는지 안 떴는지를 따로 확인해야 했습니다. 떼어 내는 방식을 고집하기보다 띄우는 방식 자체를 바꾸는 편이 빨랐습니다.

pgrep -f 는 자기 자신을 찾는다

pgrep -f 패턴 은 명령줄 전체에서 패턴을 찾습니다. 감시 스크립트가 pgrep -f "run_job" 을 부르면 그 감시 명령의 명령줄에도 run_job 이 들어 있습니다. 감시 스크립트가 둘 이상이면 서로의 pgrep 을 잡아 무한 대기가 되기도 합니다.

로그 시각과 skip 문구는 생존의 증거가 아니다

로그 마지막 줄은 "마지막으로 무언가 적힌 때"일 뿐입니다. skip 이나 대기 문구도 그것이 설계된 동작인지 코드를 봐야 압니다.

1. ssh 는 끝까지 붙잡고, 그 ssh 를 백그라운드로

ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=20 [email protected] \
  "cd /opt/job && python3 run_job.py > job.log 2>&1; echo DONE >> job.log" &

원격에서는 포그라운드로 작업이 끝날 때까지 돌고, 로컬에서 이 ssh 호출 전체를 백그라운드로 돌립니다. keepalive 옵션으로 오래 조용해도 연결이 끊기지 않게 합니다.

2. 진행은 짧은 ssh 로 따로 보기

ssh [email protected] "tail -n 5 /opt/job/job.log"

3. 완료는 표식으로

ssh [email protected] "grep -q '^DONE$' /opt/job/job.log && echo finished || echo running"

프로세스를 꼭 봐야 한다면 PID 를 잡아 ps -p PID 로 보거나, pgrep 에 실행 파일 경로까지 넣습니다.

pgrep -f "python3 /opt/job/run_job.py"

고쳐졌는지 확인하는 법

  • 로컬 백그라운드 ssh 가 끝났을 때 로그 끝에 DONE 이 있는지 봅니다. 없으면 중간에 죽은 것입니다.
  • "돌고 있나"는 로그가 아니라 프로세스 목록으로 확인합니다.
  • 남은 시간을 말해야 하면 실제로 처리된 개수와 걸린 시간으로 다시 계산합니다. 처음 예상만 믿으면 같은 질문을 두 번 받습니다.

판정을 틀리면 생기는 일

완료 판정이 틀리면 두 방향으로 손해가 납니다. 끝난 작업을 끝나지 않았다고 보면 다음 일을 시작하지 못하고 기다리게 됩니다. 반대로 죽은 작업을 살아 있다고 보면 결과가 나올 때를 기다리다 한참 뒤에야 다시 돌려야 한다는 것을 압니다.

정상 동작을 고장으로 보는 것도 비용이 큽니다. 겹침 방지용 skip 문구를 정지로 읽었을 때는 멀쩡한 작업을 두고 "7시간 정지"라는 잘못된 경보를 냈습니다. 그래서 로그에서 낯선 문구를 보면 판단하기 전에 그 문구를 찍는 코드부터 찾아 읽는 순서를 지키고 있습니다.

확인한 환경

항목 내용
로컬 윈도우 PC 의 Git Bash 와 ssh
원격 리눅스 서버, 파이썬 장시간 작업, flock 으로 겹침 방지

관련 글: 윈도우 SSH 키 권한 오류, Git Bash 에서만 접속될 때, ssh 너머로 정규식, 백슬래시를 넘기면 조용히 틀리는 이유

이 글의 내용은 2026년 10월 5일에 마지막으로 확인했습니다. 틀린 곳을 발견하시면 연락처로 알려 주세요.