← 전체로 돌아가기
공통 메모 shell

sudo -S와 heredoc 충돌

sudo -S에 비번 주려는데 heredoc이 가로채서 에러남.

bashsudoshellstdinheredoc

sudo -S랑 heredoc 같이 쓸 때 문제

/etc/fstab 에 내용 추가하려다 겪음.

echo 'PW' | sudo -S tee -a /etc/fstab > /dev/null <<EOF
UUID=... /mnt/x ext4 defaults 0 2
EOF

실행하니 "Sorry, try again. sudo: no password was provided" 에러. sudo가 비번 못 받음.

원인: sudo -S는 stdin에서 비번 읽음. heredoc (<<EOF)도 stdin을 자기 내용으로 덮어씀. heredoc이 이김. 그래서 파이프된 비번이 sudo에 안 감. heredoc 내용이 비번으로 들어간 셈.

해결: sudo -S랑 heredoc 같이 쓰지 마. 아래 중 하나로 처리.

  1. sudo bash -c 에 전체 명령을 single-quoted string으로 넘김 (추천)
echo 'PW' | sudo -S bash -c 'printf "line1\nline2\n" >> /etc/fstab'
  1. tee -a 에 echo/printf로 내용 파이프 (좀 지저분함)
printf 'line1\nline2\n' | { echo 'PW' | sudo -S -p "" tee -a /etc/fstab; }
  1. 임시 파일 만들고 sudo cp
printf '...' > /tmp/frag && echo 'PW' | sudo -S sh -c 'cat /tmp/frag >> /etc/fstab'

여러 sudo 명령 연달아 쓸 땐 sudo -v로 미리 비번 캐싱해두면 편함.

여기서 배울 것

  1. sudo -S는 stdin에서 비번 읽음.
  2. heredoc도 stdin을 덮어씀. 둘이 같이 쓰면 충돌남.
  3. sudo bash -c '...'로 여러 줄 명령 처리하는 게 깔끔.
  4. sudo -v로 비번 미리 캐싱 가능.
원본 파일 보기 (.claude/memory/sudo_S_heredoc_stdin_conflict.md)
---
name: sudo -S and heredoc both want stdin
description: Piping a password to sudo -S while the inner command reads a heredoc causes the heredoc to consume the password
date: 2026-04-18
tags: [bash, sudo, shell]
---

## What happened
Tried to append to `/etc/fstab` with:
```
echo 'PW' | sudo -S tee -a /etc/fstab > /dev/null <<EOF
UUID=... /mnt/x ext4 defaults 0 2
EOF
```
Got "Sorry, try again. sudo: no password was provided" — sudo received the heredoc body instead of the password.

## Root cause
`sudo -S` reads the password from stdin. But the heredoc (`<<EOF`) also redirects stdin to the heredoc body. The heredoc wins (it's the final stdin redirection on the command), so the piped password never reaches sudo.

## Next time
When writing files that need sudo, avoid combining `sudo -S` with heredocs. Use one of:

1. **`sudo bash -c` with a single-quoted string** (preferred for multi-line):
   ```
   echo 'PW' | sudo -S bash -c 'printf "line1\nline2\n" >> /etc/fstab'
   ```
2. **`tee -a` with echo/printf piped in, no heredoc**:
   ```
   printf 'line1\nline2\n' | { echo 'PW' | sudo -S -p "" tee -a /etc/fstab; }
   ```
   (awkward — prefer option 1)
3. **Write to a temp file first, then `sudo cp`**:
   ```
   printf '...' > /tmp/frag && echo 'PW' | sudo -S sh -c 'cat /tmp/frag >> /etc/fstab'
   ```

Use `sudo -v` first to cache credentials if doing many sudo commands in a row.