작업 제어 (jobs, fg, bg, nohup)
백그라운드로 보낸 작업이 어떻게 되고 있는지 확인하고 싶을 때가 있습니다. 아니면 잠깐 멈춰뒀던 작업을 다시 실행하거나, 터미널을 닫아도 계속 돌아가게 하고 싶을 때도 있습니다. 이 절에서는 현재 쉘 세션에서 실행 중인 작업들을 관리하는 방법을 다룹니다.
jobs: 현재 쉘의 작업 목록
jobs 명령어는 현재 쉘 세션에서 실행 중이거나 정지된 작업들을 보여줍니다. 다른 터미널이나 시스템 전체의 프로세스가 아닌, 지금 내가 사용하는 쉘에서 관리하는 작업만 표시됩니다.
# 작업 몇 개 시작sleep 100 &sleep 200 &sleep 300# Ctrl+Z로 sleep 300 일시 정지 후jobs
출력 결과입니다.
[1] Running sleep 100 &
[2]- Running sleep 200 &
[3]+ Stopped sleep 300
출력에서 [숫자]는 작업 번호, +는 현재 작업(최근 작업), -는 이전 작업을 나타냅니다. Running은 백그라운드 실행 중, Stopped는 Ctrl+Z로 정지된 상태입니다.
PID도 함께 보려면 -l 옵션을 씁니다.
jobs -l
[1] 12340 Running sleep 100 &
[2]- 12341 Running sleep 200 &
[3]+ 12342 Stopped sleep 300
fg: 백그라운드를 포그라운드로
fg 명령어는 작업을 포그라운드로 가져옵니다. 작업 번호를 지정하지 않으면 + 표시된 현재 작업을 가져옵니다.
# 작업 3번을 포그라운드로fg %3# + 표시 작업(현재 작업)을 포그라운드로fg# 작업 1번을 포그라운드로fg %1
포그라운드로 가져온 작업은 다시 Ctrl+C로 종료하거나 Ctrl+Z로 정지할 수 있습니다.
bg: 정지된 작업을 백그라운드에서 재개
Ctrl+Z로 정지된 작업을 백그라운드에서 계속 실행하려면 bg를 사용합니다.
# 긴 작업 시작./long_backup.sh# Ctrl+Z로 잠깐 멈춤# [1]+ Stopped ./long_backup.sh# 백그라운드에서 계속 실행bg %1# [1]+ ./long_backup.sh &# 이제 터미널에서 다른 작업 가능echo "다른 작업 중..."
작업 제어 전체 흐름을 정리하면 다음과 같습니다.
nohup: 터미널 종료 후에도 계속 실행
터미널을 닫으면 그 터미널에 연결된 모든 프로세스에 SIGHUP 시그널이 전송됩니다. 백그라운드로 실행한 작업도 SIGHUP을 받으면 종료됩니다. nohup은 이 시그널을 무시하게 만들어, 터미널을 닫아도 프로세스가 계속 실행되도록 합니다.
# nohup으로 실행. 출력은 nohup.out에 저장됨nohup ./long_job.sh &# 출력 파일 지정nohup ./long_job.sh > job.log 2>&1 &# PID 확인echo "PID: $!"
nohup으로 실행하면 표준 출력이 기본적으로 nohup.out 파일에 저장됩니다. 출력이 중요하다면 직접 파일을 지정하는 것이 좋습니다.
nohup ./backup.sh > /var/log/backup.log 2>&1 &echo "백업 시작. PID: $!"echo "로그: /var/log/backup.log"
disown: 쉘에서 작업 분리
이미 실행 중인 백그라운드 작업에서 SIGHUP 전달을 차단하려면 disown을 사용합니다. nohup 없이 시작한 프로세스를 나중에 분리할 때 유용합니다.
# 백그라운드로 시작./some_job.sh &# [1] 12345# 작업 분리 (jobs 목록에서도 제거됨)disown %1# 또는 PID로disown 12345# 작업 목록에서 제거하되 SIGHUP은 여전히 전달disown -h %1
disown 후에는 jobs에서 해당 작업이 사라집니다. 프로세스는 계속 실행 중이지만 현재 쉘이 더 이상 관리하지 않습니다.
screen/tmux 간단 소개
nohup과 disown으로도 충분하지만, 터미널 세션 자체를 유지하고 싶다면 screen이나 tmux를 사용합니다. 특히 서버에 SSH로 접속해 작업할 때 네트워크가 끊겨도 작업이 계속되도록 보장합니다.
# screen 설치 및 기본 사용sudo apt install screen# 새 세션 시작screen -S mywork# 세션 안에서 작업 실행./long_job.sh# 세션 분리 (작업은 계속 실행됨): Ctrl+A, D# 나중에 재접속screen -r mywork
# tmux 설치 및 기본 사용sudo apt install tmux# 새 세션 시작tmux new -s mywork# 세션 분리: Ctrl+B, D# 나중에 재접속tmux attach -t mywork
screen과 tmux 모두 세션을 여러 창으로 분할하고, SSH 연결이 끊겨도 작업을 보존합니다. 장시간 실행되는 작업(데이터 처리, 빌드, 크롤링 등)을 서버에서 돌릴 때 필수 도구입니다.
실습: nohup으로 장시간 스크립트 실행
로그를 주기적으로 분석하는 장기 실행 스크립트를 nohup으로 실행하고 관리하는 방법입니다.
#!/usr/bin/env bash# 파일: log_monitor.shLOG_FILE="/var/log/myapp/app.log"REPORT_DIR="$HOME/reports"INTERVAL=60 # 60초마다 분석mkdir -p "$REPORT_DIR"echo "로그 모니터링 시작: $(date)"echo "PID: $$"count=0while true; do count=$((count + 1)) timestamp=$(date +%Y%m%d_%H%M%S) report_file="${REPORT_DIR}/report_${timestamp}.txt" echo "--- 분석 #${count}: $(date) ---" > "$report_file" if [[ -f "$LOG_FILE" ]]; then echo "ERROR 발생 횟수: $(grep -c ERROR "$LOG_FILE" 2>/dev/null || echo 0)" >> "$report_file" echo "최근 오류:" >> "$report_file" grep ERROR "$LOG_FILE" | tail -5 >> "$report_file" 2>/dev/null || true else echo "로그 파일 없음" >> "$report_file" fi echo "분석 완료: $report_file" sleep "$INTERVAL"done
이 스크립트를 nohup으로 실행하는 방법입니다.
# 백그라운드로 실행, PID 저장nohup ./log_monitor.sh > ~/log_monitor.out 2>&1 &echo $! > ~/log_monitor.pidecho "모니터링 시작. PID: $(cat ~/log_monitor.pid)"# 나중에 종료kill $(cat ~/log_monitor.pid)rm ~/log_monitor.pidecho "모니터링 종료"
PID를 파일에 저장해두는 패턴은 장기 실행 스크립트를 나중에 찾아서 종료할 때 매우 유용합니다. 이 패턴은 다음 절에서 더 깊이 다룹니다.