Skip to main content
Summary

흐름을 보면 명령어가 연결됩니다

Linux 명령어는 혼자서도 쓸 수 있지만, 진짜 힘은 서로 연결할 때 나옵니다. 한 명령어가 데이터를 꺼내고, 다음 명령어가 필요한 줄만 고르고, 또 다음 명령어가 정렬하거나 개수를 셉니다. 주방으로 비유하면 칼, 도마, 체, 냄비를 따로 쓰는 것이 아니라 조리 순서대로 이어 붙이는 일입니다.

이 흐름을 이해하려면 먼저 데이터가 어디에서 들어오고 어디로 나가는지 봐야 합니다. 터미널에 보이는 결과도 사실은 정해진 통로를 따라 흐릅니다. 이 장에서는 그 통로를 파일로 돌리거나, 다른 명령어로 넘기는 방법을 배웁니다.

실습은 이전 장에서 사용한 공간에서 진행합니다.

cd ~/linux-practice
mkdir -p pipeline-demo
cd pipeline-demo

연습용 파일을 만듭니다. 아래 명령에서 cat > 파일명 <<'EOF'는 EOF가 다시 나올 때까지 입력한 내용을 파일로 저장합니다.

cat > access.log <<'EOF'
10.0.0.1 GET / 200
10.0.0.2 GET /login 200
10.0.0.3 GET /missing 404
10.0.0.1 POST /api 500
10.0.0.2 GET /missing 404
10.0.0.4 GET /api 200
EOF

cat > app.log <<'EOF'
INFO boot completed
WARN cache slow
ERROR database timeout
INFO request handled
ERROR permission denied
EOF

cat > names.txt <<'EOF'
minsu
jiyun
ara
minsu
hojun
EOF

파이프라인과 리다이렉션으로 명령어 연결하기AI 생성 이미지

표준 입력, 표준 출력, 표준 오류

명령어에는 기본 통로가 세 개 있습니다.

  • stdin: 표준 입력입니다. 보통 키보드 입력이나 앞 명령어가 넘겨준 데이터가 들어옵니다. 번호는 0입니다.

  • stdout: 표준 출력입니다. 명령이 정상적으로 만든 결과가 나갑니다. 번호는 1입니다.

  • stderr: 표준 오류입니다. 오류 메시지나 경고 메시지가 나갑니다. 번호는 2입니다.

예를 들어 다음 명령은 파일 내용을 읽어 표준 출력으로 보냅니다. 그래서 결과가 화면에 보입니다.

cat access.log

반대로 존재하지 않는 파일을 읽으면 오류가 생깁니다. 이 메시지는 표준 출력이 아니라 표준 오류로 나옵니다.

cat no-file.log

초보자가 자주 헷갈리는 지점은 여기입니다. 화면에 보인다고 모두 같은 출력이 아닙니다. 정상 결과와 오류는 다른 통로를 사용합니다. 이 차이를 알아야 결과만 파일에 저장하거나, 오류만 따로 모으거나, 둘을 함께 기록할 수 있습니다.

리다이렉션으로 출력 방향 바꾸기

리다이렉션은 출력의 목적지를 바꾸는 기능입니다. 원래 화면으로 나갈 내용을 파일로 보내거나, 파일 내용을 명령의 입력으로 넣을 수 있습니다.

>는 표준 출력을 파일로 저장합니다. 단, 같은 이름의 파일이 이미 있으면 기존 내용을 지우고 새로 씁니다.

grep ' 404 ' access.log > not-found.log
cat not-found.log

덮어쓰기가 걱정될 때는 먼저 확인합니다.

ls -l not-found.log
cat not-found.log

중요한 파일이라면 덮어쓰기 전에 복사본을 만듭니다.

cp not-found.log not-found.log.bak

>>는 파일 끝에 내용을 추가합니다. 기존 내용을 보존하면서 기록을 쌓을 때 사용합니다.

date >> work.log
grep 'ERROR' app.log >> work.log
cat work.log

<는 파일을 표준 입력으로 넣습니다. 어떤 명령은 파일 이름을 직접 받을 수도 있지만, 표준 입력을 쓰면 데이터가 어디에서 들어오는지 더 명확하게 볼 수 있습니다.

wc -l < access.log
sort < names.txt

오류를 따로 저장하려면 2>를 씁니다. 여기서 2는 표준 오류를 뜻합니다.

ls access.log missing.log > ok.txt 2> error.txt
cat ok.txt
cat error.txt

위 명령에서 정상 결과는 ok.txt에 들어가고, 없는 파일 때문에 생긴 오류는 error.txt에 들어갑니다. 문제를 조사할 때 이 방식이 유용합니다. 정상 출력과 오류가 섞이지 않기 때문입니다.

