오상우
오상우

Categories

  • linux
  • ubuntu

1. 표준 출력 \ 표준 오류

프로그램은 기본적으로 입력을 처리해 출력을 내놓는 작업을 한다. 리눅스 프로그램들도 마찬가지인데, ls 의 경우 그 결과를 표준 출력(stdout)에 내보낸다. 리눅스의 표준 출력은 기본적으로 화면(터미널)에 나타난다. 정상적인 결과 뿐 아니라 오류와 같은 상태 메세지도 출력되는데, 이를 표준 오류(stderr) 에 내보내며, 표준오류 역시 기본적으로 화면에 나온다. 표준 입력(stdin)은 키보드에 연결되어 있다.
이러한 표준 입출력을 바꾸는 것을 I/O 리다이렉션이라고 한다.

ls -l > result.txt

위의 명령어를 통해 ls -l 의 결과가 표준 출력(화면)이 아닌 result.txt 라는 파일로 리다이렉션 되어, 커맨드라인에 보이지 않게 되었다. 실제로 less를 통해 해당 파일을 확인하면 목록이 텍스트로 저장된 것을 볼 수 있다.
이번에는 존재하지 않는 디렉토리의 목록을 보려 해 보자.

ls -l ./nosuchdirectory > result.txt
ls: ./nosuchdirectory: No such file or directory

에러 메세지가 그대로 화면에 출력된 것을 볼 수 있다. > 는 표준 출력만을 리다이렉션 했기에, 표준 오류는 여전히 화면에 나타나게 되는 것이다. 그리고 result.txt 를 확인해보면 아무것도 없는데, > 는 해당 파일이 없으면 만들고, 존재하는 파일은 덮어쓰는 방식으로 작동하기에 위의 ls 명령어는 오류가 나면서 표준 출력에 아무것도 내보내지 않았고, 빈 텍스트로 result.txt 파일을 덮어써서 내용이 모두 지워진 것이다.
빈 파일을 만들 때, 아래와 같은 방법을 사용할 수 있다.

> empty.txt

>> 이렇게 >를 두개 연달아 쓰면 덮어쓰기가 아닌 이어쓰기가 된다.
그렇다면 표준 오류 리다이렉션은 어떻게 할 수 있을까?

ls -l ./nosuchdirectory 2> error.txt

정확히는 리다이렉션이 아닌 파일 디스크립터를 이용해 위와 같이 표준 에러를 파일로 저장할 수 있다(1은 출력, 2는 에러). 그렇다면 오류와 출력을 한 파일에 저장하려면 어떻게 해야 할까??

ls -l ./hi > stdout.txt 2>&1

위의 명령어로 우선 표준 출력을 stdout.txt파일로 리다이렉션 하고 파일 디스크립터 2(에러)를 파일 디스크립터 1(출력)으로 재지정되어 stdout.txt에 출력과 오류가 모두 저장된다. 단, 항상 표준 출력을 먼저 지정하고 표준 오류를 지정해야 정상적으로 동작한다!!
bash 최신 버전에서는 아래와 같이 한번에 재지정이 가능하다.

ls -al &> total-output.txt

2. 표준 입력

표준 입력은 기본적으로 키보드에 연결되어 있다. 표준 입력을 사용하는 대표적인 명령어로는 cat 이 있다.

cat [...files]

cat은 하나 이상의 파일을 읽어 들여서 표준 출력으로 그 내용을 복사해 내보낸다.

cat hi.txt
hi, nice to meet you!

만약 cat 명령어에 아무런 인자도 전달하지 않으면 어떻게 될까?

cat

아무 일도 일어나지 않은 것 같지만, 실은 키보드라는 표준 입력을 읽어들이는 중이다. 아무렇게나 타이핑을 한 뒤, 입력의 끝(EOF)을 의미하는 ctrl-D를 눌러보자.

cat
what are you doing?
what are you doing?

입력 내용을 그대로 표준 출력(화면)에 내보냈다.
여기에 출력 리다이렉션을 활용하면 텍스트 파일 생성이 가능해진다.

cat > test.txt
this is text file!

3. 파이프라인

파이프라인이라는 쉘의 기능으로 우리는 입출력을 더욱 다양하게 활용할 수 있다. 간단히 말해서, 파이프라인(|) 은 왼쪽 명령어의 표준 출력을 오른쪽 명령어의 표준 입력으로 전달하는 기능을 한다.
대표적으로 less 명령어는 표준 입력을 허용하기에 | less 형태로 모든 명령어의 표준 화면 출력을 페이지 형태로 볼 수 있게 해준다. 파이프라인과 함께 사용할 수 있는(표준 입력을 허용하는) 명령어는 filter, sort, wc, uniq, head\tail, tee, grep 등 많이 있지만, 그 중에서도 단연 많이 쓰이는 명령어는 grep이다.
grep [file...] 형태로 사용하며, 패턴(일반 택스트 or 정규 표현식)과 일치하는 내용을 파일 입력 or 표준 입력에서 찾아서 표준 출력으로 보여 준다.

ls -al | grep hi
ls -al | grep *.txt

첫번째 명령어는 ls -al 의 결과 중 hi가 포함된 줄만 보여주고, 두번째 명령어는 텍스트 파일만을 보여준다.

head나 tail 명령어는 출력의 일부 만을 보고 싶을때(기본은 10줄이나 -n 옵션으로 조절 가능) 사용한다.
특히 tail의 경우 -f 옵션을 사용하면 한번 출력하고 종료하는 것이 아니고 지속적으로 파일을 감시해서 변화할 때마다 내용을 갱신하여, 로그 파일등을 실시간으로 보고 싶을 때 편리하다.

ls -al / | head
tail -f error.log

첫번째 명령어는 루트 디렉토리의 파일 목록 위에서 10줄만을 표준 출력에 보여주고, 두번째 명령어는 error.log 파일의 마지막 10줄을 갱신될 때마다 보여준다.