iBetter Books
수정

작업 제어 (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를 파일에 저장해두는 패턴은 장기 실행 스크립트를 나중에 찾아서 종료할 때 매우 유용합니다. 이 패턴은 다음 절에서 더 깊이 다룹니다.