macOS下如何在bash脚本内清除带密码的运行命令在bash历史中的痕迹
问题根因
你之前在脚本内执行history相关命令无效,本质原因是运行独立bash脚本时系统会启动独立的子shell进程,子shell的历史记录空间和你当前操作的父交互式shell完全隔离,无法操作父shell内存中已经记录的带密码的命令行。
解决方案1:不修改调用习惯,直接修改现有脚本
在你原有脚本末尾新增如下逻辑,利用bash的PROMPT_COMMAND机制实现父shell层级的历史记录删除:
#!/bin/bash while getopts "p:" option; do case "${option}" in p) PASSWORD=${OPTARG};; esac done /usr/bin/expect -c " spawn ssh my.login.server.com expect { \"Password*\" { send \"$PASSWORD\r\" } } interact " # ========== 新增清除历史逻辑 ========== # 构造父shell待执行的清理命令 cat > /tmp/.tmp_clear_login_hist <<'EOF' # 读取最后一条历史的行号,适配macOS自带bash LAST_HIST_LINE=$(history 1 | awk '{print $1}') # 删除对应行历史 history -d ${LAST_HIST_LINE} # 将更新后的历史写入磁盘文件,避免终端退出时同步旧记录 history -w ~/.bash_history # 清理临时文件和环境变量 rm -f /tmp/.tmp_clear_login_hist unset PROMPT_COMMAND EOF # 将清理命令挂载到PROMPT_COMMAND,会在脚本执行完成回到父shell、显示提示符前自动执行 export PROMPT_COMMAND="source /tmp/.tmp_clear_login_hist"
该方案不需要修改你调用脚本的方式,仍然可以用./login.sh -p <密码>的方式运行,执行完成后命令行历史中不会留存这条带密码的记录。
解决方案2(更推荐):从根源避免密码出现在命令行
密码出现在命令行本身就存在安全风险(除了历史记录泄露,还会在ps等进程查询命令中暴露),建议直接取消密码传参逻辑,从根源避免问题:
版本A:交互式隐式输入密码
#!/bin/bash # 隐式输入密码,输入内容不会显示在屏幕上 read -s -p "请输入服务器登录密码:" PASSWORD echo -e "\n正在登录..." /usr/bin/expect -c " spawn ssh my.login.server.com expect { \"Password*\" { send \"$PASSWORD\r\" } } interact "
直接运行./login.sh按照提示输入密码即可,命令行全程不会出现明文密码。
版本B(macOS专属,免输入密码):利用系统钥匙串存储密码
- 打开「钥匙串访问」app,新增一条通用密码,「名称」填
my_server_login_pwd,「账户」随便填,「密码」填你的服务器登录密码,保存后授权信任该密码项 - 脚本修改为:
#!/bin/bash # 从系统钥匙串读取密码,全程无明文泄露 PASSWORD=$(security find-generic-password -s "my_server_login_pwd" -w) /usr/bin/expect -c " spawn ssh my.login.server.com expect { \"Password*\" { send \"$PASSWORD\r\" } } interact "
该方案安全性最高,密码只存在于系统钥匙串中,不会出现在任何明文位置,也不需要每次手动输入。
内容的提问来源于stack exchange,提问作者itsji10dra
相关产品推荐
相关产品推荐

