GPG脚本化加解密必须使用--batch和--yes禁用交互,密码通过--passphrase-file安全传入, recipient需明确指定且公钥已导入,错误处理应检查退出码并校验输出。

gpg 命令行加解密必须用 --batch 和 --yes 才能脚本化
交互式 GPG 默认会弹出密码输入提示,脚本里直接调用 gpg -d 会卡住。必须显式禁用交互行为,否则任务在 CI 或定时任务里直接失败。
-
--batch关闭所有交互式提示(包括密钥选择、密码输入) -
--yes自动确认覆盖、不安全算法等警告(否则某些旧版本 GPG 仍会阻塞) - 缺一不可:只加
--batch在部分环境(如 systemd service)下仍可能因 tty 检测失败而挂起
解密时必须指定私钥密码,不能靠 gpg-agent 缓存
自动化场景下,gpg-agent 通常未运行或缓存已过期,依赖它会导致解密随机失败。得把密码传给 GPG,但绝不能硬编码到脚本里。
- 用环境变量传参:
GPG_PASSPHRASE="xxx" gpg --batch --yes --passphrase-fd 0 -d file.gpg,然后用echo "$GPG_PASSPHRASE" | ... - 更安全的做法是读取文件:
gpg --batch --yes --passphrase-file /etc/secrets/gpg-pass --decrypt data.gpg,注意该文件权限必须为600且属主为运行用户 - 别用
--passphrase命令行参数——它会出现在ps输出里,有泄露风险
加密时选对 recipient 且确保公钥已导入本地 keyring
脚本里执行 gpg -e 失败,90% 是因为目标公钥没导入当前用户的 keyring,或者用了错误的 key ID。
- 检查是否已导入:
gpg --list-keys "user@example.com"或gpg --list-keys 0xABC123DE - 加密命令必须明确指定 recipient:
gpg --batch --yes --recipient "user@example.com" --encrypt input.txt - 别依赖默认 key:脚本运行用户和交互登录用户 keyring 不同,
gpg --default-recipient容易误配 - 若用子密钥加密,recipient 应填主密钥 ID;GPG 会自动选可用的加密子密钥
脚本里处理 gpg 错误码比捕获 stdout 更可靠
GPG 出错时,错误信息可能混在 stderr,也可能根本没输出,仅靠 if [ $? -ne 0 ] 判断不够——有些失败返回 0 却没生成输出,比如密钥过期但没报错。
- 始终检查退出码:
gpg --batch --yes ... || { echo "GPG failed"; exit 1; } - 解密后校验输出文件是否存在且非空:
[[ -s decrypted.txt ]] || { echo "Decryption produced empty output"; exit 1; } - 避免重定向所有输出:
2>/dev/null会吞掉关键错误,至少保留 stderr 到日志
真正麻烦的是密钥信任链和过期时间——GPG 不会在命令行里主动提醒“该密钥已于昨天过期”,它就静默失败。每次部署前手动跑一遍加解密测试,比写一百行容错逻辑都管用。


















