安全读密码需避免明文暴露:用 read -s 读取后通过 stdin 传递(如 echo "$pass" | sshpass -f -),或用 sshpass -e sshpass 配合临时环境变量并及时 unset;禁用硬编码。

怎么让 shell 脚本安全地读取密码而不暴露在 ps 或 history 里
直接用 read password 或把密码写进变量再传给 ssh/curl,进程列表里一眼就能看到明文——ps aux | grep curl 会漏出整个命令行。这不是“可能被看到”,是默认就会被看到。
- 用
read -s -p "Password: " password屏蔽回显,且别把$password拼进命令行字符串;改用 stdin 传入,比如echo "$password" | sshpass -f - ssh user@host - 更稳的做法是彻底绕过变量:用
sshpass -e SSHPASS ssh user@host,然后执行前临时设环境变量SSHPASS="xxx",并确保脚本退出后立即unset SSHPASS - 别把密码硬编码在脚本里,哪怕加了
chmod 600——运维脚本常被cat、grep、ansible拉取,权限拦不住读操作
判断远程主机是否存活,为什么不能只靠 ping
ping 返回 0 只说明 ICMP 通,但防火墙常禁 ICMP,而 SSH 端口(22)或 HTTP(80/443)开着才是真可用。反过来,ping 通却连不上 SSH 的情况太常见。
- 用
timeout 3 bash -c 'echo > /dev/tcp/$host/22' 2>/dev/null测试 TCP 连通性,比nc -z更少依赖外部命令 - 如果目标必须走 SSH 才算“活”,直接跑
timeout 5 ssh -o ConnectTimeout=3 -o BatchMode=yes user@$host true,BatchMode=yes防止卡在密码提示 - 注意
/dev/tcp/是 bash 内置功能,dash/sh 不支持;用bash -c '...'显式调用,别只写#!/bin/sh
日志文件自动轮转但不丢数据,logrotate 常见错在哪
直接配 rotate 7 + daily,结果 crond 触发时旧日志正被 tail -f 或应用持续写入,一转就丢最后几秒内容——logrotate 默认是先 mv 再 kill -USR1,中间有窗口期。
- 必须加
copytruncate:先拷贝再清空原文件,避免应用因文件句柄失效中断写入 - 如果应用支持重载信号(如 nginx 的
reload、rsyslog 的kill -HUP),优先用postrotate发信号,比copytruncate更精确 - 别信
dateext默认格式——%Y%m%d在跨年时可能和旧文件冲突,显式写成dateformat -%Y%m%d-%s避免重复名
用 find 清理临时文件,为什么 -mtime +7 总是删错
-mtime 看的是“修改时间距今多少个完整 24 小时”,不是“7 天前”。比如文件是昨天 23:59 修改的,今天 00:01 运行 find . -mtime +7,它才过 2 分钟,但已满足“大于 7×24 小时”,会被删掉。
- 要真正删“7 天前创建/修改”的文件,用
-newermt "7 days ago"(GNU find)或-newerct(创建时间),语义明确 - 清理
/tmp下的文件,务必加-maxdepth 1和-type f,否则可能递归进/tmp/systemd-private-xxx这类目录,误删运行中服务的 socket - 先加
-print预览,别一上来就-delete;-delete自带-depth,但某些老版本 find 不支持,保险起见还是用-exec rm {} +
脚本里的时间判断、路径遍历、凭据传递,每个点都卡在“看起来能跑通”和“线上不出问题”之间。差的不是语法,是那半秒没想清楚的执行上下文。










