题
我有一个脚本,其中一部分如下所示:
for file in `ls *.tar.gz`; do
echo encrypting $file
gpg --passphrase-file /home/$USER/.gnupg/backup-passphrase \
--simple-sk-checksum -c $file
done
由于某种原因,如果我手动运行此脚本,则可以正常工作并且所有文件都已加密。如果我将其作为 cron 作业运行, echo $file
工作正常(我在日志中看到“正在加密 <文件>”),但文件未加密,并且 gpg 静默失败,没有 stdout/stderr 输出。
有什么线索吗?
解决方案
事实证明答案比我想象的要容易。有一个 --batch
缺少参数,gpg 尝试从 cron 作业不存在的 /dev/tty 中读取数据。调试我用过的 --exit-on-status-write-error
参数。但使用它时,我受到了 echoing 报告的退出状态 2 的启发 $?
正如 CD-Man 所建议的。
其他提示
在我的例子中,gpg 无法找到使用密钥的主目录:
GPG:无默认密钥:没有秘钥
GPG:0003608.cmd:签名+加密失败:没有秘钥
所以我添加了 --homedir /root/.gnupg
. 。最终命令看起来像
回声'密码'| gpg -vvv -homedir/root/.gnupg - -batch - -passphrase -fd 0 -o -output/usr/share/file.gpg -encrypt -sign/usr/share/share/file.bz2
您应该确保 cronjob 运行时 GPG 在您的路径中。你最好的猜测是获取 GPG 的完整路径(通过这样做 which gpg
)并使用完整路径运行它(例如 /usr/bin/gpp...
).
其他一些调试技巧:
- 输出的值
$?
运行 GPG 后(如下所示:回声“$?”)。这将为您提供退出代码,如果成功,该代码应该为 0 - 将 STDERR 重定向到 GPG 的 STDOUT,然后将 STDOUT 重定向到文件,以检查可能打印的任何错误消息(您可以在命令行中执行此操作:
/usr/bin/gpg ... 2>&1 >> gpg.log
)
确保运行 cron 作业的用户具有加密文件所需的权限。
我曾经遇到过这个问题。
我不能真正告诉你为什么,但我不认为 cron 使用与用户相同的环境变量执行。
实际上,我必须导出良好的路径才能使我的程序良好执行。gpg 至少尝试执行吗?
或者当 cron 执行时您尝试加密的文件实际上位于当前目录中?
也许尝试执行 echo whereis gpg
和 echo $PATH
在您的脚本中查看它是否包含...为我工作。
@skinp Cron 作业由 sh 执行,而大多数现代 Unix 使用 bash 或 ksh 进行交互式登录。最大的问题(根据我的经验)是 sh 不理解以下内容:
export PS1='\u@\h:\w> '
需要改为:
PS1='\u@\h:\w> '
export PS1
因此,如果 cron 运行一个使用第一种语法定义环境变量的 shell 脚本,那么在运行其他命令之前,其他命令将永远不会被执行,因为 sh 会尝试定义该变量。
就我而言:“GPG:解密失败:错误的会话密钥”。
尝试添加 /usr/bin/gpg、检查版本、设置 --batch、设置 --home (使用 /root/.gnupg 和 /home/user/.gnupg),但所有这些都不起作用。
/usr/bin/gpg -d --batch --homedir /home/ec2-user/.gnupg --no-mdc-warning -quiet --passphrase "$GPG_PP" "$file"
事实证明,AWS beanstalk 实例上的 cron 需要使用环境变量来设置 --passphrase $GPG_PP。现在的克朗:
0 15 * * * $(source /opt/elasticbeanstalk/support/envvars && /home/ec2-user/bin/script.sh >> /home/ec2-user/logs/cron_out.log 2>&1)