Linux / 명령어 / nohup - 로그아웃 후에도 명령 계속 실행
nohup은 터미널 연결이 끊길 때 전송될 수 있는 SIGHUP 신호를 무시하도록 명령을 실행하는 도구입니다. 로그아웃 후에도 작업을 계속하려면 일반적으로 nohup과 백그라운드 실행 기호 &를 함께 사용하고, 표준 입력과 출력 파일도 명시적으로 지정하는 것이 좋습니다.
가장 실용적인 기본 형태는 다음과 같습니다.
nohup ./worker.sh > worker.log 2>&1 < /dev/null &
다만 nohup은 프로세스를 감시하거나 재시작하는 서비스 관리자가 아닙니다. 재부팅 후 자동 시작, 실패 시 재시작, 로그 순환이 필요한 장기 서비스라면 systemd 같은 서비스 관리 도구가 더 적합합니다.
nohup은 무엇을 하는 명령어인가요?
nohup은 지정한 명령이 행업(hangup) 신호인 SIGHUP을 무시하도록 설정한 뒤 그 명령을 실행합니다. 터미널을 닫거나 SSH 연결을 종료할 때 셸과 관련 프로세스에 SIGHUP이 전달될 수 있는데, 이를 무시하면 작업이 계속 실행될 가능성이 높아집니다.
GNU Coreutils의 nohup 공식 설명에서 확인할 수 있듯이 nohup 자체는 명령을 백그라운드로 보내지 않습니다. 현재 터미널에서 다른 작업을 계속하려면 명령 끝에 &를 별도로 붙여야 합니다.
| 구성 요소 | 하는 일 | 하지 않는 일 |
|---|---|---|
nohup |
실행할 명령이 SIGHUP을 무시하게 합니다. |
자동으로 백그라운드 실행하지 않습니다. |
& |
셸이 명령을 백그라운드 작업으로 실행하게 합니다. | SIGHUP을 무시하도록 보장하지 않습니다. |
| 출력 리디렉션 | 표준 출력과 오류를 지정한 로그 파일로 보냅니다. | 로그 크기 제한이나 자동 삭제를 하지 않습니다. |
기본 문법과 권장 실행 형태
기본 문법
nohup 뒤에 실행할 명령과 인수를 차례로 적습니다.
nohup command [arg ...]
예를 들어 현재 디렉터리의 backup.sh를 실행하려면 다음과 같이 입력합니다.
nohup ./backup.sh
이 형태는 SIGHUP을 무시하지만 포그라운드에서 실행됩니다. 따라서 명령이 끝나기 전까지 같은 셸에서 다음 명령을 입력하기 어렵습니다.
백그라운드 실행과 로그 저장
실제 작업에서는 백그라운드 실행과 로그 경로를 함께 지정하는 편이 관리하기 쉽습니다.
nohup ./backup.sh > backup.log 2>&1 < /dev/null &
> backup.log는 표준 출력을 새 로그 파일에 기록합니다. 같은 파일이 있으면 기존 내용을 덮어씁니다.2>&1은 표준 오류를 현재 표준 출력과 같은 곳으로 보냅니다.< /dev/null은 프로그램이 터미널 입력을 기다리지 않게 표준 입력을 닫힌 입력원으로 바꿉니다.- 마지막
&는 명령을 백그라운드에서 실행합니다.
기존 로그 뒤에 새 내용을 이어 쓰려면 > 대신 >>를 사용합니다.
nohup ./backup.sh >> backup.log 2>&1 < /dev/null &
실행 직후 PID 저장하기
백그라운드 명령을 실행한 직후의 $!에는 가장 최근에 백그라운드로 시작한 작업의 프로세스 ID(PID)가 들어 있습니다. 나중에 상태를 확인하거나 종료하려면 이 값을 안전한 위치에 기록해 두는 것이 편리합니다.
nohup ./backup.sh > backup.log 2>&1 < /dev/null & job_pid=$! printf '%s\n' "$job_pid" > backup.pid
PID 파일은 해당 작업을 관리하는 사용자만 쓸 수 있는 디렉터리에 두세요. 오래된 PID 파일이 남아 있으면 같은 번호를 나중에 다른 프로세스가 사용할 수 있으므로, 종료 전에 명령과 시작 시각도 함께 확인하는 것이 안전합니다.
표준 입력과 출력은 어떻게 처리되나요?
표준 입력
GNU 구현에서 표준 입력이 터미널에 연결되어 있으면 nohup은 읽을 수 없는 입력원으로 바꿉니다. 이 동작은 터미널이 사라진 뒤 프로그램이 입력을 기다리며 멈추는 상황을 줄여 줍니다. 구현 차이를 줄이고 의도를 명확히 하려면 명령에 < /dev/null을 직접 적을 수 있습니다.
표준 출력과 nohup.out
표준 출력이 터미널을 향하고 있고 별도의 리디렉션을 지정하지 않으면 GNU nohup은 현재 디렉터리의 nohup.out에 출력을 이어 씁니다. 현재 디렉터리에 파일을 만들 수 없으면 사용자의 홈 디렉터리에 있는 nohup.out을 시도하며, 두 위치 모두 쓸 수 없으면 명령을 실행하지 않습니다.
여러 작업이 같은 nohup.out을 공유하면 어느 작업의 로그인지 구분하기 어렵고 파일도 계속 커질 수 있습니다. 작업별로 이름과 보관 정책을 정한 로그 파일을 지정하는 편이 좋습니다.
표준 오류
표준 오류가 터미널을 향하면 GNU nohup은 일반적으로 표준 출력과 같은 대상으로 보냅니다. 하지만 셸, 운영체제, 앞서 적용한 리디렉션에 따라 읽는 사람이 결과를 오해할 수 있으므로 2>&1처럼 의도를 명시하는 것이 안전합니다. 셸의 입출력 연결 순서는 결과에 영향을 주므로 자세한 원리는 GNU Coreutils 입출력 리디렉션 설명에서 확인할 수 있습니다.
실행 상태와 로그 확인하기
저장한 PID로 프로세스 확인하기
실행 직후 저장한 PID가 있다면 ps에 직접 전달하여 상태를 확인할 수 있습니다.
job_pid=$(cat backup.pid) ps -p "$job_pid" -o pid,ppid,stat,etime,cmd
PID는 프로세스 번호, PPID는 부모 프로세스 번호, STAT는 상태, ELAPSED는 실행 시간입니다. PID가 존재한다는 사실만으로 원하는 작업이라고 단정하지 말고 마지막의 명령 열도 함께 확인하세요.
이름으로 프로세스 찾기
PID를 저장하지 않았다면 pgrep로 명령행을 검색할 수 있습니다.
pgrep -af 'backup.sh'
같은 문자열을 포함한 다른 프로세스도 검색될 수 있으므로 결과의 전체 명령행을 확인해야 합니다. 단순히 ps 결과를 grep에 연결하는 방식은 검색 명령 자체가 함께 나타나기 쉬워 자동화에 적합하지 않습니다.
로그를 실시간으로 확인하기
tail -f를 사용하면 파일 끝에 추가되는 내용을 계속 확인할 수 있습니다.
tail -f backup.log
로그 감시를 끝내려면 Ctrl+C를 누릅니다. 이는 tail만 종료하며 로그를 작성하는 원래 작업은 종료하지 않습니다. tail 명령어 사용법에서 줄 수 지정과 파일 추적 방법을 더 자세히 볼 수 있습니다.
nohup으로 시작한 프로세스 종료하기
먼저 정상 종료 요청하기
대상 PID와 명령을 확인한 다음 kill을 실행하면 기본적으로 SIGTERM 신호를 보냅니다. 프로그램이 종료 처리 코드를 갖고 있다면 파일을 닫고 상태를 정리할 기회를 얻습니다.
job_pid=$(cat backup.pid) ps -p "$job_pid" -o pid,ppid,stat,etime,cmd kill "$job_pid"
종료 여부 확인하기
잠시 기다린 뒤 같은 PID를 다시 조회합니다.
ps -p "$job_pid" -o pid,stat,etime,cmd
셸 스크립트가 여러 자식 프로세스를 만들었다면 부모 하나를 종료해도 자식이 남을 수 있습니다. 프로세스 트리와 프로세스 그룹을 먼저 확인하고, 사용하는 프로그램이 제공하는 공식 종료 명령이 있다면 그것을 우선하세요.
강제 종료는 마지막 수단으로 사용하기
SIGTERM에 반응하지 않는다는 이유만으로 바로 강제 종료하면 데이터 저장이나 임시 파일 정리가 끝나지 않을 수 있습니다. 원인과 대상이 정확한지 확인한 뒤 마지막 수단으로만 SIGKILL을 사용합니다.
kill -KILL "$job_pid"
파이프라인과 복합 명령 실행하기
하나의 셸 명령으로 묶기
파이프라인, 여러 리디렉션, 조건 연산자를 하나의 작업으로 실행하려면 셸에 명령 문자열을 전달할 수 있습니다.
nohup sh -c 'producer | consumer' > pipeline.log 2>&1 < /dev/null &
이때 따옴표 안의 파이프라인은 새 셸이 해석합니다. 외부 입력을 검증 없이 명령 문자열에 합치면 명령 주입 위험이 생기므로, 신뢰할 수 없는 값을 직접 끼워 넣지 마세요. 셸 연산자의 실행 관계는 Bash 명령 연결 연산자 사용법도 참고할 수 있습니다.
로그가 바로 보이지 않을 때
프로세스는 실행 중인데 로그가 늦게 나타난다면 nohup보다 프로그램의 출력 버퍼링이 원인일 수 있습니다. 프로그램 자체의 로그 플러시 설정을 우선 확인하세요. GNU 계열 환경에서는 프로그램과 출력 방식이 호환되는 경우 stdbuf로 줄 단위 버퍼링을 요청할 수도 있습니다.
nohup stdbuf -oL -eL ./worker > worker.log 2>&1 < /dev/null &
stdbuf는 모든 프로그램에 효과가 있는 것은 아닙니다. 프로그램이 자체 버퍼를 다시 설정하거나 특정 입출력 방식을 사용하면 적용되지 않을 수 있습니다.
nohup의 한계와 다른 도구를 선택할 기준
nohup이 제공하지 않는 기능
nohup은 신호 하나의 처리 방식을 바꾸는 간단한 실행 도구입니다. 다음 기능은 제공하지 않습니다.
- 시스템 재부팅 후 자동 시작
- 프로세스가 비정상 종료됐을 때 자동 재시작
- 의존 서비스의 시작 순서 관리
- CPU·메모리 같은 자원 제한과 상태 감시
- 로그 파일의 크기 제한, 압축, 보관 및 삭제
- 대화형 터미널 세션 보존
systemd, tmux, screen과의 차이
| 도구 | 적합한 상황 | 특징 |
|---|---|---|
nohup |
잠시 실행하는 비대화형 일괄 작업 | 간단하지만 감시·재시작·로그 순환 기능이 없습니다. |
systemd |
서버에서 지속적으로 운영할 서비스 | 부팅 연동, 재시작 정책, 의존성, 로그와 자원 관리를 구성할 수 있습니다. |
tmux·screen |
나중에 다시 접속해야 하는 대화형 작업 | 가상 터미널 세션을 분리했다가 다시 연결할 수 있습니다. |
| 작업 스케줄러 | 정해진 시각이나 주기로 실행할 작업 | cron이나 전용 작업 큐로 실행 시점과 이력을 관리합니다. |
disown과의 차이
disown은 Bash 같은 일부 셸이 이미 시작한 작업을 셸의 작업 목록에서 제거하거나 행업 신호 처리 방식을 바꾸는 셸 내장 기능입니다. 반면 nohup은 명령을 시작할 때부터 SIGHUP을 무시하도록 하는 외부 프로그램입니다. disown의 옵션과 동작은 셸에 따라 다르므로 이식 가능한 스크립트에서는 현재 셸의 문서를 확인해야 합니다.
안전하게 실행하기 위한 점검 목록
- 경로: 스크립트, 설정 파일, 로그 파일은 가능하면 절대 경로로 지정합니다. 로그인한 위치가 달라져도 같은 파일을 사용하게 할 수 있습니다.
- 권한: 로그에 비밀번호, 토큰, 개인 정보가 남을 수 있는지 확인하고 파일 권한을 제한합니다.
- 용량: 로그가 계속 커지지 않도록
logrotate또는 프로그램 자체의 로그 보관 정책을 구성합니다. - 중복 실행: 같은 작업이 동시에 여러 번 실행돼도 안전한지 확인합니다. 필요하면 잠금 파일이나 프로그램의 단일 실행 기능을 사용합니다.
- 환경: 비대화형 실행에서는 작업 디렉터리,
PATH, 로케일, 환경 변수가 로그인 셸과 다를 수 있으므로 필요한 값을 명시합니다. - 민감한 인수: 비밀번호나 토큰을 명령행 인수로 넘기면 다른 사용자가 프로세스 목록에서 볼 수 있습니다. 프로그램이 지원하는 자격 증명 파일이나 비밀 저장 방식을 사용합니다.
- 종료 절차: 실행 직후 PID를 기록하고, 정상 종료 방법과 남은 자식 프로세스 확인 절차를 함께 준비합니다.
자주 묻는 질문
SSH 창을 닫으면 nohup 작업은 반드시 유지되나요?
nohup으로 시작한 명령은 SIGHUP을 무시하지만, 모든 환경에서 작업 존속을 절대적으로 보장하는 것은 아닙니다. 프로그램이 별도의 자식 프로세스를 만들면서 신호 설정을 바꾸거나 터미널 장치를 계속 사용한다면 결과가 달라질 수 있습니다. 표준 입출력을 모두 터미널에서 분리하고, 중요한 장기 작업은 서비스 관리자를 사용하는 편이 안전합니다.
nohup.out 파일을 만들지 않으려면 어떻게 하나요?
표준 출력과 표준 오류를 직접 지정하면 됩니다. 로그가 전혀 필요하지 않은 작업만 /dev/null로 보낼 수 있지만, 문제를 진단할 정보도 사라지므로 운영 작업에는 보통 별도 로그 파일을 권장합니다.
nohup ./worker > /dev/null 2>&1 < /dev/null &
jobs에 작업이 보이지 않는 이유는 무엇인가요?
jobs는 현재 셸이 관리하는 작업만 표시합니다. 로그아웃한 뒤 새 셸에 접속하면 이전 셸의 작업 목록은 이어지지 않으므로 jobs에 나오지 않습니다. 저장한 PID와 ps를 사용하거나 서비스 관리 도구의 상태 조회 기능을 사용하세요.
nohup의 종료 코드는 무엇을 의미하나요?
GNU 구현에서는 nohup 자체의 오류, 명령을 찾지 못한 경우, 명령을 실행할 수 없는 경우에 별도의 종료 코드를 사용하며, 정상적으로 명령을 시작했다면 그 명령의 종료 상태를 반환합니다. 정확한 값은 구현과 POSIXLY_CORRECT 설정의 영향을 받을 수 있으므로 자동화에서는 해당 시스템의 nohup --help와 공식 문서를 확인하세요. 백그라운드로 시작한 뒤 셸을 종료하면 그 셸에서 단순히 $?를 읽어 최종 작업 결과를 얻을 수 없다는 점도 주의해야 합니다.
정리
nohup은 로그아웃이나 터미널 종료 시 발생할 수 있는 SIGHUP을 무시하도록 명령을 실행합니다. 일반적인 비대화형 작업은 nohup, &, 명시적인 표준 입출력 리디렉션을 함께 사용하고, 실행 직후 PID를 저장하면 관리하기 쉽습니다.
작업이 재부팅 후에도 시작되어야 하거나 실패 시 자동 복구가 필요하다면 nohup 대신 systemd 같은 서비스 관리자를 선택하세요. 다른 기본 도구를 한눈에 살펴보려면 리눅스에서 자주 사용하는 명령어 목록을 참고할 수 있습니다.









