xiaowei-system/skills/devops/devops-umbrella/references/sudo-password-pattern.md

103 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Sudo 密码传递模式
> 常见陷阱heredoc 消耗密码导致 sudo 认证失败
## 模式对比
### ❌ 错误heredoc 中使用 `echo | sudo -S`
```bash
# 失败密码在第一个命令后被消耗sudo 第二次读取时得到空行
echo 'z1020' | sudo -S bash -c 'cat > /etc/file << EOF
some content
EOF
another command' # 这里 sudo 读不到密码
```
### ✅ 正确:单条命令直接 pipe
```bash
echo 'z1020' | sudo -S sysctl -w vm.swappiness=10
```
### ✅ 正确:多条命令用 bash -c内容不在 heredoc
```bash
# bash -c 的参数是单行字符串,不是 heredoc密码可重复使用
echo 'z1020' | sudo -S bash -c 'sysctl -w vm.swappiness=10 && sysctl -w net.core.default_qdisc=fq'
```
### ✅ 正确:分开执行(最可靠)
```bash
# 每条命令独立 pipe密码各用一次
echo 'z1020' | sudo -S sysctl -w vm.swappiness=10
echo 'z1020' | sudo -S sysctl -w net.core.default_qdisc=fq
echo 'z1020' | sudo -S sysctl -w net.ipv4.tcp_congestion_control=bbr
```
### ✅ 正确:用 tee 写入文件(替代 heredoc
```bash
# heredoc 需要交互式 shell用 tee 代替
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
```
## 根本原因
`echo 'password' | sudo -S` 中,密码通过 stdin 传递,但:
- **Heredoc `<<EOF`** 也会从 stdin 读取内容,把密码吃掉了
- **`sudo -S`** 第一次 read 成功,后续命令重试时 stdin 已耗尽
## 验证方法
```bash
# 检查上条 sudo 命令是否成功
sudo -n true && echo "sudo OK" || echo "sudo failed"
```
---
## 坑 #6sudo flag 顺序打错2026-06-28 实测)
**症状**:单独跑 `echo 'pw' | sudo -S -v` 接受密码,但换 `echo 'pw' | sudo -S <args>` 写法立即 `[3 incorrect password attempts]`
**根因**flag 顺序/组合打错(比如 `sudo -S -p '' gpg ...`)时 sudo wrapper 抛 usage error但 sudo 内部认证层把 stdin 已消耗算成"密码不匹配",导致 3 次 fail 锁。
**正确(-S 必须独立)**
```bash
echo 'z1020' | sudo -S gpg --dearmor -o /usr/share/keyrings/microsoft-edge.gpg /tmp/msedge.asc
```
**教训**:先在最小可工作命令验证 sudo 接受密码(`echo 'pw' | sudo -S whoami`再叠加业务参数。Flag 顺序/组合改一次验证一次。
---
## 坑 #7提议"额外步骤"前没先做 preflight浪费 3-4 步)
**反例**2026-06-28 Edge
1. 用户问要不要加 apt 自动更新源 → 直接跑到加 GPG key 那里,失败 2 次
2. 真相:`.deb` 安装时 post-install hook 早已写好 `/usr/share/keyrings/microsoft-edge.gpg``/etc/apt/sources.list.d/microsoft-edge.sources`,只是我没先看一眼。
**正确流程**:提议任何"额外配置"前先 fs 探测现状:
```bash
ls /etc/apt/sources.list.d/ | grep -i -E 'edge|micros|teams|vscode|...'
ls /usr/share/keyrings/ | grep -i -E 'edge|micros|microsoft|...'
cat /etc/apt/sources.list.d/<name>.list /etc/apt/sources.list.d/<name>.sources 2>/dev/null
```
**规则**:先 `ls`/`cat` 看现状,再告诉用户"剩什么没做",不要上来就说"我没做 X要不要我加"。
⚠️ **这条规律适用于大部分 `.deb` 包**Microsoft 系Edge 已验证VS Code/Teams/PowerToys 推测同模式)通常自带 post-install 写源。其他发行包Chrome / Slack / Discord beta通常**不**自带,需要手动加。
---
## 坑 #8用 `sudo -v` 单独 stamp回避管道 sudo 反复认证
**观察**`echo 'pw' | sudo -S <业务命令>` 容易踩 sudo flag 顺序/组合边界问题,反复解锁浪费时间。
**解决**:先 stamp sudo 缓存(默认 5min之后业务命令直接 `sudo <cmd>`
```bash
# 一次性输密码
echo 'z1020' | sudo -S -v
# 5 分钟内免密(不指定命令)
sudo dpkg -i /tmp/edge.deb
sudo apt update
```
**前提**5 分钟窗口期内能列出所有 sudo 操作。如果密集 sudo 命令散落在整个 session 里,就只能在每次登录态新发命令时分别 `echo | sudo -S`