리눅스(Linux)나 맥(macOS) 환경에서 인프라 배포나 자동화 작업을 처리할 때 가장 먼저 찾게 되는 도구는 바로 Bash 셸 스크립트(Shell Script)입니다. 이번 포스팅에서는 셸 스크립트 파일 최상단에 붙는 #!/bin/bash의 의미와 함께, 에러 메시지를 통제하는 핵심 기법인 표준 에러 리다이렉션(2> /dev/null)의 동작 원리에 대해 자세히 다뤄보겠습니다.
1. 스크립트의 시작, 쉬뱅(Shebang: #!)
텍스트 편집기(vi, nano 등)를 이용해 셸 스크립트를 작성할 때, 첫 번째 줄에는 약속처럼 다음과 같은 문자열을 작성합니다.
#!/bin/bash
이를 쉬뱅(Shebang) 또는 해시-뱅(Hash-bang)이라고 부르며, 해당 스크립트 파일을 실행할 때 어떤 인터프리터(해석기)를 사용해 구문을 분석할 것인지 운영체제(OS)에 지시하는 선언문입니다.
#!: OS 커널에게 “이 줄 이후에 오는 경로의 실행 파일로 아래 스크립트를 가동해라”라는 신호를 줍니다./bin/bash: 실행할 인터프리터의 절대 경로(여기서는 Bash 셸)를 나타냅니다.- 이유: 쉬뱅을 적지 않고 스크립트를 가동하면 현재 사용자가 로그인해 있는 로그인 셸(zsh, sh 등) 환경에서 실행되어, 셸 종류에 따른 미세한 문법 차이로 인해 런타임 에러가 발생할 수 있습니다. 시스템 환경에 구애받지 않고 항상 Bash의 문법 규칙으로 동작하게 고정하려면 쉬뱅 선언이 필수적입니다.
2. 파일 디스크립터(File Descriptor)와 3대 스트림
리눅스 및 유닉스 계열 OS에서는 “모든 것은 파일이다”라는 대원칙 하에 입출력을 처리합니다. 프로세스가 가동되면 OS는 기본적으로 3개의 데이터 통로(스트림)를 열어주며, 이를 식별하기 위한 정수 번호를 파일 디스크립터(FD)라고 부릅니다.
| 파일 디스크립터 (FD) | 표준 명칭 | 기본 목적 |
|---|---|---|
| 0 | 표준 입력 (Standard Input, stdin) | 키보드 등의 입력 스트림 |
| 1 | 표준 출력 (Standard Output, stdout) | 화면에 출력되는 정상적인 실행 결과 |
| 2 | 표준 에러 (Standard Error, stderr) | 실행 중 발생하는 오류 메시지 출력 |
3. 에러 출력을 감추는 exec 2> /dev/null
스크립트를 백그라운드 크론탭(Crontab) 등으로 스케줄링하여 돌리다 보면, 명령 오류로 인해 화면이나 터미널 로그에 지저분한 에러 메시지가 대량으로 출력되는 것을 막아야 하는 상황이 생깁니다. 이때 활용하는 명령이 바로 리다이렉션 기호(>)와 파일 디스크립터 2번(stderr)입니다.
1) 개별 명령어 단위 제어
ls -l /nonexistent_folder 2> /dev/null
- 존재하지 않는 폴더를 조회하려 했으므로 원래는
No such file or directory에러가 떠야 하지만,2>연산자가 에러 스트림(2)을 감지해 우측의 목적지로 리다이렉트합니다. /dev/null: 리눅스의 쓰레기통(블랙홀) 장치 파일입니다. 이 파일로 유입된 모든 데이터는 저장되지 않고 즉시 폐기됩니다. 결과적으로 화면에 에러 메시지가 표시되지 않습니다.
2) 스크립트 전체 제어 (exec 활용)
스크립트 내부의 매 명령어마다 2> /dev/null을 붙이는 것은 귀찮은 일입니다. 스크립트 상단에 exec 명령을 사용하면 이후 실행되는 모든 명령어에 글로벌하게 적용할 수 있습니다.
#!/bin/bash
exec 2> /dev/null # 이후 발생하는 모든 표준 에러를 화면에 출력하지 않고 폐기합니다.
# 이 명령어들은 에러가 발생해도 화면에 아무런 출력을 남기지 않습니다.
cat /invalid/path/file.txt
rm /nonexistent/file
4. 실무 권장 가이드: 에러 로깅으로 활용하기
무조건 에러를 폐기하는 2> /dev/null은 개발 단계나 디버깅 시 치명적인 결함의 원인을 추적하기 어렵게 만듭니다. 실무에서는 에러를 버리기보다 아래와 같이 에러 로그 파일로 보관하는 방식(누적 추가 >>)을 훨씬 권장합니다.
#!/bin/bash
# 표준 에러(2)를 error.log 파일에 누적 기록합니다.
exec 2>> /var/log/my_script_error.log
쉬뱅의 정확한 정의와 파일 디스크립터 기반 스트림 처리를 명확히 이해하시면, 안정적이고 제어 가능한 리눅스 인프라 제어 스크립트를 작성하실 수 있습니다.