정상 출력과 오류를 한 파일에 함께 저장하려면 Bash에서 다음처럼 쓸 수 있습니다.

ls access.log missing.log > all.txt 2>&1
cat all.txt

2>&1은 표준 오류를 표준 출력이 가는 곳으로 보내라는 뜻입니다. 순서가 중요합니다. 먼저 > all.txt로 표준 출력을 파일로 보낸 뒤, 2>&1로 표준 오류도 그 목적지를 따라가게 합니다.

Bash에서는 더 짧게 쓸 수도 있습니다.

ls access.log missing.log &> all-bash.txt

다만 &>는 Bash에서 흔히 쓰는 문법입니다. 여러 셸에서 최대한 넓게 통하는 형태를 원한다면 > 파일 2>&1을 기억해 두는 편이 좋습니다.

파이프로 명령어 이어 붙이기

파이프 |는 앞 명령의 표준 출력을 뒤 명령의 표준 입력으로 넘깁니다. 파일을 중간에 만들지 않고도 작업 흐름을 이어 붙일 수 있습니다.

grep ' 404 ' access.log | wc -l

이 명령은 두 단계로 읽으면 쉽습니다.

  1. grep ' 404 ' access.log가 404가 들어 있는 줄만 고릅니다.

  2. wc -l이 그 줄 수를 셉니다.

중간 결과가 궁금하면 파이프 앞부분만 먼저 실행합니다.

grep ' 404 ' access.log

파이프라인을 만들 때는 한 번에 길게 쓰기보다 왼쪽부터 하나씩 확인하는 습관이 중요합니다. 출력이 예상과 다르면 다음 명령을 붙이기 전에 멈추고 고쳐야 합니다.

접속 로그에서 IP별 요청 횟수를 세어 보겠습니다.

awk '{print $1}' access.log | sort | uniq -c | sort -nr

흐름은 다음과 같습니다.

  • awk '{print $1}' access.log: 첫 번째 열인 IP만 뽑습니다.

  • sort: 같은 IP가 붙어 있도록 정렬합니다.

  • uniq -c: 연속된 같은 줄의 개수를 셉니다.

  • sort -nr: 숫자 기준으로 큰 값부터 정렬합니다.

프로세스 목록에서도 같은 방식으로 쓸 수 있습니다.

ps aux | grep '[s]sh'

grep '[s]sh'처럼 쓰면 grep ssh 명령 자신이 결과에 섞이는 일을 줄일 수 있습니다. 하지만 특정 프로세스를 찾는 목적이라면 pgrep -a ssh가 더 간단할 때도 있습니다. 중요한 것은 파이프를 무조건 쓰는 것이 아니라, 출력 구조를 보고 적절한 도구를 고르는 것입니다.

파이프는 기본적으로 표준 출력만 넘깁니다. 표준 오류는 뒤 명령으로 가지 않고 화면에 남습니다.

ls access.log missing.log | wc -l

오류까지 파이프로 넘기고 싶다면 표준 오류를 표준 출력으로 합친 뒤 넘깁니다.

ls access.log missing.log 2>&1 | wc -l

이 차이를 모르면 왜 어떤 메시지는 파일에 저장되지 않는지, 왜 어떤 줄은 grep으로 걸러지지 않는지 이해하기 어렵습니다.

tee로 화면 확인과 파일 저장을 동시에 하기

>를 쓰면 결과가 파일로 들어가므로 화면에는 보이지 않습니다. 작업 중에는 화면으로도 보고 파일에도 남기고 싶을 때가 많습니다. 이때 tee를 사용합니다.

grep 'ERROR' app.log | tee errors.log

tee는 표준 입력으로 받은 내용을 화면으로 다시 내보내면서 파일에도 저장합니다. 그래서 뒤에 다른 명령을 계속 연결할 수 있습니다.

grep 'ERROR' app.log | tee errors.log | wc -l

이 명령은 오류 줄을 errors.log에 저장하면서 동시에 오류 개수를 셉니다.

기존 파일 끝에 추가하려면 -a를 사용합니다.

grep 'WARN' app.log | tee -a errors.log
cat errors.log

관리자 권한 파일에 내용을 추가할 때도 tee가 쓰입니다. 예를 들어 다음 형태는 셸의 리다이렉션이 아니라 tee 명령 자체를 sudo로 실행합니다.

echo '127.0.0.1 app.local' | sudo tee -a /etc/hosts

단, /etc/hosts 같은 시스템 파일은 잘못 수정하면 네트워크 이름 해석에 문제가 생길 수 있습니다. 실습으로 실행하지 말고, 필요할 때는 먼저 파일을 백업하고 변경할 줄이 정확한지 확인한 뒤 사용합니다.

