쿼카러버의 기술 블로그

Linux Shell Script - Redirection (>, >>, 2>&1) (커맨드/프로그램 로그 저장) 쉬운 사용법 & 원리에 대한 이해 본문

Linux - Ubuntu/Shell Script

Linux Shell Script - Redirection (>, >>, 2>&1) (커맨드/프로그램 로그 저장) 쉬운 사용법 & 원리에 대한 이해

quokkalover 2021. 7. 18. 15:10

타겟 : 

- 커맨드 실행 후 출력 결과를 계속해서 파일에 로그처럼 남기고 싶은 경우

- 프로그램 실행 후 출력 결과를 파일에 로그처럼 남기고 싶은 경우 

- redirection에 대한 개념 이해가 필요한 경우

등을 고민하는 분은 이 글을 참고하시기 바랍니다.

 

읽는법 :

쉬운 사용방법만 알고 싶은 분들은 Easy Explanation파트를,

왜?How?등 디테일하게 알아보고 싶다면 하단의 Redirection in Detail 참고.

 

Easy Explanation

redirecting stdout stream 기호

  • 기호들은 데이터의 흐름의 방향을 나타냄
  • > 출력(overwrite)
  • >> 출력(append)

overwrite (>)

stdout stream을 redirect하기 위해서는 > or >> 기호를 쓸 수 있음.

output > file.txt
  • Redirect the output (stdout) to file.txt
  • file.txt가 존재하지 않으면 새로 생성함
  • 이미 존재하면 덮어씌워짐 (기존의 내용이 사라짐/overwrite)

append(>>)

output >> file.txt
  • 출력을 file.txt 파일에 append함 (기존의 내용 뒤에 덧 붙임)
  • 파일이 존재하지 않는 경우 새로 생성함.

 

예 1) 명령어의 결과(ls *)를 file.txt에 남기기

=현재 디렉토리에 있는 파일 명을 file.txt로 옮겨서 저장하기

ls * > file.txt
  • 그냥 ls * 만 실행해보면 file.txt에 입력된 내용이 터미널에서 출력되지만.
  • 위처럼 > file.txt를 붙일 경우 터미널에선 출력되지 않고, 모든 출력이 다 파일에 저장된다.

 

예 2) 특정 스크립트 실행 결과와 에러를 같은 파일에 남기기 (overwrite)

test.sh > file.txt 2>&1

 

예 3) 특정 스크립트 실행 결과와 에러를 같은 파일에 남기기 (append)

test.sh >> file.txt 2>&1

 

예 4) 특정 스크립트 실행결과(stdout)과 에러를 분리해서 저장하기

test.sh > file.txt 2> errfile.txt

 

예 5) stdout은 overwrite, stderr는 append하기

test.sh > file.txt 2>> errfile.txt

정리

  • 프로그램의 입력(stdin), 결과(stdout), 에러(stderr) 을 파일이나 다른 스트림으로 전달할 때 사용
  • program/stream to/from files (program > file)
    • 프로그램 실행결과/stream을 특정 파일로
  • 저장 방식 overwrite, append는 기호를 통해 구분

Redirection in Detail

표준 입력 / 표준 출력에 대해서

  • UNIX 이전의 OS에서는 명령어를 입력하고 출력을 보기 위해서는 프로그래머가 직접 입/출력장치를 설정해야 했다.
  • 하지만 Unix부터는 data stream이라는 개념을 이용하여 프₩로그래머가 어떤 장치를 사용하는지와는 관계 없이 open, read, write을 할 수 있게 했다. 또한 자동으로 입/출력 장치를 연결하여 많은 부담을 덜게 됐다고 한다.

stream이란 디스크상의 파일이나 컴퓨터에 연결되는 여러 장치들을 통일된 방식으로 다루기 위한 가상적인 개념이다.

  • 즉, 데이터가 어디서 나와서 어디로 가는지 신경쓸 필요없이 장치, 프로세스, 파일들과 연결돼어 많은 편리성을 제공해준다.
  • 프로세스가 생성되면 기본적으로 입, 출력을 위한 채널을 가지게 되는데, 이것을 standard stream이라고 한다.

Unix에서는 모든 장치를 파일로 관리한다. 즉, standard stream도 각각 /dev/stdin, /dev/stdout, /dev/stderr에 파일로 존재한다.

FD (File Descriptor)

우리가 사용하는 파일들은 우리가 알아보기 쉬운 이름으로 보여지지만, 실제 프로그램 실행시에는 FD(File Descriptor)라는 양의 정수 번호에 의해 처리가 된다.

  • 참고 : 프로그램이 수행되면 운영체제는 실행되는 프로그램에게 3개의 기본 FD를 할당한다. 그리고 프로그램이 내부적으로 다른 파일을 open하게 되면 3번째 FD를 할당한다.
    • 프로그램을 작성하고 프로그램 내부에서 파일을 열게 되면 파일 디스크립터는 3부터 할당된다

redirection

redirection이란, 위 그림에서 번호로 매겨져 있는 부분을 프로그래머가 원하는쪽으로 redirect하는 것.

  • FD 번호를 사용해, 화살표가 가르치는 빨간 별표 부분을 redirect 하는게 redirection

