Shell脚本不能全局自动输入密码,需按命令适配:sudo -S可读标准输入密码(末尾需换行),ftp需-i -n参数,chpasswd直接读user:pass格式,passwd部分系统支持--stdin。

不能直接“配置”Shell脚本自动输入密码——Shell本身不提供全局密码自动填充机制,必须针对具体命令选择适配的交互方式。硬写密码到脚本里还可能被进程列表或日志泄露,得看命令是否支持标准输入、是否有专用参数、是否需要多轮匹配。
sudo -S 是最安全的管道方案
只有加了 -S 参数,sudo 才会从标准输入读密码;不加就完全忽略管道或重定向内容。
-
echo "mypass" | sudo -S apt-get update—— 有效 -
echo "mypass" | sudo apt-get update—— 密码被丢弃,仍卡在提示符 - 密码末尾必须带换行(
\n),echo默认满足,但用printf时得手动加 - 如果脚本中多次调用
sudo,第一次输完后通常有缓存(默认 15 分钟),后续调用无需重复输
ftp / chpasswd 等命令依赖 -i 或 -stdin 参数
不是所有命令都默认接受 stdin 密码,必须查 man 确认是否有对应开关:
-
ftp必须带-i -n:前者禁用交互提示,后者跳过.netrc自动登录 -
chpasswd直接读取user:pass格式,不需要额外参数:echo "root:mypass" | chpasswd -
passwd不接受明文密码,但passwd --stdin(仅部分发行版支持,如 CentOS)或echo "mypass" | passwd --stdin username - 用
重定向时,EOF 前后不能有空格或制表符,否则 shell 不识别结束标记
ssh / git / telnet 等无密码参数的命令只能用 expect
ssh、git(HTTPS)、telnet 这类程序不读 stdin 密码,也不提供 -p 类参数,必须用 expect 模拟终端交互。
- 脚本第一行必须是
#!/usr/bin/expect,运行时用./script,不能用sh script(否则报spawn: command not found) -
expect匹配字符串要加通配:用"*password*"比"password:"更鲁棒(避免大小写、空格、本地化提示差异) -
send后必须跟\r(回车),不是\n;\n在某些终端下可能不触发确认 - 若远程命令执行完需保持连接,结尾加
interact;若只想执行完退出,改用expect eof
密码明文存储的风险和替代建议
把密码写死在脚本里,等于把钥匙贴在锁上——ps aux、/proc/*/cmdline、shell 历史、日志都可能暴露它。
- 优先用密钥认证代替密码:如
ssh-keygen+ssh-copy-id,彻底绕过密码环节 - 用环境变量传参:
PASSWD="mypass" ./script.sh,脚本里用$PASSWD,至少不会出现在文件里 - 用
read -s交互式读取一次密码,再复用到多个命令中,避免多次硬编码 -
expect脚本里别用set password "xxx",改用set password $env(PASSWD),启动前PASSWD=xxx ./script
真正麻烦的从来不是“怎么让脚本输密码”,而是“为什么非得输密码”。能免密的地方尽量免,实在绕不开时,选对工具、看清参数、避开换行和匹配陷阱,比堆技巧更重要。


