xargs로 결과를 다음 명령의 인자로 넘기기

파이프는 데이터를 표준 입력으로 넘깁니다. 그런데 어떤 명령은 표준 입력이 아니라 명령 뒤의 인자를 기대합니다. 이때 xargs가 중간에서 입력을 인자로 바꾸어 줍니다.

cat names.txt | sort | uniq | xargs -n 1 echo user:

-n 1은 입력값을 하나씩 끊어서 명령을 실행하라는 뜻입니다. 결과적으로 이름 하나마다 echo user:가 실행됩니다.

파일 검색 결과에 작업을 적용할 때도 xargs를 자주 씁니다.

mkdir -p tmp
touch tmp/a.tmp tmp/b.tmp tmp/keep.txt
find tmp -name '*.tmp' -print

삭제하기 전에는 반드시 먼저 검색 결과만 확인합니다. 결과가 맞는지 확인하지 않고 바로 rm으로 넘기면 엉뚱한 파일을 지울 수 있습니다.

안전하게 삭제 명령을 연결하려면 다음처럼 씁니다.

find tmp -name '*.tmp' -print0 | xargs -0 -r rm -i

-print0와 -0는 파일 이름 사이를 일반 공백이 아니라 널 문자로 구분합니다. 파일 이름에 공백이 있어도 안전하게 처리하기 위한 방법입니다. -r은 입력이 없으면 명령을 실행하지 않게 합니다. 대부분의 Linux 배포판에서 쓰는 GNU xargs에서 사용할 수 있습니다. rm -i는 파일마다 삭제 여부를 물어봅니다.

실제로 삭제하기 전에는 다음처럼 echo를 붙여 실행될 명령을 미리 보는 방법도 좋습니다.

find tmp -name '*.tmp' -print0 | xargs -0 -r echo rm -i

위 출력이 예상과 같을 때만 echo를 제거합니다.

실전 시나리오: 로그에서 필요한 내용만 남기기

웹 요청 로그에서 404 오류가 난 경로를 확인하고, 결과도 파일로 남겨 보겠습니다.

grep ' 404 ' access.log | tee not-found.log | awk '{print $3}' | sort | uniq -c | sort -nr

이 파이프라인은 다음 일을 한 줄로 처리합니다.

  1. 404가 포함된 줄만 고릅니다.

  2. 고른 줄 전체를 not-found.log에 저장합니다.

  3. 세 번째 열인 경로만 뽑습니다.

  4. 같은 경로끼리 모아 개수를 셉니다.

  5. 많이 나온 경로부터 보여 줍니다.

문제가 생기면 전체를 한 번에 의심하지 말고 왼쪽부터 끊어서 확인합니다.

grep ' 404 ' access.log

grep ' 404 ' access.log | awk '{print $3}'

grep ' 404 ' access.log | awk '{print $3}' | sort

이 습관이 파이프라인 디버깅의 핵심입니다. 각 단계의 출력이 다음 단계가 기대하는 입력인지 확인하면 긴 명령도 어렵지 않습니다.

짧은 실습 과제

  1. app.log에서 ERROR가 들어 있는 줄을 only-errors.log에 저장하세요. 기존 파일이 있다면 덮어써도 되는지 ls -l로 먼저 확인하세요.

  2. ls access.log none.log의 정상 출력과 오류를 각각 다른 파일에 저장하세요. 파일 이름은 ls-ok.txt, ls-error.txt로 합니다.

  3. access.log에서 IP별 요청 횟수를 세고, 결과를 ip-count.txt에 저장하세요. 화면에도 결과가 보이게 tee를 사용하세요.

  4. tmp 디렉터리에서 .tmp 파일을 찾은 뒤, xargs와 echo로 삭제될 명령을 먼저 출력하세요. 출력이 맞으면 rm -i로 하나씩 확인하며 삭제하세요.

핵심 정리

리다이렉션은 명령어와 파일 사이의 방향을 바꿉니다. 파이프는 명령어와 명령어 사이를 연결합니다. tee는 중간 결과를 보면서 저장하게 해 주고, xargs는 출력 목록을 다음 명령의 인자로 바꿔 줍니다.

이제 Linux 명령어는 하나씩 외워서 실행하는 도구가 아니라, 필요한 흐름대로 조립하는 작업 시스템이 됩니다. 중요한 것은 긴 명령을 한 번에 완성하는 능력이 아닙니다. 표준 입력, 표준 출력, 표준 오류가 어디로 흐르는지 추적하고, 각 단계의 결과를 확인하며 안전하게 연결하는 습관입니다.

책 목록

처음부터 실전까지, 터미널이 두렵지 않은 Linux 활용법

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기