Overview
오늘은 리눅스 셸 스크립트에서 자주 등장하는 /dev/null 에 대해 알아보고자 한다. 이 개념을 이해하기 위해 먼저 파일 디스크립터(File Descriptor) 에 대해 간단히 짚고 넘어간다.
리눅스 시스템에서는 프로세스가 입출력을 처리하기 위해 정수 기반의 파일 디스크립터를 사용한다. 이 디스크립터는 음수가 아닌 정수 값이며, 운영체제 내부의 파일 디스크립터 테이블에 등록되어 관리된다. 기본적으로 프로세스는 아래 세 가지 입출력 스트림을 가진다.
이름 | 파일 디스크립터 번호 | 설명 |
Standard Input | 0 | 표준 입력 (키보드 등) |
Standard Output | 1 | 표준 출력 (화면) |
Standard Error | 2 | 표준 에러 (화면) |
이러한 스트림은 쉘에서 리디렉션 연산자(`>`, `>>`, `2>`, `&>`, 등)를 사용하여 다른 파일이나 /dev/null과 같은 특수 파일로 연결할 수 있다.
/dev/null은 "블랙홀" 역할을 하는 특수 장치 파일로, 여기에 출력되는 데이터는 어디에도 저장되지 않고 폐기된다. 즉, 불필요한 출력(특히 에러 메시지)을 억제하거나 로그를 비우는 용도로 사용된다.
예를 들어
command > /dev/null # 표준 출력을 버린다
command 2> /dev/null # 표준 에러를 버린다
command &> /dev/null # 표준 출력 + 에러 모두 버린다
파일을 /dev/null로 덮어쓰거나 접근을 시도하면 Permission denied 에러가 발생할 수 있으므로 쓰기 권한 없는 상황에서는 주의가 필요하다.
File Descriptor(파일 디스크립터)란?
파일 디스크립터는 시스템으로 할당 받은 파일을 대표하는 0이 아닌 정수 값이다.
파일 디스크립터는 '0이 아닌 정수', 'Non-negative Integer'값이다. 음수가 아닌 0과 양수인 정수 값을 가진다.
3가지의 Default input/output streams가 있다.
- 표준 입력(Standard Input(STDIN), 표준 출력(Standard Output(STDOUT)), 그리고 표준 오류(Standard Error(STDERR))이다. 기본적으로 이 스트림들은 각자 특정한 파일 디스크립터(File Descriptor)를 가지고 있다.
- 각 파일 디스크립터는 어떤 정수(Inter)값인데 그것은 어떤 하나의 open file과 연결되어 있다.
- 그리고 프로세스들은 파일 디스크립터를 이용해 데이터를 처리한다.
- stdin=0, stdout=1, stderr=2
- 이 파일 디스크립터들은 어떤 하나의 파일 디스크립터 테이블에 저장되어 있다.
쉽게 설명하자면, 파일 디스크립터는 시스템이 만들어 놓은 것을 사용할 수 있게 하기 위해 시스템이 우리에게 건네주는 숫자에 불가하다.
/dev/null 이란?
/dev/null 은 쉽게 말해서 null 값이라고 보면된다. shell을 crontab 실행할 때 오류가 생겨도 멈추지 않고 표준에러를 표준출력으로 리다이렉션 할때, 또는 사용중인 파일을 비우고 싶을때 주로 사용된다.
1) 예제
$ echo "Somaz"
Somaz
$ echo "Somaz" > /dev/null'
$ ls
Desktop Documents Downloads Music Pictures Public Templates Videos snap socket
$ rm somaz > /dev/null
rm: cannot remove 'test': No such file or directory
# 하지만 somaz라는 file이 존재하지 않기 때문에 위와 같이 표준에러가 출력된다.
$ rm somaz > /dev/null 2>&1
# 이렇게 명령하면 표준에러는 버려진다.
- > 표준출력 : 명령의 결과를 파일로 저장 ( 명령 > 파일 )
- >> 표준출력(추가) : 명령의 결과를 기존 파일 데이터에 추가 ( 명령 >> 파일 )
- < 표준입력 : 파일의 데이터를 명령에 입력 ( 명령 < 파일 )
2) 예제
$ cat somaz
1
2
3
4
5
6
7
8
9
10
$ /dev/null > somaz
-bash: /dev/null: Permission denied
$ ls -l
-rw-r--r-- 1 root root 0 Sep 14 16:01 somaz
$ cat somaz
# 이렇게 파일이 비워진다.
3) 예제
$ rm -rf somaz
$ cat somaz.sh
#!/bin/bash
rm somaz > /dev/null
# 쉘 생성
$ chmod 755 somaz.sh
# 쉘 실행을 위한 권한 설정
$ crontab -e
* * * * * /root/somaz.sh >> /root/somaz.log 2>&1
# crontab 설정
$ service cron start
* Starting periodic command scheduler cron [ OK ]
# crontab 서비스 실행
root@DESKTOP-UE21GPH:~# cat somaz.log
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
rm: cannot remove 'somaz': No such file or directory
# 이렇게 1분마다 게속 쌓인다.
마무리
오늘 학습을 통해 /dev/null이 단순한 파일이 아니라 출력 무시, 에러 억제, 불필요한 출력 정리 등에 유용하게 쓰이는 핵심 유틸리티임을 이해할 수 있었다. 또한, 이를 사용하는 기반이 되는 파일 디스크립터 구조(0, 1, 2) 역시 리눅스 시스템 프로그래밍의 중요한 기본 개념임을 확인했다.
쉘 스크립트나 백그라운드 작업, 크론(CRON)과 같은 자동화 시스템에서 /dev/null은 불필요한 출력으로 로그를 오염시키지 않게 하는 깨끗한 결과 관리의 비법으로 많이 사용된다.
"불필요한 출력은 /dev/null로 보내고, 필요한 정보에만 집중하자!"
Reference
https://blog.naver.com/dev_zion/222631283389