【问题标题】:If-else-statement is working wrong in crontab?if-else-statement 在 crontab 中工作错误?
【发布时间】:2014-02-14 12:14:32
【问题描述】:

当我使用这个时:

*/5 6-18 * * 1-6 [ "$(ls -A /DIR_WHERE_FILES_ARE_OR_NOT/)" ] &&
  rsync -au /DIR_WHERE_FILES_ARE_OR_NOT/ /DIR_WHERE_FILES_SHOLD_GO; \
  mv /DIR_WHERE_FILES_ARE_OR_NOT/*  /SAVE_DIR/ ||
  mail -s "DIR IS EMPTY" myemail@klkldkl.de <<< "message"

我收到两封邮件:

mv: cannot stat `/DIR_WHERE_FILES_ARE_OR_NOT/*': 没有这样的文件或 目录

“目录为空”

为什么?

【问题讨论】:

  • 拥有一个具有这些条件的适当脚本并从 crontab 调用它怎么样?像这样,追踪和维护起来相当复杂。
  • 谢谢! :) 现在我已将两个命令更改为 { } 但它没有帮助
  • 仅当我退出 0 时;在这两个赞扬之后,我没有收到任何错误邮件,但是当文件在 DIR 中时,我收到一条错误消息:/bin/sh: -c: line 0: syntax error near unexpected token `}'

标签: bash shell if-statement crontab


【解决方案1】:

你得到

mv: cannot stat `/DIR_WHERE_FILES_ARE_OR_NOT/*': No such file or directory

正是出于上述原因:该目录是空的,因此它不包含名为*(星号)的文件。这正是 glob 扩展在 shell 中的工作方式:如果 glob 不匹配任何内容,则将其按字面意思传递给命令。由于mv 尝试重命名一个不存在的文件,它会报错,如图所示。

如果不是 crontab 中的一系列 &amp;&amp;|| 运算符,而是将整个逻辑放在具有等效 if/else/fi 构造的脚本中,然后从 cron 调用脚本,这一切都会更具可读性.

您收到两封邮件,因为您明确使用mail -s 发送第一封邮件。第二个来自 cron,因为 stderr 和 stdout 上的输出不为空。

你的命令相当于

if [ "$(ls ...)" ]; then
   rsync
fi
if ! mv; then
   mail
fi

注意这里没有else

【讨论】:

  • 但是为什么 crontab 不只做 if 语句或 else 语句呢?
  • 因为&amp;&amp;|| 的优先级。
  • 澄清一下,因为与分号结合的短路语义。在 shell 语法用语中,分号使这两个独立的 AND-OR-lists。在第二个列表中,mv || mail 都运行,因为 mv 失败。
【解决方案2】:

就像用户 Jens 已经提到的,也是根据我的经验,除非您使用非常简单且通常是单个命令,否则您应该坚持使用脚本文件。所以,在你的情况下,我会选择一个脚本文件。我给你举个例子。

#!/bin/bash

dir_where_files_are_or_not=/filespath
dir_where_files_should_go=/another/filespath
save_dir=/savefiles/path

# ok, lets start by checking if dir contains files
if [ "$(ls -A $dir_where_files_are_or_not)" ]; then
  # dir contains files, so lets rsync and mv them
  rsync -au $dir_where_files_are_or_not/ $dir_where_files_should_go
  mv $dir_where_files_are_or_not/* $save_dir
else
  # dir is empty, lets send email
   mail -s "DIR IS EMPTY" myemail@klkldkl.de <<< "message"
fi

现在,我只是将这段代码放在一个文件中。给它一个名字,例如“chkfiles”并将它保存在一个目录中(我对所有脚本都使用/usr/local/sbin)。

接下来,在 shell 中,运行命令 chmod +x /usr/local/sbin/chkfiles 以使文件可执行。然后将脚本添加到您的 crontab。

我建议在 crontab 中使用以下行:

*/5 6-18 * * 1-6 /bin/bash /usr/local/sbin/chkfiles

我使用 /bin/bash 为这个脚本调用了正确的解释器。它现在应该按预期工作。

重要提示:

  1. 在运行脚本之前,您需要根据需要更改 dir_where_files_are_or_notdir_where_files_should_gosave_dir 变量。
  2. 在 dirs 中包含斜杠,否则 rsync 和 mv 可能无法执行您真正想要的操作

问候

【讨论】:

    【解决方案3】:

    您会收到两封邮件,因为当mv 失败时,cron 会捕获写入标准错误的内容并将其邮寄给所有者,然后运行mail 命令。您可以隐藏来自mv 的错误消息,以避免来自cron 的邮件。

    mv /DIR_WHERE_FILES_ARE_OR_NOT/*  /SAVE_DIR/ 2> /dev/null || mail -s "DIR IS EMPTY" myemail@klkldkl.de <<< "message"
    

    【讨论】:

    • mv 失败时,mv 写入stderr,而不是cron
    • 我知道我的措辞很糟糕,但没有意识到多么很糟糕。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多