rsync 从 shell 成功,但抱怨来自 crontab 的"syntax or usage error"



以下 crontab 行 (在 CentOS 7.6 上)

@daily rsync -rav --remove-source-files --files-from=<(find /home/qa/buildbot/master/packages/rhel7 -type f -mtime +30 -exec basename {} ;) /home/qa/buildbot/master/packages/rhel7 192.168.1.31:/local/raid0/buildbotpackages/packages/rhel7

失败,并向我发送以下电子邮件:

From: (Cron Daemon) <crontab@docker.local>
Subject: Cron <qa@docker> rsync -rav --remove-source-files --files-from=<(find /home/qa/buildbot/master/packages/rhel7 -type f -mtime +30 -exec basename {} ;) /home/qa/buildbot/master/packages/rhel7 192.168.1.31:/local/raid0/buildbotpackages/packages/rhel7

rsync: failed to open files-from file <(find /home/qa/buildbot/master/packages/rhel7 -type f -mtime +30 -exec basename {} ;): No such file or directory
rsync error: syntax or usage error (code 1) at main.c(1567) [client=3.1.2]

我查看了 rsync 的 main.c 的源代码,但看不到第 1567 行的相关性:

1557     SIGACTMASK(SIGINT, sig_int);
1558     SIGACTMASK(SIGHUP, sig_int);
1559     SIGACTMASK(SIGTERM, sig_int);
1560 #if defined HAVE_SIGACTION && HAVE_SIGPROCMASK
1561     sigprocmask(SIG_UNBLOCK, &sigmask, NULL);
1562 #endif
1563 
1564     /* Ignore SIGPIPE; we consistently check error codes and will
1565      * see the EPIPE. */
1566     SIGACTION(SIGPIPE, SIG_IGN);
1567 #ifdef SIGXFSZ
1568     SIGACTION(SIGXFSZ, SIG_IGN);
1569 #endif
1570 
1571     /* Initialize change_dir() here because on some old systems getcwd
1572      * (implemented by forking "pwd" and reading its output) doesn't
1573      * work when there are other child processes.  Also, on all systems
1574      * that implement getcwd that way "pwd" can't be found after chroot. */
1575     change_dir(NULL, CD_NORMAL);
1576 
1577     init_flist();

此外,当我从 shell 运行确切的 crontab 行时,它可以工作:

qa@docker /tmp$ rsync -rav --remove-source-files --files-from=<(find /home/qa/buildbot/master/packages/rhel7 -type f -mtime +30 -exec basename {} ;) /home/qa/buildbot/master/packages/rhel7 192.168.1.31:/local/raid0/buildbotpackages/packages/rhel7
sending incremental file list
sent 18 bytes  received 12 bytes  20.00 bytes/sec
total size is 0  speedup is 0.00
qa@docker /tmp$

关于如何调试此问题的任何想法?

损坏的 cron 作业通常是由于在与 cron 使用的一个不同的 shell 中测试命令而导致的。大多数流行的交互式 shell(如bashzsh以及标准/bin/sh(由 cron 使用)都有类似的基本语法,因为它们都是 Bourne shell 的后代。它们之间的相似性足够强,以至于您可以在一段时间内认为 cron 的命令语法与您的登录 shell 相同。

当您将更复杂的命令放入 crontab 时,您会发现存在差异。在您的示例中,我怀疑命令替换运算符<(...).这种类型的替换在 Bourne shell 中不存在,我认为 POSIX 也没有采用它,所以我不会相信它在 cron 工作中。

只需在另一个 shell 中运行一个命令,即可在系统上/bin/sh测试您的命令:

BIG-FANCY-PROMPT%>$ sh
$ rsync -rav --remove-source-files --files-from=<(find /home/qa/buildbot/master/packages/rhel7 -type f -mtime +30 -exec basename {} ;) /home/qa/buildbot/master/packages/rhel7 192.168.1.31:/local/raid0/buildbotpackages/packages/rhel7
... probably some error message here...
$ exit
BIG-FANCY-PROMPT%>$ _

如果你想不出用sh语法重写命令的方法,你总是可以显式调用bash或任何其他你喜欢的shell:

@daily bash -c '...'

这种方式涉及额外的引用层,以便sh将整个命令传递给bash而不尝试解析它。如果这变得太困难,那么把你的命令放在一个带有漂亮#!行的脚本中,然后从cron运行

最新更新