우분투 실전 명령어 | timeout으로 장기 실행 작업 멈추기
우분투 실전 명령어 | timeout으로 장기 실행 작업 멈추기
백업, 점검, 원격 호출처럼 끝나는 시간이 일정하지 않은 작업은 한 번 꼬이면 전체 배치가 같이 멈춥니다. timeout을 앞에 붙여 실행 시간을 강제로 제한해 두면 장애가 나도 다음 단계로 넘어가서 복구나 재시도를 설계하기 쉬워집니다.
언제 쓰는가
- 크론이나 배치에서 특정 명령이 가끔 무한 대기에 빠질 때
- 외부 API 호출, NFS 마운트 확인처럼 네트워크 상태에 따라 지연이 큰 작업을 감쌀 때
- 운영 점검 스크립트에서 "최대 N초만 실행" 규칙을 강제하고 싶을 때
바로 쓰는 명령어
# 1) 10초 넘으면 종료
timeout 10s curl -fsS https://api.example.com/health
# 2) 2분 제한으로 rsync 실행
timeout 2m rsync -a /data/ backup:/archive/
# 3) 종료 시그널을 TERM -> KILL 순서로 제어
timeout --signal=TERM --kill-after=5s 30s ./long-job.sh
# 4) 타임아웃 여부를 종료코드로 분기
timeout 15s ./check-queue.sh
rc=$?
if [ "$rc" -eq 124 ]; then
echo "TIMEOUT: check-queue.sh"
elif [ "$rc" -ne 0 ]; then
echo "ERROR: rc=$rc"
else
echo "OK"
fi
핵심 옵션/패턴
10s,2m,1h: 시간 단위 지정 (s,m,h,d)--signal=TERM: 제한 시간 초과 시 먼저 보낼 시그널 지정--kill-after=5s: 지정 시그널 후에도 안 끝나면 강제 종료까지 대기 시간- 종료코드
124: timeout으로 종료됨 - 종료코드
125~127: timeout 자체 실행 오류 또는 명령 실행 실패
명령 출력 예시
$ timeout 3s sleep 10
$ echo $?
124
$ timeout --signal=TERM --kill-after=2s 5s ./worker.sh
timeout: sending signal TERM to command './worker.sh'
$ echo $?
124
자주 하는 실수
timeout만 붙이고 종료코드 124를 따로 처리하지 않음- 타임아웃과 일반 실패를 분리하지 않으면 재시도 정책이 엉킵니다.
- DB 마이그레이션 같은 트랜잭션 작업을 너무 짧게 제한함
- 중간 종료가 더 큰 장애가 될 수 있으니 작업 성격에 맞는 제한 시간을 잡아야 합니다.
--kill-after없이 TERM만 보내고 끝났다고 착각함- 프로세스가 TERM을 무시할 수 있어서 후속 강제 종료 정책이 필요합니다.
검증 방법
# 1) 의도적으로 타임아웃 발생시키기
timeout 2s bash -c 'sleep 5'
echo "rc=$?" # 기대값: rc=124
# 2) 정상 완료 케이스 확인
timeout 5s bash -c 'sleep 1'
echo "rc=$?" # 기대값: rc=0
# 3) 운영 스크립트에서 로그 남기기
run_with_timeout() {
local limit="$1"; shift
timeout "$limit" "$@"
local rc=$?
if [ "$rc" -eq 124 ]; then
echo "[WARN] timeout limit=${limit} cmd=$*"
fi
return "$rc"
}
run_with_timeout 10s curl -fsS https://api.example.com/health
운영 팁
- 크론 작업은
timeout + flock조합으로 실행 시간과 중복 실행을 같이 막아두면 안정성이 확 올라갑니다. - 제한 시간은 평균 실행 시간의 2~3배부터 시작하고, 실제 로그를 보면서 조정하는 게 안전합니다.
- 타임아웃 발생 시점과 대상 명령을 로그에 남겨야 다음 장애 때 원인 추적이 빨라집니다.
출처
- GNU Coreutils timeout 문서
- Ubuntu manpage timeout
- systemd.service 문서