레슨 09: 프로세스 관리 및 작업 제어(Process Management and Job Control)
레슨 09: 프로세스 관리 및 작업 제어(Process Management and Job Control)¶
난이도: ⭐⭐⭐
이전: 08_Regex_in_Bash.md | 다음: 10_Error_Handling.md
1. 백그라운드 프로세스(Background Processes)¶
셸 스크립트는 백그라운드에서 프로세스를 실행할 수 있어 병렬 실행과 성능 향상을 가능하게 합니다.
기본 백그라운드 실행¶
#!/bin/bash
# &로 명령을 백그라운드에서 실행
sleep 10 &
echo "Sleep started in background"
# 마지막 백그라운드 프로세스의 PID
SLEEP_PID=$!
echo "Sleep PID: $SLEEP_PID"
# 다른 작업 계속 수행
echo "Doing other work..."
# 백그라운드 프로세스가 완료될 때까지 대기
wait $SLEEP_PID
echo "Sleep completed"
wait 명령¶
#!/bin/bash
# 여러 백그라운드 프로세스 시작
sleep 2 &
PID1=$!
sleep 3 &
PID2=$!
sleep 1 &
PID3=$!
echo "Started 3 background processes: $PID1, $PID2, $PID3"
# 모든 백그라운드 작업 대기
wait
echo "All processes completed"
# 특정 PID 대기
sleep 5 &
SPECIFIC_PID=$!
wait $SPECIFIC_PID
echo "Specific process $SPECIFIC_PID completed with exit code: $?"
# Bash 4.3+: 임의의 작업이 완료될 때까지 대기
if [ "${BASH_VERSINFO[0]}" -ge 4 ] && [ "${BASH_VERSINFO[1]}" -ge 3 ]; then
sleep 2 &
sleep 4 &
sleep 1 &
wait -n # 다음 작업이 완료될 때까지 대기
echo "First job completed"
wait -n
echo "Second job completed"
wait
echo "All remaining jobs completed"
fi
작업 제어 명령¶
#!/bin/bash
# 장시간 실행되는 프로세스 시작
sleep 100 &
# 모든 작업 나열
jobs
# 출력: [1]+ Running sleep 100 &
# PID와 함께 나열
jobs -l
# 출력: [1]+ 12345 Running sleep 100 &
# 실행 중인 작업만 나열
jobs -r
# 중지된 작업만 나열
jobs -s
# 작업을 포그라운드로 가져오기
# fg %1 # (대화형 셸에서 주석 해제)
# 작업을 백그라운드로 보내기 (중지된 경우)
# bg %1 # (대화형 셸에서 주석 해제)
# 작업 참조:
# %1 - 작업 번호 1
# %?sleep - 명령에 "sleep"이 포함된 작업
# %% - 현재 작업
# %+ - 현재 작업 (%%와 동일)
# %- - 이전 작업
# 백그라운드 작업 종료
kill %1
작업 제어 예제¶
#!/bin/bash
# 작업 제어를 보여주는 함수
job_control_demo() {
echo "Starting 3 jobs..."
(sleep 5; echo "Job 1 done") &
(sleep 3; echo "Job 2 done") &
(sleep 7; echo "Job 3 done") &
# 모든 작업 표시
jobs
# 작업 2를 특정하여 대기
wait %2
echo "Job 2 has completed"
# 나머지 모두 대기
wait
echo "All jobs completed"
}
job_control_demo
2. 병렬 실행(Parallel Execution)¶
독립적인 작업을 병렬로 실행하면 스크립트를 크게 가속화할 수 있습니다.
기본 병렬 패턴¶
#!/bin/bash
# 순차 실행 (느림)
sequential() {
for i in {1..5}; do
sleep 1
echo "Task $i completed"
done
}
# 병렬 실행 (빠름)
parallel_basic() {
for i in {1..5}; do
(
sleep 1
echo "Task $i completed"
) &
done
wait
}
echo "Sequential (5 seconds):"
time sequential
echo -e "\nParallel (1 second):"
time parallel_basic
백그라운드 PID 추적¶
#!/bin/bash
# 배열에 PID 저장
pids=()
for i in {1..5}; do
sleep $((RANDOM % 3 + 1)) &
pids+=($!)
echo "Started job $i with PID ${pids[-1]}"
done
# 각 PID를 대기하고 종료 상태 확인
for pid in "${pids[@]}"; do
wait "$pid"
status=$?
echo "PID $pid exited with status $status"
done
동시성 제한¶
#!/bin/bash
# 최대 N개의 작업을 병렬로 실행
MAX_JOBS=3
run_with_limit() {
local max_jobs=$1
shift
local jobs=("$@")
local pids=()
local count=0
for job in "${jobs[@]}"; do
# 한계에 도달하면 하나가 완료될 때까지 대기
if [ "${#pids[@]}" -ge "$max_jobs" ]; then
wait -n # Bash 4.3+
# 완료된 PID 제거
for i in "${!pids[@]}"; do
if ! kill -0 "${pids[$i]}" 2>/dev/null; then
unset 'pids[$i]'
fi
done
pids=("${pids[@]}") # 배열 재색인
fi
# 새 작업 시작
eval "$job" &
pids+=($!)
echo "Started job: $job (PID: $!)"
done
# 남은 작업 대기
wait
echo "All jobs completed"
}
# 사용 예제
jobs=(
"sleep 2; echo 'Job 1 done'"
"sleep 1; echo 'Job 2 done'"
"sleep 3; echo 'Job 3 done'"
"sleep 1; echo 'Job 4 done'"
"sleep 2; echo 'Job 5 done'"
)
run_with_limit $MAX_JOBS "${jobs[@]}"
xargs를 사용한 병렬 실행¶
#!/bin/bash
# xargs로 파일을 병렬 처리
process_file() {
local file=$1
echo "Processing $file..."
sleep 1
echo "$file processed"
}
export -f process_file
# 4개의 작업을 병렬로 실행
echo -e "file1.txt\nfile2.txt\nfile3.txt\nfile4.txt\nfile5.txt" | \
xargs -P 4 -I {} bash -c 'process_file "{}"'
# 대안: parallel (GNU parallel 도구, 설치된 경우)
# seq 1 10 | parallel -j 4 'echo Processing {}; sleep 1'
병렬 처리 템플릿¶
#!/bin/bash
# 범용 병렬 프로세서
parallel_process() {
local max_parallel=$1
local processor_func=$2
shift 2
local items=("$@")
local count=0
local pids=()
for item in "${items[@]}"; do
# 동시성 제한
while [ "${#pids[@]}" -ge "$max_parallel" ]; do
for i in "${!pids[@]}"; do
if ! kill -0 "${pids[$i]}" 2>/dev/null; then
wait "${pids[$i]}"
echo "Job for '$item' completed (PID: ${pids[$i]}, status: $?)"
unset 'pids[$i]'
fi
done
pids=("${pids[@]}")
sleep 0.1
done
# 새 작업 시작
$processor_func "$item" &
pids+=($!)
((count++))
done
# 남은 모든 작업 대기
for pid in "${pids[@]}"; do
wait "$pid"
done
echo "Processed $count items"
}
# 예제 프로세서 함수
my_processor() {
local item=$1
sleep $((RANDOM % 3 + 1))
echo "Processed: $item"
}
export -f my_processor
# 최대 5개 병렬로 20개 항목 처리
items=($(seq 1 20))
parallel_process 5 my_processor "${items[@]}"
3. 서브셸(Subshells)¶
서브셸은 자체 변수 스코프를 가진 격리된 실행 환경을 생성합니다.
서브셸 구문¶
#!/bin/bash
# 괄호는 서브셸을 생성합니다
VAR="outer"
(
VAR="inner"
echo "Inside subshell: $VAR"
)
echo "Outside subshell: $VAR" # 여전히 "outer"
# 명령 치환도 서브셸을 생성합니다
result=$(
VAR="command substitution"
echo "$VAR"
)
echo "Result: $result"
echo "VAR is still: $VAR" # 여전히 "outer"
서브셸 vs 명령 그룹화¶
#!/bin/bash
# 서브셸 ( ) - 별도 프로세스, 격리된 스코프
VAR="original"
( VAR="subshell"; cd /tmp; pwd )
echo "VAR: $VAR" # "original"
echo "PWD: $PWD" # 변경되지 않음
# 명령 그룹화 { } - 동일한 프로세스, 공유 스코프
VAR="original"
{ VAR="grouped"; echo "In group: $VAR"; }
echo "VAR: $VAR" # "grouped"
# 참고: { }는 공백과 세미콜론/줄바꿈이 } 앞에 필요합니다
실용적인 서브셸 사용¶
#!/bin/bash
# 1. 임시 디렉토리 변경
(cd /tmp && ls -la) # 이후 원래 디렉토리로 돌아옴
# 2. 임시 환경 변경
(
export PATH="/custom/path:$PATH"
export CUSTOM_VAR="value"
./my_program # 수정된 환경 사용
)
# 여기서 환경 복원됨
# 3. 리다이렉션을 위한 그룹화
(
echo "Log entry 1"
echo "Log entry 2"
echo "Log entry 3"
) >> logfile.txt
# 4. 백그라운드 작업 격리
for i in {1..3}; do
(
# 각 반복은 격리된 환경을 가짐
ITERATION=$i
sleep 1
echo "Iteration $ITERATION complete"
) &
done
wait
# 5. 그룹화된 명령이 있는 파이프라인
(echo "line 1"; echo "line 2"; echo "line 3") | grep "line 2"
변수 스코프 함의¶
#!/bin/bash
# 서브셸에서 수정된 변수는 유지되지 않음
counter=0
while read line; do
((counter++)) # while이 서브셸에 있으면 작동하지 않습니다!
done < <(seq 1 10)
echo "Counter: $counter" # 10 (프로세스 치환은 while에 대한 서브셸 회피)
# 이것은 서브셸을 생성합니다 (while에 파이프)
counter=0
seq 1 10 | while read line; do
((counter++))
done
echo "Counter: $counter" # 0 (서브셸이 변경 사항을 격리)
# 해결책 1: 프로세스 치환 사용 (위에 표시됨)
# 해결책 2: here 문자열 또는 리다이렉션 사용
# 해결책 3: 파일 디스크립터 사용
4. 시그널(Signals)¶
시그널은 프로세스에 이벤트를 알리는 소프트웨어 인터럽트입니다.
일반적인 시그널¶
| 시그널 | 번호 | 설명 | 기본 동작 |
|---|---|---|---|
| SIGHUP | 1 | 행업 (터미널 닫힘) | 종료 |
| SIGINT | 2 | 인터럽트 (Ctrl+C) | 종료 |
| SIGQUIT | 3 | 종료 (Ctrl+) | 종료 + 코어 덤프 |
| SIGKILL | 9 | 킬 (캐치 불가) | 종료 |
| SIGTERM | 15 | 종료 요청 | 종료 |
| SIGSTOP | 19 | 중지 (캐치 불가) | 중지 |
| SIGCONT | 18 | 중지된 경우 계속 | 계속 |
| SIGUSR1 | 10 | 사용자 정의 시그널 1 | 종료 |
| SIGUSR2 | 12 | 사용자 정의 시그널 2 | 종료 |
| SIGPIPE | 13 | 깨진 파이프 | 종료 |
| SIGCHLD | 17 | 자식 프로세스 변경됨 | 무시 |
| SIGALRM | 14 | 타이머 만료 | 종료 |
시그널 전송¶
#!/bin/bash
# 백그라운드 프로세스 시작
sleep 100 &
PID=$!
# 프로세스에 시그널 전송
kill -SIGTERM $PID # 정중한 종료 요청
# kill -15 $PID # 동일, 번호 사용
# kill -SIGKILL $PID # 강제 종료 (캐치 불가)
# kill -9 $PID # 동일, 번호 사용
# 프로세스가 실행 중인지 확인 (시그널 0)
if kill -0 $PID 2>/dev/null; then
echo "Process $PID is running"
else
echo "Process $PID is not running"
fi
# 프로세스 그룹에 시그널 전송
# kill -TERM -$$ # 전체 프로세스 그룹 종료
시그널 나열¶
#!/bin/bash
# 모든 시그널 나열
kill -l
# 번호로부터 시그널 이름 가져오기
kill -l 9 # KILL
# 이름으로부터 시그널 번호 가져오기
kill -l TERM # 15
5. trap 명령¶
trap 명령은 스크립트가 시그널을 캐치하고 처리할 수 있게 합니다.
기본 trap 구문¶
#!/bin/bash
# trap 구문: trap 'commands' SIGNAL [SIGNAL...]
# Ctrl+C (SIGINT) 캐치
trap 'echo "Caught SIGINT (Ctrl+C)! Exiting..."; exit 1' INT
echo "Press Ctrl+C to trigger the trap..."
sleep 30
echo "Completed normally"
여러 시그널 트랩¶
#!/bin/bash
cleanup() {
echo "Cleanup function called by signal: $1"
# 여기서 정리 수행
exit 0
}
# 여러 시그널 트랩
trap 'cleanup SIGINT' INT
trap 'cleanup SIGTERM' TERM
trap 'cleanup SIGHUP' HUP
echo "Script running (PID: $$)..."
echo "Try: kill -TERM $$"
while true; do
sleep 1
done
시그널 무시¶
#!/bin/bash
# SIGINT 무시 (빈 문자열)
trap '' INT
echo "Try Ctrl+C - it won't work!"
sleep 5
# 기본 동작으로 재설정
trap - INT
echo "Now Ctrl+C will work again"
sleep 5
EXIT에 대한 트랩¶
#!/bin/bash
# EXIT 의사 시그널: 스크립트 종료 시 트리거됨 (모든 이유)
trap 'echo "Script exiting..."' EXIT
echo "Starting script"
sleep 2
echo "Ending script"
# EXIT 트랩은 스크립트가 어떻게 종료되든 여기서 실행됩니다
trap을 사용한 디버깅¶
#!/bin/bash
# DEBUG 의사 시그널: 각 명령 전에 실행됨
trap 'echo "Executing: $BASH_COMMAND"' DEBUG
echo "First command"
x=10
echo "x is $x"
((x++))
echo "x is now $x"
trap - DEBUG # DEBUG 트랩 비활성화
6. 정리 패턴(Cleanup Patterns)¶
적절한 정리는 스크립트가 임시 파일, 락 파일 또는 고아 프로세스를 남기지 않도록 보장합니다.
임시 파일 정리¶
#!/bin/bash
# 임시 파일 생성
TMPFILE=$(mktemp) || exit 1
# 종료 시 정리 보장
trap 'rm -f "$TMPFILE"' EXIT
echo "Using temp file: $TMPFILE"
# 임시 파일 사용
echo "data" > "$TMPFILE"
cat "$TMPFILE"
# 종료 시 자동으로 정리됩니다
포괄적인 정리¶
#!/bin/bash
# 정리 함수
cleanup() {
local exit_code=$?
echo "Performing cleanup..."
# 임시 파일 제거
[ -n "$TMPFILE" ] && [ -f "$TMPFILE" ] && rm -f "$TMPFILE"
[ -n "$TMPDIR" ] && [ -d "$TMPDIR" ] && rm -rf "$TMPDIR"
# 락 파일 해제
[ -n "$LOCKFILE" ] && [ -f "$LOCKFILE" ] && rm -f "$LOCKFILE"
# 자식 프로세스 종료
[ -n "$WORKER_PID" ] && kill "$WORKER_PID" 2>/dev/null
# 상태 복원
[ -n "$ORIGINAL_DIR" ] && cd "$ORIGINAL_DIR"
echo "Cleanup complete"
exit "$exit_code"
}
# 트랩 설정
trap cleanup EXIT INT TERM
# 원래 디렉토리 기억
ORIGINAL_DIR=$PWD
# 임시 리소스 생성
TMPFILE=$(mktemp)
TMPDIR=$(mktemp -d)
LOCKFILE="/tmp/myscript.lock"
echo "Resources created:"
echo " TMPFILE: $TMPFILE"
echo " TMPDIR: $TMPDIR"
echo " LOCKFILE: $LOCKFILE"
# 작업 시뮬레이션
echo "Working..."
sleep 2
# 자동으로 정리됩니다
락 파일 패턴¶
#!/bin/bash
LOCKFILE="/var/lock/myscript.lock"
# 락 획득
acquire_lock() {
if [ -e "$LOCKFILE" ]; then
echo "Another instance is running (lock file exists)"
exit 1
fi
# 우리 PID로 락 파일 생성
echo $$ > "$LOCKFILE"
# 정리 보장
trap 'rm -f "$LOCKFILE"; exit' EXIT INT TERM
}
# 대안: mkdir로 원자적 락
acquire_lock_atomic() {
local lockdir="/var/lock/myscript.lock.d"
if mkdir "$lockdir" 2>/dev/null; then
trap 'rmdir "$lockdir"; exit' EXIT INT TERM
return 0
else
echo "Another instance is running"
return 1
fi
}
acquire_lock
echo "Lock acquired, doing work..."
sleep 5
echo "Done"
멱등적 정리(Idempotent Cleanup)¶
#!/bin/bash
# 안전하게 여러 번 호출할 수 있는 정리
cleanup() {
# 플래그를 사용하여 정리된 것을 추적
[ -n "$CLEANUP_DONE" ] && return
CLEANUP_DONE=1
echo "Running cleanup..."
# 제거하기 전에 확인
if [ -n "$TMPFILE" ] && [ -f "$TMPFILE" ]; then
rm -f "$TMPFILE"
echo "Removed $TMPFILE"
fi
# 실행 중인 경우에만 프로세스 종료
if [ -n "$CHILD_PID" ] && kill -0 "$CHILD_PID" 2>/dev/null; then
kill "$CHILD_PID"
wait "$CHILD_PID" 2>/dev/null
echo "Killed process $CHILD_PID"
fi
}
trap cleanup EXIT INT TERM
TMPFILE=$(mktemp)
sleep 100 &
CHILD_PID=$!
echo "Press Ctrl+C to test cleanup..."
sleep 30
7. 코프로세스(Coprocesses) (coproc)¶
Bash 4.0+는 양방향 통신을 위한 코프로세스를 지원합니다.
기본 코프로세스¶
#!/bin/bash
# 코프로세스 시작
coproc BC { bc; }
# 코프로세스에 쓰기 (stdin)
echo "5 + 3" >&"${BC[1]}"
# 코프로세스에서 읽기 (stdout)
read -u "${BC[0]}" result
echo "Result: $result"
# 코프로세스 닫기
eval "exec ${BC[1]}>&-"
wait $BC_PID
명명된 코프로세스¶
#!/bin/bash
# 명명된 코프로세스
coproc CALC { bc -l; }
# 계산 함수
calculate() {
echo "$1" >&"${CALC[1]}"
read -u "${CALC[0]}" result
echo "$result"
}
# 계산기 사용
echo "sqrt(16) = $(calculate 'sqrt(16)')"
echo "10 / 3 = $(calculate '10 / 3')"
echo "e(1) = $(calculate 'e(1)')"
# 정리
eval "exec ${CALC[1]}>&-"
wait $CALC_PID
대화형 코프로세스 예제¶
#!/bin/bash
# 셸 코프로세스 시작
coproc SHELL { bash; }
# 코프로세스에서 명령 실행 함수
exec_in_coproc() {
local cmd=$1
echo "$cmd" >&"${SHELL[1]}"
echo "echo '<<<END>>>'" >&"${SHELL[1]}"
while read -u "${SHELL[0]}" line; do
[ "$line" = "<<<END>>>" ] && break
echo "$line"
done
}
# 명령 실행
echo "Current directory:"
exec_in_coproc "pwd"
echo -e "\nFiles:"
exec_in_coproc "ls -1"
echo -e "\nEnvironment variable:"
exec_in_coproc "echo \$HOME"
# 정리
echo "exit" >&"${SHELL[1]}"
wait $SHELL_PID
에러 처리가 있는 코프로세스¶
#!/bin/bash
# 에러 처리가 있는 코프로세스 시작
start_coproc() {
if ! coproc WORKER { python3 -u -c '
import sys
while True:
try:
line = input()
if line == "QUIT":
break
# 라인 처리
print(f"Processed: {line}")
sys.stdout.flush()
except EOFError:
break
'; }; then
echo "Failed to start coprocess"
return 1
fi
# 정리 설정
trap 'echo "QUIT" >&"${WORKER[1]}" 2>/dev/null; wait $WORKER_PID 2>/dev/null' EXIT
}
# 코프로세스 사용
send_to_worker() {
echo "$1" >&"${WORKER[1]}"
read -u "${WORKER[0]}" -t 5 response || {
echo "Timeout or error reading from worker"
return 1
}
echo "$response"
}
start_coproc
send_to_worker "task1"
send_to_worker "task2"
send_to_worker "task3"
8. 프로세스 우선순위(Process Priority)¶
프로세스의 CPU 및 I/O 우선순위를 제어합니다.
nice 명령¶
#!/bin/bash
# Nice 값은 -20 (최고 우선순위)에서 19 (최저)까지
# 기본값은 0
# 낮은 우선순위로 실행 (nice 값 10)
nice -n 10 ./cpu-intensive-script.sh
# 높은 우선순위로 실행 (음수 값은 root 필요)
# sudo nice -n -10 ./important-script.sh
# 현재 nice 값 확인
echo "Current nice value: $(nice)"
renice 명령¶
#!/bin/bash
# 프로세스 시작
./my-script.sh &
PID=$!
# 실행 중인 프로세스의 우선순위 변경
renice -n 15 -p $PID
# 사용자의 모든 프로세스 renice
# sudo renice -n 10 -u username
# 그룹의 모든 프로세스 renice
# sudo renice -n 5 -g groupname
ionice 명령¶
#!/bin/bash
# I/O 스케줄링 클래스:
# 0 - None (기본)
# 1 - Real-time (최고 우선순위, root 필요)
# 2 - Best-effort (기본)
# 3 - Idle (다른 I/O가 없을 때만)
# idle I/O 우선순위로 실행
ionice -c 3 ./disk-intensive-script.sh
# best-effort, 우선순위 4 (0-7, 낮을수록 높은 우선순위)로 실행
ionice -c 2 -n 4 ./my-script.sh
# 실행 중인 프로세스의 I/O 우선순위 변경
ionice -c 3 -p $PID
결합된 우선순위 예제¶
#!/bin/bash
# CPU와 I/O 집약적 작업을 낮은 우선순위로 실행
run_low_priority() {
local cmd=$1
# nice로 시작
nice -n 19 bash -c "$cmd" &
local pid=$!
# I/O 우선순위를 idle로 설정
ionice -c 3 -p $pid
echo "Started low priority process: $pid"
echo "Nice: $(ps -o nice= -p $pid)"
echo "I/O class: $(ionice -p $pid)"
wait $pid
}
# 사용 예제
run_low_priority "find / -name '*.log' 2>/dev/null | xargs gzip"
우선순위 관리 스크립트¶
#!/bin/bash
# 프로세스 우선순위 관리
manage_priority() {
local pid=$1
local cpu_priority=$2 # -20 ~ 19
local io_class=$3 # 0-3
local io_priority=$4 # 0-7
echo "Managing priority for PID $pid"
# CPU 우선순위 설정
if [ -n "$cpu_priority" ]; then
if renice -n "$cpu_priority" -p "$pid" >/dev/null 2>&1; then
echo " CPU priority set to $cpu_priority"
else
echo " Failed to set CPU priority (may need sudo)"
fi
fi
# I/O 우선순위 설정
if [ -n "$io_class" ]; then
local ionice_cmd="ionice -c $io_class"
[ -n "$io_priority" ] && ionice_cmd="$ionice_cmd -n $io_priority"
if $ionice_cmd -p "$pid" >/dev/null 2>&1; then
echo " I/O priority set to class $io_class"
else
echo " Failed to set I/O priority (may need sudo)"
fi
fi
# 현재 우선순위 표시
echo " Current nice value: $(ps -o nice= -p $pid)"
echo " Current I/O: $(ionice -p $pid | head -1)"
}
# 예제: 낮은 우선순위로 백업 실행
echo "Starting backup..."
./backup.sh &
BACKUP_PID=$!
manage_priority $BACKUP_PID 19 3
wait $BACKUP_PID
echo "Backup complete"
연습 문제¶
문제 1: 병렬 파일 프로세서¶
설정 가능한 최대 동시 작업 수로 여러 파일을 병렬로 처리하는 스크립트를 작성하세요. 각 파일은 작업을 시뮬레이션하는 함수(sleep)로 처리되어야 하며, 스크립트는 각 파일이 처리를 시작하고 완료할 때 보고해야 합니다.
요구 사항:
- 디렉토리 경로와 최대 동시 작업 수를 인수로 받음
- 디렉토리의 모든 .txt 파일 처리
- 총 처리 시간 추적 및 보고
- 에러를 우아하게 처리
문제 2: 시그널 안전 다운로드 매니저¶
다음 기능을 가진 다운로드 매니저 스크립트를 만드세요: - 여러 URL을 병렬로 다운로드 - 진행 상황을 상태 파일에 저장 - SIGINT (Ctrl+C)로 중단하고 나중에 재개 가능 - SIGTERM에서 부분 다운로드 정리 - 모든 정리를 적절히 처리하기 위해 trap 사용
문제 3: 백그라운드 작업 모니터¶
다음 기능을 가진 작업 모니터링 시스템을 구현하세요: - 여러 백그라운드 작업 시작 - 매초마다 상태 모니터링 - 각 작업이 완료될 때 보고 - 진행 표시기 표시 - 동시 작업을 최대값으로 제한 (예: 3) - 작업 실패를 처리하고 실패한 작업을 한 번 재시도
문제 4: 코프로세스 계산기 서비스¶
코프로세스를 사용하여 계산기 서비스를 만드세요:
- bc 코프로세스 시작
- 표현식을 입력할 명령줄 인터페이스 제공
- 히스토리 지원 (최근 10개 계산 표시)
- 에러 처리 (잘못된 표현식)
- 적절한 종료 시퀀스 구현
문제 5: 우선순위 기반 작업 스케줄러¶
다음 기능을 가진 작업 스케줄러를 만드세요: - 우선순위 수준(high, medium, low)을 가진 작업 수락 - 높은 우선순위 작업은 nice 값 0으로 실행 - 중간 우선순위 작업은 nice 값 10으로 실행 - 낮은 우선순위 작업은 nice 값 19와 I/O 클래스 idle로 실행 - 모든 실행 중인 작업의 상태 보고 - 총 동시 작업을 5개로 제한 - 종료 시 적절한 정리 구현
이전: 08_Regex_in_Bash.md | 다음: 10_Error_Handling.md