【问题标题】:rsync succeeds from the shell but complains of "syntax or usage error" from crontabrsync 从 shell 成功,但从 crontab 抱怨“语法或使用错误”
【发布时间】:2019-11-25 13:53:32
【问题描述】:

以下 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 使用/bin/sh 运行命令,它不支持交互式shell 的所有花哨语法。用&lt;(...) 替换命令不是标准sh 语言的一部分。
  • 您可以将rsync 命令放在一个shell 脚本中(以指定bash 的shebang 行开头——#!/bin/bash#!/usr/bin/env bash),然后从cron 运行该脚本。
  • 感谢@Wumpus 的回答。如果您将其放在答案中,我可以为您的 StackOverflow 声誉做出贡献。
  • 只是加入。尝试用完整路径替换 rsync。通常是 (/usr/bin/rsync)。

标签: cron centos7 rsync


【解决方案1】:

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

当您将更复杂的命令放入 crontab 时,您会发现存在差异。在您的示例中,我怀疑命令替换运算符&lt;(...)。 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 运行 that

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    • 2021-09-09
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多