Published on

timeout linux command example: 실행 시간 제한과 종료 코드

Authors
  • avatar
    Name
    Indo Yoon
    Twitter

timeout은 GNU coreutils에 포함된 명령으로, 지정한 시간이 지나면 실행 중인 명령에 신호를 보내 중단시켜요. 별도 패키지를 설치하지 않아도 대부분의 리눅스 배포판에서 바로 쓸 수 있어서, 배포 스크립트나 헬스 체크에서 응답 없는 작업을 정리할 때 가장 간단한 수단이 돼요. 아래에서는 기본 문법과 옵션, 종료 코드를 읽는 방법, 운영 상황별 선택 기준을 예제와 함께 정리해요.

한눈에 보기

timeout은 "이 시간 안에 끝나지 않으면 중단한다"는 규칙을 셸 수준에서 강제하는 도구예요. 애플리케이션 코드를 고치지 않고도 외부 호출에 상한을 걸 수 있다는 점이 가장 큰 장점이고, 반대로 신호 전달 범위와 종료 코드 해석을 잘못 이해하면 실패 원인을 놓치기 쉬워요.

  • 형식은 timeout [옵션] 시간 명령어 [인자...] 순서예요.
  • 시간 값은 숫자 뒤에 단위 접미사를 붙여 지정하고, 접미사를 생략하면 기본 단위가 적용돼요.
  • 시간이 지나면 기본 신호로 프로세스를 종료하고, -s로 다른 신호를 지정할 수 있어요.
  • --kill-after를 쓰면 첫 신호 이후 강제 종료 신호를 한 번 더 예약할 수 있어요.
  • 종료 코드를 보면 시간 초과인지 명령 자체의 실패인지 구분할 수 있어요.
  • --foreground는 터미널 입력이나 job control이 필요한 프로그램을 감쌀 때 필요해요.

기본 문법과 옵션 비교

기본 형태는 timeout [OPTION] DURATION COMMAND [ARG]...이에요. 시간 값은 숫자와 단위 접미사로 이루어지고, s, m, h, d 같은 접미사로 단위를 명시할 수 있어요. 접미사를 생략하면 기본 단위가 적용되므로, 스크립트에서는 단위를 명시하는 편이 읽기에도 안전해요.

옵션하는 일이런 때 써요
-s, --signal시간 초과 시 보낼 신호를 지정정상 종료 절차를 거치게 하고 싶을 때
-k, --kill-after첫 신호 이후 추가 대기 후 강제 종료 신호를 보냄신호를 무시하는 프로세스를 확실히 정리할 때
--preserve-status명령의 종료 상태를 그대로 반환CI나 배포 스크립트에서 원래 결과를 유지할 때
--foregroundtimeout이 별도 프로세스 그룹을 만들지 않음터미널 입력이나 job control이 필요할 때
-v, --verbose시간 초과 시 진단 메시지를 출력로그에서 원인을 빠르게 확인할 때

옵션은 반드시 명령 앞에 와야 해요. 실행할 명령과 그 인자는 시간 값 뒤에 오고, 인자에 하이픈으로 시작하는 값이 들어가면 구분이 모호해질 수 있으니 스크립트에서는 인용부호를 함께 쓰는 편이 좋아요.

단계별 사용 방법

가장 단순한 형태로 걸어 보기

timeout 10 sleep 30
echo $?

제한 시간을 넘기면 timeout이 종료를 시도하고, 셸에는 시간 초과를 뜻하는 종료 코드가 남아요. 반대로 명령이 먼저 끝나면 그 명령의 종료 코드가 그대로 전달돼요. 이 차이를 이용하면 스크립트에서 "느려서 실패한 것"과 "명령이 실패한 것"을 나눌 수 있어요.

신호를 바꿔 정리 시간 주기

timeout -s INT 10 ./long-task.sh

INT 신호를 보내면 프로그램이 정리 루틴을 실행할 기회를 가질 수 있어요. 웹 서버나 워커처럼 종료 훅이 있는 프로세스에 잘 맞고, 기본 신호로는 정리가 끝나기 전에 끊기는 프로그램에도 유용해요.

강제 종료를 예약하기

timeout -k 5 30 ./worker.sh

첫 신호를 보낸 뒤에도 프로세스가 남아 있으면 추가로 KILL 신호를 보내요. 정리 루틴이 멈춰 있는 상황에서도 프로세스를 확실히 회수할 수 있어서, 배포 파이프라인처럼 다음 단계로 넘어가야 하는 자리에 자주 써요.

스크립트에서 결과 분기하기

if timeout 10 curl -fsS https://example.com/health; then
  echo "healthy"
else
  echo "failed or timed out: $?"
fi

