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

sudo -S와 heredoc stdin 충돌 해결

sudo -S와 heredoc 동시 사용 시 stdin 충돌 주의.

bashsudoshellstdinheredoc

sudo -S와 heredoc을 같이 쓰면 비밀번호 입력이 안 되는 문제 겪어봤어? 둘 다 표준 입력(stdin)을 사용하려다 보니 heredoc이 우선권을 가져가서 sudo가 비밀번호를 못 받게 됨.

문제 상황 예시:

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

위처럼 하면 sudo: no password was provided 에러가 뜸.

해결 방법: sudo bash -c를 사용해서 명령어를 싱글 쿼트로 묶어주면 돼. 이게 가장 깔끔함.

echo 'PW' | sudo -S bash -c 'printf "line1\nline2\n" >> /etc/fstab'

여러 sudo 명령을 연속으로 써야 한다면, 미리 sudo -v로 인증을 캐싱해두면 편리해.

여기서 배울 것

  1. `sudo -S`와 heredoc은 모두 표준 입력(stdin)을 사용함.
  2. 두 기능이 동시에 stdin을 사용하려 할 때 heredoc이 우선권을 가짐.
  3. 이로 인해 `sudo -S`가 비밀번호를 받지 못해 인증 실패가 발생함.
  4. `sudo bash -c`를 활용하여 heredoc 충돌 없이 sudo 명령을 실행할 수 있음.
원본 파일 보기 (.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.