我想通过 cronjob 定期备份我的远程 VPS。两个系统都运行Debian 10。我一直在关注本指南并根据我的喜好进行了调整。脚本的相关部分:
/root/.local/bin/backup
#!/bin/bash
SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
rsync -avzAHXh -e ssh root@[someIP]:/path/to/remote/dir /path/to/local/dir \
|| { echo "rsync died with error code $?"; exit 1; }
当我从终端运行它时,一切正常。但是,如果我通过 cronjob 运行它:
crontab -u root -e
# m h dom mon dow command
0 6 * * * /root/.local/bin/backup >> /var/log/backup 2>&1
然后/var/log/backup
显示:
root@[someIP]: Permission denied (publickey).^M
rsync: connection unexpectedly closed (0 bytes received so far) [Receiver]
rsync error: error in rsync protocol data stream (code 12) at io.c(235) [Receiver=3.1.3]
rsync died with error code 12
cronjob 出了什么问题,我该怎么办?
PS:我已经删除了我在这里使用的 gpg 密钥的密码,试图使其工作。理想情况下,我想要一个即使我再次添加密码短语也能正常工作的解决方案。
答案1
Cron 执行的命令有一个非常基本的执行环境和路径设置,一个常见的错误是用普通用户 ID 来测试命令或脚本。然后由 Cron 运行时就会失败。
导出的环境变量经常被忽视。谨慎的做法是,在部署之前,以 root 身份在完全精简的环境中进行最终测试,使用子 shell。您始终可以添加一个一次性的 cronjob,它只需将其环境打印到日志文件中,这使您能够在 Cron 调用时模拟命令运行的确切条件。第二个优点是,如果发生任何错误,它可以显示在您的终端上,这样更容易调试。
看起来您的脚本中分配的变量未导出,因此 SSH 不会拾取它。
在脚本中使用绝对文件路径也很重要,除非您专门更改目录,否则您不能假设您位于特定目录中,在一次性测试脚本中打印工作目录,前面提到的也有帮助。您不能假设所有分布在这方面都是相同的。检查一下当然没有什么坏处。