시간 초과와 명령 실패를 구분해야 한다면 --preserve-status를 함께 검토해요. 이 옵션을 쓰면 timeout이 자체 코드로 결과를 덮어쓰지 않고 자식 프로세스의 상태를 그대로 넘겨요. 반대로 "시간 초과 자체를 감지"하는 것이 목적이라면 옵션 없이 쓰는 편이 단순해요.

파이프라인 전체에 적용하기

timeout 10 bash -c 'producer | consumer'

파이프라인 전체에 상한을 걸려면 셸을 하나 더 감싸는 방식이 안전해요. timeout은 자신이 실행한 프로세스에만 신호를 보내므로, 여러 프로세스를 묶어서 다룰 때는 서브셸이나 별도 스크립트로 감싸야 해요.

상황별 선택 가이드

  • 배포 스크립트의 외부 API 호출: 짧은 제한과 --kill-after를 조합해요. 응답이 없으면 다음 단계로 넘어가야 하므로 길게 붙잡지 않는 편이 좋아요.
  • 데이터베이스 마이그레이션: 넉넉한 제한을 두고 TERM으로 정리 시간을 줘요. 중간에 강제로 끊으면 락이나 임시 객체가 남을 수 있어요.
  • CI 잡: --preserve-status로 원래 종료 코드를 유지하고, -v로 진단 메시지를 로그에 남겨요. 실패 원인을 나중에 추적하기 쉬워져요.
  • 터미널 제어가 필요한 프로그램: --foreground를 사용해요. 그렇지 않으면 TTY 입력이 끊기거나 job control이 어긋날 수 있어요.
  • 컨테이너 진입점: 컨테이너의 첫 프로세스에 신호가 제대로 전달되는지 함께 확인해요. timeout이 만든 프로세스 그룹 구조가 신호 전달 범위를 바꿀 수 있어요.

주의할 점

timeout은 자식 프로세스를 별도 프로세스 그룹으로 실행해요. 그래서 신호가 그룹 전체로 퍼지지 않고 timeout이 직접 띄운 프로세스에만 갈 수 있어요. 자식이 다시 자식을 띄우는 구조라면 정리되지 않는 프로세스가 남을 수 있으니, 프로세스 트리를 함께 확인해야 해요.

TERM을 무시하도록 작성된 프로그램은 KILL 없이는 남아 있을 수 있어요. 정리 루틴이 필요한 프로그램에는 유예 시간을 주고, 그렇지 않으면 강제 종료를 예약하는 편이 안전해요.

셸 내장 명령이나 셸 함수에는 직접 걸 수 없어요. bash -c로 감싸서 별도 프로세스로 실행해야 하고, 이때 인용부호 처리에 주의해야 해요. 또한 시간 값에 단위를 붙이지 않으면 기본 단위로 해석되므로, 스크립트에서는 단위를 명시하는 편이 읽기 좋아요.

종료 코드만 보고 원인을 단정하지 말고 로그를 함께 봐요. 시간 초과인지, 신호로 종료됐는지, 명령이 스스로 실패했는지는 코드와 로그를 같이 볼 때 정확히 갈라져요. --foreground를 쓰면 프로세스 그룹 분리가 사라져 신호 전달 범위가 달라진다는 점도 기억해 두세요.

자주 묻는 질문

timeout은 별도로 설치해야 하나요?

GNU coreutils에 포함되어 있어서 대부분의 배포판에 기본으로 있어요. timeout --version으로 존재 여부를 확인할 수 있고, 없다면 coreutils 패키지 설치 상태를 확인하면 돼요.

시간 초과와 명령 실패를 스크립트에서 어떻게 구분하나요?

기본 동작에서는 시간 초과 시 전용 종료 코드가 반환되고, 그 외에는 명령의 종료 코드가 전달돼요. --preserve-status를 쓰면 시간 초과여도 명령의 상태가 유지되므로, 구분이 필요할 때는 옵션 없이 쓰는 편이 좋아요.

TERM 신호를 무시하는 프로세스는 어떻게 정리하나요?

--kill-after로 첫 신호 이후 강제 종료 신호를 예약해 두면 돼요. 정리 시간이 필요한 프로그램에는 짧은 유예를 주고, 그렇지 않으면 바로 KILL을 쓰는 편이 안전해요.

파이프라인 전체에 제한을 걸려면 어떻게 하나요?

bash -c로 파이프라인을 감싸고 그 셸에 timeout을 걸어요. timeout은 자신이 실행한 프로세스에만 신호를 보내므로, 묶음 단위로 감싸는 것이 핵심이에요.

--foreground는 언제 써야 하나요?

timeout이 별도 프로세스 그룹을 만들지 않게 하고 싶을 때 써요. 대화형 입력을 받거나 job control이 필요한 프로그램을 감쌀 때 필요하고, 일반 배치 작업에서는 기본 동작으로 충분해요.

출처

배포 스크립트에서 실패를 다루는 방식은 서버 운영 가이드와 헬스 체크 설계에서 이어서 확인할 수 있어요.