IMG-LOGO
공지사항 :

Linux I/O Redirection

lmkfox - 2025-10-04 06:28:55 77 Views 0 Comment

1. 기본 개념 (파일 디스크립터)

  • FD 0 : stdin

  • FD 1 : stdout

  • FD 2 : stderr

    명령 → stdout/stderr로 결과를 출력. 리다이렉션으로 이들을 파일이나 파이프로 보냄.


2. 기본 리다이렉션 문법

# stdout을 파일로 (덮어쓰기)
command > out.txt

# stdout을 파일에 추가(append)
command >> out.txt

# stderr을 파일로
command 2> err.txt

# stderr을 파일에 추가
command 2>> err.txt

# stdin을 파일로부터 읽기
command < input.txt


3. stdout/stderr 합치기 (merge) — 순서 주의

# stdout과 stderr를 같은 파일로 합치기 (포터블)
command > out_and_err.txt 2>&1

# 또는 (bash 전용 간단문법)
command &> out_and_err.txt

중요 — 순서가 중요

  • command > out 2>&1 : >가 먼저 수행되어 stdout이 파일로 향하고, 그 다음 2>&1로 stderr를 현재(바뀐) stdout으로 복제 → stderr도 파일로 들어감. (의도한 동작)

  • command 2>&1 > out : 먼저 stderr를 현재 stdout(터미널)으로 복제, 그 다음 stdout을 파일로 변경 → stderr는 여전히 터미널로 남음. 즉 서로 다른 결과.

항상 > file 2>&1 또는 2>file 1>&2 등 의도한 순서로 작성할 것.


4. stderr만 리다이렉트 / stdout만 콘솔 유지

# stdout은 그대로 콘솔에, stderr만 파일로
command 2> err.txt

# stdout을 파일로, stderr는 콘솔에 유지 (순서 중요)
command 2> /dev/tty > out.txt   # 복잡하므로 보통 아래 방식 권장
# 추천: stdout만 파일, stderr는 터미널로 남겨두려면
command > out.txt  # stderr 자동으로 콘솔에 남음
# (하지만 > out.txt 2>&1 would combine)


5. /dev/null 사용 — 출력 무시

# 표준출력 무시
command > /dev/null

# 표준에러 무시
command 2> /dev/null

# 둘 다 무시
command > /dev/null 2>&1
# 또는 bash: command &> /dev/null


6. 파이프와 tee

  • 파이프 |는 한 명령의 stdout을 다음 명령의 stdin으로 보냄(주로 stdout만 전달 — stderr는 전달되지 않음).

cmd1 | cmd2

  • tee는 stdout을 파일로 쓰면서 다음 프로세스로도 전달:

cmd | tee logfile | other_cmd
# 출력 기록 + 파이프 계속
# 로그 파일에만 쓰려면:
cmd | tee logfile > /dev/null


7. Here-documents / Here-strings

  • Here-document: 여러 줄을 표준입력으로 제공

cat <<EOF > file.txt
line1
line2 $VARIABLE   # 변수 확장됨
EOF

  • 변수 치환을 막고 싶으면 'EOF'로 감싸기:

cat <<'EOF'
$VARIABLE   # 그대로 출력
EOF

  • <<-EOF는 각 줄의 선행 탭을 제거(탭으로 들여쓰기된 스크립트에서 유용).

  • Here-string (bash/ksh):

grep pattern <<< "$variable"


8. 프로세스 치환 (process substitution) — 

<(...)

>(...)

 (bash, zsh)

  • 명령의 출력을 파일처럼 취급(임시 FIFO 사용):

# diff 두 정렬된 파일 비교
diff <(sort fileA) <(sort fileB)

# 명령의 결과를 프로그램의 파일 인자로 전달
some_cmd >(process_output)

유용: 명령 간 비교·병렬 처리 시.


9. 여러 명령 블록 리다이렉션

  • 여러 명령을 하나의 파일로 리다이렉트하려면 brace {} 또는 subshell () 사용:

# 같은 셸에서 리다이렉트 (중괄호, 세미콜론 필요)
{ cmd1; cmd2; } > all_out.txt 2>&1