shell에서도 redirection을 할때 이와 같은 FD번호를 사용한다.

  • 명령어를 실행하면 stdin(입력), stdout(출력), stderr(에러 출력)이 존재하는데,
  • 기본적으로 shell 프로세스의 stdin, stdout, stderr가 모두 터미널에 연결되어 사용자로부터 입력을 받고 출력을 해서 우리가 터미널 명령어를 편리하게 사용할 수 있는 것.

기본 사용법

아래와 같은 infile이 있다고 해보자.

$ cat infile
hello
world

그리고 위의 infile을 그대로 outfile로 옮겨적을때는 아래와 같이 하면 된다.

$ wc 0< infile 1> outfile
$ cat outfile 
 2  2 12

위의 wc 명령은 redirection 의 기본 사용법을 보여준다.

데이터 흐름의 방향을 나타내는 redirection 기호인 < (입력), > (출력), >> (출력:append) 을 가운데 두고

  • 왼쪽에는 FD (file descriptor),
  • 오른쪽에는 FD '나' filename 을 위치시키면 됩니다.

기본 값 (Default Value)

위 예시를 보면 infile을 FD 0(stdin)에 연결해서 입력으로 사용했고

FD 1 (stdout)을 outfile에 연결하여 출력이 outfile파일에 저장되게 했다.

redirection기호를 사용할 때 FD번호를 적어줘야 하지 않으면 적어주지 않을 경우에는 standard stream이 사용된다.

  • <의 좌측 기본 값 = 0
  • >, >>의 좌측 기본값 = 1

따라서

$ wc < infile > outfile
$ cat outfile
 2  2 12

처럼 입력해도 동일한 결과 값을 가져옴.

주의 사항

< , >, >> 기호 좌측값은 공백없이 붙여야한다. 그렇지 않으면 명령의 인수로 인식이 되기 때문에 주의해야 한다..

$ wc 0 < infile 1> outfile         # 0 을 wc 명령의 인수로 인식.
wc: 0: No such file or directory

$ wc 0< infile 1 > outfile         # 1 을 wc 명령의 인수로 인식.
wc: 1: No such file or directory

>, >> 기호의 우측값은 파일이름이 올경우는 괜찮지만

  • FD 번호가 올경우는 & 기호를 붙여줘야 한다.
  • 그렇지 않으면 FD 숫자가 파일이름이 된다.

>&2 , 2>&1, 1>&2들의 의미

  • >&2 , 2>&1, 1>&2 등은 위에서 설명했듯이,기호 오른쪽에 파일이름이 아닌 FD번호를 쓰고 싶을때 &를 사용해서 표현한 기호들이다.

헷갈리는 케이스 1)

아래 명령어가 의미하는건 → 1이라는 파일로 asdfgh의 파일 내의 내용을 입력하는 것.

$ wc asdfgh  2>1
$ cat 1
wc: asdfgh: No such file or directory
  • 오른쪽에 &를 붙이지 않아서, 파일 이름으로 인식한 것
  • 따라서 에러 출력이 파일 1로 가게 됨.

헷갈리는 케이스 2)

$ wc asdfgh 2>&1
wc: asdfgh: No such file or directory
  • stdout을 stderr로 redirect 하겠다는 의미가 됨.
    • 그럼 위 명령어를 실행하면 FD 1의 경우 현재 shell을 가리키고 있기 때문에 에러를 터미널에 출력하라는 것과 동일한 의미.
  • 자 이해안되면 아래를 잘 읽어야 이해된다.
    • 위 커맨드를 실행시, asdfgh 라는 파일이 없기 때문에 stderr가 출력될텐데
    • 해당 내용을 &1(stdout)으로 넘기는데, 현재는 "터미널창으로 가리키고 있기 때문"에 터미널 창에 에러 메시지가 출력이 됨.
  • >& as 'redirect merger operator' 라고 생각하면 됨.
    • 2>&1 = 2> redirect stderr to a file,를 의미하고 &1를 추가해서 stderr를 stdout로 머지시키는 것.

자주 사용하는 케이스

만약 특정 명령어의 결과를 특정 파일에 넣고싶고, 에러도 같은 파일에 넣고 싶으면 두 가지 방법이 있음.

$ wc asdfghh > tmpfile 2>&1 
$ wc asdfghh 1> tmpfile 2> tmpfile #위와 동일함. 
  • 위처럼 하면 &1이 현제 tmpfile로 지정됐기 때문에 err도 tmpfile로 넘어감.

만약에 stdout과 stderr를 나누고 싶다면 아래처럼 하면 됨

{명령어, 프로그램} 1>{stdout file이름} 2>{stderr 지정할 파일 이름}

stdout만 출력하고 싶으면

{명령어, 프로그램} 1>{stdout file이름}   #or 
{명령어, 프로그램} >{stdout file이름}
  • 이렇게 하면 정상 출력은 {stdout file 이름}으로 들어가고 stderr는 터미널에서 출력됨.

참고 자료

https://stackoverflow.com/questions/9553628/piping-and-redirection

https://twpower.github.io/133-difference-between-redirect-and-pipe

https://www.linuxunit.com/io-redirection-stdin-stdout-stderr-streams/

https://mug896.github.io/bash-shell/redirections.html

https://stackoverflow.com/questions/818255/in-the-shell-what-does-21-mean

https://blogger.pe.kr/369

Comments