운영체제/Linux

[Linux] tee Command를 이용한 stdout / stderr 처리 관련

louky 2023. 12. 6. 14:12
반응형

간만에 끄적 거려 봅니다.

 

최근 CI/CD를 하다보니 Error 상황을 많이 마주치게 됩니다. 

리눅스 커맨드를 사용할때 Error가 발생할 경우 파일로도 저장을 하고 싶고 종료하고 싶을때도 있습니다.

다양한 방법이 있겠지만. 그중 tee command를 이용한 처리 방법입니다.

 

정답은 아닙니다. 다만.. 필자가 겪은 내용을 토대로 작성한 내용이며, 필자 또는 또 다른 누군가가 저와 같은 고충을 겪었을때 조금이나마 도움이 되고자 하는것입니다.

 

먼저 기본적으로 tee 사용법은 아래와 같습니다.

$ ls -al | tee stdout.log
total 5176
drwxr-x--- 9 ubuntu ubuntu    4096 Dec  6 03:33 .
drwxr-xr-x 4 root   root      4096 Oct 24 14:22 ..
-rw------- 1 ubuntu ubuntu    8047 Dec  6 03:50 .bash_history
-rw-r--r-- 1 ubuntu ubuntu     220 Jan  6  2022 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu    3986 Dec  5 23:04 .bashrc
drwx------ 2 ubuntu ubuntu    4096 Aug 24 04:47 .cache
-rw------- 1 ubuntu ubuntu      20 Dec  5 23:06 .lesshst
-rw-r--r-- 1 ubuntu ubuntu     807 Jan  6  2022 .profile
drwx------ 2 ubuntu ubuntu    4096 Dec  5 23:05 .ssh
-rw-r--r-- 1 ubuntu ubuntu       0 Aug 24 04:47 .sudo_as_admin_successful
-rw------- 1 ubuntu ubuntu   12206 Dec  6 03:17 .viminfo
-rw-rw-r-- 1 ubuntu ubuntu      52 Dec  6 03:38 stderr.log
-rw-rw-r-- 1 ubuntu ubuntu       0 Dec  6 03:51 stdout.log
drwxrwxr-x 3 ubuntu ubuntu    4096 Nov  2 06:40 vault

########################################################################
# 화면에 출력도 되고 stdout.log 파일로 저장도 됩니다. 

$ cat stdout.log
total 5176
drwxr-x--- 9 ubuntu ubuntu    4096 Dec  6 03:33 .
drwxr-xr-x 4 root   root      4096 Oct 24 14:22 ..
-rw------- 1 ubuntu ubuntu    8047 Dec  6 03:50 .bash_history
-rw-r--r-- 1 ubuntu ubuntu     220 Jan  6  2022 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu    3986 Dec  5 23:04 .bashrc
drwx------ 2 ubuntu ubuntu    4096 Aug 24 04:47 .cache
-rw------- 1 ubuntu ubuntu      20 Dec  5 23:06 .lesshst
-rw-r--r-- 1 ubuntu ubuntu     807 Jan  6  2022 .profile
drwx------ 2 ubuntu ubuntu    4096 Dec  5 23:05 .ssh
-rw-r--r-- 1 ubuntu ubuntu       0 Aug 24 04:47 .sudo_as_admin_successful
-rw------- 1 ubuntu ubuntu   12206 Dec  6 03:17 .viminfo
-rw-rw-r-- 1 ubuntu ubuntu      52 Dec  6 03:38 stderr.log
-rw-rw-r-- 1 ubuntu ubuntu       0 Dec  6 03:51 stdout.log
drwxrwxr-x 3 ubuntu ubuntu    4096 Nov  2 06:40 vault

 

하지만 command상에 Error가 발생할 경우 stdout.log로 저장이 되지 않습니다. 

$ ls a-la | tee stdout.log
ls: cannot access 'a-la': No such file or directory

# Command 오류가 있을 경우 정상적인 표준출력이 되지 않기에 stdout.log에 저장될 수 없습니다.
$ cat stdout.log
# 내용 없음..

 

">" 또는 ">>"를 이용한 표준 리다이렉트를 사용할 경우엔 아래와 같이 사용 됩니다. 

$ ls a-al 2> stdout.log

# 화면에 출력이 없이 파일로 저장됩니다. 
$ cat stdout.log
ls: cannot access 'a-al': No such file or directory

 

 

표준 리다이렉트를 이용하면 exitCode도 정상적으로 확인 할 수 있습니다. 

$ ls a-al 2> stdout.log ;echo $? 
2

# echo $? <-- 이 커맨드는 실행 결과를 알려주는 exitcode 또는 returncode라 하며, 
# 0을 제외한 나머지 숫자는 에러를 의미 합니다.

 

하지만 tee를 사용할 경우 모두 exitcode가 정상응답인 0을 리턴하고 있었습니다. 

# 비정상 command일때 returnCode
$ ls a-al | tee stdout.log  ; echo $?
ls: cannot access 'a-al': No such file or directory
0

# 정상 command일때 returnCode
$ ls -l | tee stdout.log  ; echo $?
total 5124
-rw-r--r-- 1 ubuntu ubuntu 5215082 Oct 24 14:39 172-16-102-106_bjh.tar.gz
drwxrwxr-x 2 ubuntu ubuntu    4096 Aug 24 04:50 codedeploy
drwxrwxr-x 4 ubuntu ubuntu    4096 Dec  5 01:00 db_test
-rwxr-xr-x 1 ubuntu ubuntu     114 Aug 24 04:47 disk_size_up.sh
drwxrwxr-x 2 ubuntu ubuntu    4096 Aug 24 04:50 node_exporter
drwxrwxr-x 5 ubuntu ubuntu    4096 Aug 24 04:50 promtail
-rw-rw-r-- 1 ubuntu ubuntu      52 Dec  6 03:38 stderr.log
-rw-rw-r-- 1 ubuntu ubuntu       0 Dec  6 04:01 stdout.log
drwxrwxr-x 3 ubuntu ubuntu    4096 Nov  2 06:40 vault

0

 

이렇게 tee를 이용하여 정의 할 경우returnCode가 0으로 나오는 현상이 있습니다. 

(물론 다른 방법이 있겠지만 필자는 아직 찾지 못했습니다. )

 

Script 상 또는 CI/CD상에서 리눅스 커맨드를 사용할때 console에 출력도 하고 파일로도 저장도 하고 싶으며, return code가 0이 아닐 경우 멈추기를 원한하면 아래와 같은 방법으로구현 하실 수 있습니다. 

# USAGE 
COMMAND 2> >(tee {STD_ERROR_FILE}) > >(tee {STD_OUTPUT_FILE})

# example 
# 정상 케이스 
# stderror.log 파일에는 아무것도 없고 stdout.log에만 결과를 저장
$ ls -al 2> >(tee stderr.log) > >(tee stdout.log)


# 비정상 케이스
# stderror.log 파일에만 결과를 저장하고  stdout.log에만 결과를 저장하지 않음
$ ls a-al 2> >(tee stderr.log) > >(tee stdout.log)

 

script 에 구현시 아래와 같이 할 수 있습니다. 

#!/bin/bash

ls a-al 2> >(tee stderr.log) > >(tee stdout.log)

if [ $? -eq 0 ] ; then
        echo "Command Success"
else
        echo "Command Fail"
fi

 

script 결과

$ ./tee_test.sh
ls: cannot access 'a-al': No such file or directory
Command Fail

 

 다양한 방법이 있겠지만... 여기까지가 필자가 확인한 내용이다. 

 

더 좋은 방법을 알고 계신다면 댓글 부탁 드립니다. 

반응형