# 서브셸(별도 프로세스)
( cmd1; cmd2 ) > all_out.txt 2>&1

중괄호는 현재 셸에서 실행되며 } 앞에 공백 필요.


10. exec로 파일 디스크립터 조작 (현재 셸에 영향)

  • 스크립트 전체의 출력을 로그 파일로 보내려면:

exec > script.log 2>&1
# 이후 이 셸에서 실행되는 모든 명령의 stdout/stderr가 script.log로 감.

  • 원래 stdout 저장하고 복원:

exec 3>&1        # FD 3에 원래 stdout 저장
exec > out.txt   # stdout을 파일로 바꿈
# ... 작업 ...
exec >&3 3>&-    # stdout 복원, FD 3 닫기
FD 숫자(3,4 등)는 임의로 사용 가능(0..2는 표준).

  • FD 닫기:

exec 3>&-   # FD 3 닫음


11. 고급: 파일 디스크립터 복제 / 복원 예제

# 현재 stdout을 FD 3에 저장
exec 3>&1

# stdout을 파일로 리다이렉트
exec 1>out.log

# 이 시점에서 명령들
echo "this goes to out.log"

# 잠깐 원래 stdout(터미널)에 쓰기
echo "to terminal" >&3

# 복원
exec 1>&3 3>&-


12. sudo와 리다이렉션 문제

sudo는 리다이렉션 자체는 셸(사용자 권한)에서 처리하기 때문에 sudo로 명령만 root로 실행해도 > /root/file 같은 리다이렉션은 권한 부족 에러가 날 수 있습니다.

해결법:

# 1) sudo sh -c 'command > /root/file'
sudo sh -c 'echo hello > /root/somefile'

# 2) 또는 tee 사용
echo hello | sudo tee /root/somefile > /dev/null


13. 두 출력( stdout/stderr )을 서로 다른 파일로 저장

command > out.txt 2> err.txt

혹은 시간 순서를 보존하려면 stdbuf나 unbuffer로 버퍼링 조정(파이프를 통해 순서가 섞일 수 있음).


14. 리다이렉션 관련 흔한 실수와 해결

  • 순서 실수: command 2>&1 > out 은 의도대로 작동하지 않음(위 참조).

  • 권한 문제: sudo로 실행해도 >는 여전히 비루트 셸에서 수행 → sudo sh -c 또는 tee 사용.

  • 버퍼링으로 인한 출력 순서 변경: 파이프나 파일로 리다이렉션하면 stdout/stderr 버퍼링이 달라져 출력 순서가 바뀔 수 있음. stdbuf -oL 등으로 라인 버퍼링을 강제하거나 unbuffer 사용.

  • &>는 bash 전용: POSIX 호환성을 원하면 >file 2>&1 사용.


15. 로그·디버깅 실무 예제

  • 스크립트 전체를 로그로 남기기:

#!/bin/bash
exec > >(tee -a /var/log/myscript.log) 2>&1
# 이렇게 하면 stdout은 파일과 터미널에 동시에 쓰임, stderr도 합쳐서 둘 다로
echo "start"
# rest of script

  • 안전한 백그라운드 실행(로그 보존):

nohup myscript.sh > /var/log/myscript.out 2>&1 &


16. named pipe (FIFO) 와 리다이렉션

  • mkfifo /tmp/myfifo로 FIFO 생성 후 producer/consumer를 연결 가능:

mkfifo /tmp/f
# in one shell:
cat /tmp/f | process_consumer
# in another shell:
echo "data" > /tmp/f


17. Quick reference (요약)

  • > : stdout → 파일(덮어쓰기)

  • >> : stdout → 파일(추가)

  • < : stdin ← 파일

  • 2> : stderr → 파일

  • &> : stdout+stderr → 파일 (bash 전용)

  • >file 2>&1 : stdout → file, stderr → same as stdout (포터블)

  • command | command : stdout 파이프 전달

  • cmd | tee file : stdout을 file과 파이프 둘 다로

  • <<EOF : here-document (여러 줄 stdin)

  • <(cmd) : process substitution (파일처럼 사용)


댓글