오늘은 리눅스 기본 강의에서 Command Input and Output, Command Pipeline과 그에 관련된 명령어들을 정리해 보려고 한다.
다음 그림은 커맨드 에서 Stream이 어떻게 나타나는지를 보여주는 그림이다.
그림에서 보는 것 처럼 Data Stream은 Standard Input(0), Standard Output(1), 그리고 Standard Error(2) 이렇게 세 가지가 있고 커맨드가 Arguments를 받는 건 Data Stream이라고 하지 않는다. 즉, 두 가지 방법으로 데이터를 받고, 두 가지 방법으로 데이터를 보내는 것이다.
여기서 Redirection을 통해서 Stream의 흐름을 컨트롤 할 수가 있다. 아래의 코드를 통해 확인해 보자. 참고로 1> 과 1>> 등은 STDOUT의 번호가 1이어서 적은 것이고 1을 빼고 >, >> 로 적어도 동일한 결과가 나온다. 명령어 cat은 concatenate의 약자로 새로운 파일을 만들 때 사용하거나(아래 코드), 여러 파일들을 합칠 때 사용한다.
# output.txt 파일을 지우고 새로 만듦(truncate)
$ cat 1> output.txt
Hello
^C
# 이렇게 하면 새로운 output.txt 라는 파일이 생성된다. 기존에 output.txt 파일이 있었다면 지워진다.
# output.txt 파일을 지우지 않고 해당 파일에 이어서 작성(append)
# 위의 파일이 있다고 가정
$ cat 1>> output.txt
World
^C
# 이렇게 하면 output.txt 라는 파일에 Hello / World 가 쓰여지게 된다.
# 다음과 같이 에러 메시지를 리다이렉트 할 수도 있다
$ cat -k bla 2> error.txt
# 이 코드가 실행이 되면 bla라는 단어로 검색을 할 수 없으므로 에러 메시지가 error.txt에 작성된다.(아래 스크린샷 참고)
# STDIN 을 통해 입력 값을 리다이렉트하여 input.txt 파일의 값을 불러올 수 있다.
# input.txt 가 생성되어 있고 abcd 라고 작성되어 있다고 가정하면
$ cat 0< input.txt
abcd
지금까지 Command I/O에 대해서 살펴보았고 이와 같이 STDOUT을 리다이렉트 해서 새로운 명령에 STDIN 하는 프로세스를 'piping'이라고 한다.
piping은 아래 그림에서 보는 것 처럼 Command1에서 출력받은 데이터를 새로운 Command2에서 입력받을 때 마치 파이프라인으로 연결되어 있는 것 같다고 해서 붙여진 이름이다. 실제로 이렇게 데이터의 흐름을 연결하는 부분을 Command Pipeline 이라고 한다.
예를 들어 커맨드에 date라고 친다고 생각을 해보자 그러면 2019. 08. 04 (일) 22:39:10 KST 와 같은 데이터가 생길 것이다. 우리는 이 데이터를 cut 이라는 명령어를 통해서 조작해 보려고 한다.
$ date
2019. 08. 04. (일) 22:39:10 KST
# cut이라는 명령어는 delimiter를 가지고 내용을 필드로 구분하고 특정 필드별로 출력해 주는 명령어이다
# 예를 들어 방금 생긴 데이터를 " " 공백을 가지고 나눈 뒤 첫 번째 부분을 출력하고 싶다면
$ date | cut --delimeter " " --fields 1
2019.
파이프(|)를 통해서 date에서 생성된 데이터(2019. 08. ...)를 그 뒤에 새로운 커맨드에서 cut 명령어를 통해서 다룰 수 있다. 위의 그림처럼 command1(date)의 출력값을 command2(cut)의 입력값으로 연결한 것이며 연결시킬 수 있는 파이프의 갯수에는 제한이 없다.
여기서 또 우리는 이런 생각을 해볼 수도 있다.
"출력 데이터를 파일에도 저장하고, 다른 커맨드로 연결해서 작업도 하고 두 가지를 동시에 해볼 수는 없을까?"
이러한 동작을 할 수 있는 명령어가 바로 tee 이다. T형 파이프를 통해 물이 오른쪽과 아래로 빠져나가는 것을 생각하면 이해하기가 쉽다.
위의 그림에서도 알 수 있듯이 ls -l 을 통해서 파일 리스트가 쭉 나오게 되는데 그 STDOUT 데이터를 tee 명령어를 통해서 file.txt에 저장을 함과 동시에 파이프로 연결하여 less 명령어에 새로운 STDIN 값으로 받을 수가 있다.
tee의 경우는 이전 커맨드에서 받은 출력값을 STDIN(0)으로 다음 커맨드로 전달해 준다. 반면에 이 출력값을 Command Arguments로 전달해 주는 경우도 있는데 이 때 사용하는 명령어가 xargs이다.
위처럼 date 명령어를 통해 나온 데이터를 파이프로 연결하여 다음 커맨드에 STDIN으로 전달한 뒤, 공백을 가지고 필드를 구분해서 특정 필드값을 다시 파이프로 전달해 줄 수가 있다. 이 때 xargs를 통해서 전달해 주면 echo의 argument로 이전 커맨드의 STDOUT 데이터가 전달이 되므로 보이는 것처럼 결과를 출력받을 수 있다. 이 때 xargs를 쓰지 않으면 빈 공백을 출력하는 것을 볼 수 있다.
간단하게 설명한 내용들을 정리하면
1. 파이프는 하나의 커맨드에서 나온 STDOUT 값을 다른 커맨드의 STDIN으로 연결해 준다.
2. STDOUT의 리다이렉션은 파이프라인을 중단시킨다.
3. 파이프라인을 중단하지 않고 데이터의 "스냅샷"을 찍고 싶다면, tee 커맨드를 사용하자.
4. 커맨드가 STDIN 값을 받지 못하는데, 파이프를 통해 연결하고 싶다면, xargs를 사용하자.
5. xargs를 사용하는 커맨드는 여전히 자신의 arguments를 가지고 있다.
'Prog. Langs & Tools > Linux' 카테고리의 다른 글
[Udemy] 리눅스 강의 #4 (nano, find, sort 등) (0) | 2019.08.22 |
---|---|
[Udemy] 리눅스 강의 #3 (alias, wildcards, basic commands) (0) | 2019.08.16 |
[Udemy] 리눅스 강의 #1 (BASH, Linux Manual) (0) | 2019.08.06 |