rsync 工作正常,直到我把它放入 crontab 中(更新:'date' 在 crontab 中不起作用)

rsync 工作正常,直到我把它放入 crontab 中(更新:'date' 在 crontab 中不起作用)

我有这个rsync命令,当我从命令行(Ubuntu Server 12.04.1 LTS)运行它时,它工作得很好。我希望它每小时按时运行一次,并将结果(连同错误)输出到日志文件。这是我放入 crontab 的命令:

0 * * * * root rsync -av --delete -e "ssh -i /root/.ssh/id_rsa" 
user@host:/path/to/dir/ user@host:/path/to/another/dir/ /destination/dir
--exclude='.DS_Store' &> /var/log/backup/`date '+%Y_%m_%d_%H:%M'`_hourlybackup.log

尽管 bash 的工作方式与我预期的完全一样,但当它在 crontab 中时却什么也没有发生。它甚至没有将任何错误写入文件。运行时没有ps aux | grep rsync显示任何有趣的内容。我似乎找不到问题所在。有什么想法吗?

更新:感谢我收到的答案,我能够调整命令以使其正常工作,尽管它们都没有单独解决问题。以下是我今天早上发现有效的方法:

0 * * * * /usr/bin/rsync -av --delete -e "ssh -i /root/.ssh/id_rsa" 
user@host:/path/to/dir/ user@host:/path/to/another/dir/ /destination/dir
--exclude='.DS_Store' > /var/log/backup/_hourlybackup.log 2>&1   

由于某种原因,date '+%Y_%m_%d_%H:%M'(用反引号括起来)导致了这个问题。如果我从命令中删除它,它就可以正常工作……尽管对我来说,拥有全面的备份日志很重要,所以我仍然想找到解决方案。我会继续努力,但如果有人知道,请随意。

答案1

正如我在更新中提到的,问题出在命令上date。事实证明,如果您将命令直接写入crontab,而不是写入 shell 脚本,则需要在选项字符串%中转义date。以下是最终有效的方法:

0 * * * * rsync -av --delete user@host:/path/to/dir 
user@host:/path/to/another/dir /path/to/destination
--exclude='.DS_Store' >
/var/log/backup/`date '+\%Y_\%m_\%d_\%H'`h_hourlybackup.log 2>&1

感谢所有帮助我解决这个问题的人。这个命令将来可能会变得更长更复杂,因此更适合用自己的 shell 脚本来编写,但crontab我认为现在直接在 中编写就足够了。

答案2

大多数情况下是因为你没有输入完整的rsync 路径

/usr/bin/rsync -av ...

您还可以尝试创建一个小型 shell 脚本并将该命令放在那里,然后从 cron 中执行该单个脚本

答案3

这可能是路径问题,但可能性不大,因为根应该/usr/bin在其路径中。

然而,crontab 命令很可能不能用 Bash 运行,而是用 Dash 运行. 这个&>结构是一个“巴什主义”[1][2]。

代替

command >& file

command > file 2>&1

使其在 Dash 中按预期工作。

答案4

本来只是对已检查的答案进行评论,但是由于是新的,所以还不能评论。

我只是想解释一下为什么你会看到这个问题。%表示换行符,第一个文本之后的任何文本都作为标准输入提供给命令。

所以你的 cron 命令:

rsync -av --delete -e "ssh -i /root/.ssh/id_rsa" user@host:/path/to/dir/ \
  user@host:/path/to/another/dir/ /destination/dir --exclude='.DS_Store' \
  &> /var/log/backup/`date '+%Y_%m_%d_%H:%M'`_hourlybackup.log

被解释为:

rsync -av --delete -e "ssh -i /root/.ssh/id_rsa" user@host:/path/to/dir/ \
  user@host:/path/to/another/dir/ /destination/dir --exclude='.DS_Store' \
  &> /var/log/backup/`date '+<<EOI
Y_
m_
d_
H:
M'`_hourlybackup.log
EOI

当 shell 尝试执行它时,它找不到第二个 `,因为它现在作为命令的标准输入的一部分存在。关键是要意识到所有 % 字符都需要转义,除非您确实需要换行符。

相关内容