이 글에서 다루는 내용

이 글에서는 sudo tee로 systemd 서비스 파일을 생성하는 명령어 패턴을 분석하고, 왜 sudo echo > file 대신 tee를 써야 하는지, 그리고 비슷해 보이지만 목적이 전혀 다른 teesed의 차이를 정리한다.

sudo tee로 시스템 파일 만들기

/etc/systemd/system/ 같은 디렉토리는 루트 권한이 있어야 쓸 수 있다. 이럴 때 흔히 등장하는 패턴이 아래와 같다.

sudo tee /etc/systemd/system/myservice.service >/dev/null <<'EOF'
[Unit]
Description=My Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/node server.js
Restart=always

[Install]
WantedBy=multi-user.target
EOF

sudo cat > file이 아니라 sudo tee file인가

셸의 리다이렉션(>)은 sudo의 권한 상승 대상이 아니다. sudo는 그 뒤에 오는 명령어만 관리자 권한으로 실행할 뿐, 리다이렉션 자체는 현재 로그인한 사용자의 권한으로 셸이 처리한다.

sudo echo "text" > /etc/protected_file   # 실패: > 부분은 일반 사용자 권한
echo "text" | sudo tee /etc/protected_file   # 성공: tee 자체가 sudo로 실행됨

tee는 프로그램 자체가 파일 쓰기를 담당하기 때문에, teesudo로 실행하면 파일 쓰기도 root 권한으로 이루어진다.

>/dev/null이 붙는 이유

tee는 원래 파일 저장과 동시에 화면에도 출력한다. 히어독으로 여러 줄의 서비스 설정을 붙여넣을 때 화면에 그대로 다시 찍히면 지저분하므로, >/dev/null로 화면 출력만 버린다.

히어독(<<'EOF' ... EOF)의 따옴표 유무

EOF를 따옴표로 감싸면(<<'EOF') 안의 $변수나 백틱 명령어 치환이 일어나지 않고 문자 그대로 전달된다. 따옴표 없이 <<EOF로 쓰면 셸이 변수 확장을 시도하므로, 설정 파일 안에 $ 기호가 있다면 반드시 따옴표를 붙여야 한다.

파일 생성 후에는 보통 아래 순서로 서비스를 등록한다.

sudo systemctl daemon-reload
sudo systemctl enable myservice
sudo systemctl start myservice

tee와 sed는 뭐가 다른가

이름도 비슷하고 파이프라인에서 자주 같이 등장하다 보니 헷갈리기 쉽지만, 둘은 역할이 완전히 다르다.

tee는 입력을 가공하지 않고 그대로 파일에 저장하면서 동시에 화면으로도 흘려보내는 도구다. 즉 "복사"에 가깝다.

echo "hello world" | tee output.txt
# output.txt 내용: hello world (변경 없음)

sed는 입력 내용을 검색하고 치환하거나 삭제하는 등 실제로 텍스트를 변형하는 도구다.

echo "hello world" | sed 's/hello/goodbye/'
# 출력: goodbye world

함께 쓰이는 경우

둘은 경쟁 관계가 아니라 파이프라인에서 자주 함께 사용된다.

cat config.txt | sed 's/DEBUG=false/DEBUG=true/' | tee config_new.txt

sed가 내용을 치환하고, 그 결과를 tee가 파일로 저장하면서 화면에도 출력하는 구조다.

선택 기준

파일에 내용을 그대로 옮겨 적고 싶다면 tee, 이미 있는 내용 중 특정 부분만 찾아서 바꾸거나 지우고 싶다면 sed를 쓰면 된다. 앞서 다룬 sudo tee ... <<'EOF' 패턴은 완전히 새로운 텍스트를 그대로 파일에 옮기는 작업이라 tee가 맞는 선택이다.