当它从命令行 bash 工作时,无法从 crontab 运行 bash 脚本
Posted
技术标签:
【中文标题】当它从命令行 bash 工作时,无法从 crontab 运行 bash 脚本【英文标题】:Cannot run bash script from crontab when it works from command line bash 【发布时间】:2014-12-19 07:10:08 【问题描述】:我有一个奇怪的问题,即能够从命令行运行 bash 脚本,但不能从 root 的 crontab 条目运行。我正在运行 Ubuntu 12.04。
* * * * 1-5 root /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
如果我使用 bash 从 cmd 行运行脚本,它可以正常工作,但 sh
失败并出现以下错误:
> jmeter-cron-randomise.sh: 7: jmeter-cron-randomise.sh: arithmetic
> expression: expecting primary: " % 1 "
用谷歌搜索了这个问题,似乎标准 shell 没有与 bash 相同的数学运算符,如 %(模数)。我不确定为什么脚本中的 cron 作业失败了?我假设这是因为它没有使用 bash shell?它肯定是被 cron 守护进程触发的(可以在 /var/log/syslog 中看到它)。非常感谢任何帮助。
【问题讨论】:
你的 shebang 线上有什么? 您的cron
是否使用/bin/sh
运行命令?看起来它可能确实如此,因为如果您使用sh
而不是bash
(如:sh /home/…/jmeter-cron-randomise.sh
)运行脚本,则会出现错误。在 Ubuntu 上,/bin/sh
通常是 dash
,而不是 bash
。要修复,请在您的 crontab 条目中使用 bash /home/…/jmeter-cron-dandomise.sh >> …
。
看起来它正在运行 sh。如何强制它在 shebang 线之外运行 bash?
kal:运行bash /path/of/script.sh
。这个bash
应该是which bash
的输出,也就是二进制的全路径。
@kal head -n 1 /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh | cat -vE
的完整输出是什么?这将以视觉上明确的方式显示第一行,以帮助确定是否例如字节顺序标记使您的 shebang 无效。
【参考方案1】:
您可能需要告诉 cron 要使用的 shell 是 bash shell,因为它默认为 sh。您可以通过将此行放入您的 crontab 中来对所有 crontab 条目执行此操作:
SHELL=/bin/bash
请注意,这将导致 crontab 中的所有脚本都在 bash 下运行,这可能不是您想要的。如果您想将 crontab 行本身更改为仅运行 bash,请将其更改为:
* * * * 1-5 root /bin/bash /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log 2>&1
请注意,我还导致将 stderr 写入 cron.log 文件 (2>&1),这可能不是您想要的,但这是很常见的做法。这可以帮助您进一步诊断脚本中的错误。
【讨论】:
这几乎是正确的:它可以是/bin/bash
,也可以是/usr/bin/bash
或其他。有趣的是,真正的完整路径可以通过which bash
获取。
谢谢。通过 crontab -e 恢复为 root 用户使用 crontab 条目并面对原始问题我现在可以看到有用的失败消息 ------ 运行 jmeter-cron-randomiser 脚本 min = 1 random = 1933 rmin = 0 /bin/sh: 1: root: 未找到 /bin/sh: 1: root: 未找到 /bin/sh: 1: root: 未找到
感谢@viritude。通过编辑 /etc/crontab 解决了总体问题。
@fedorqui - 虽然这是正确的,但路径是已知的。 kal 在他对这个问题的第一条评论中提到它是 /bin/bash。【参考方案2】:
如果这对任何人都有帮助:对我来说,这似乎是因为我以“DOS”line endings(CR-LF)而不是“unix”行尾(LF)结束。这可以使用od 或您最喜欢的十六进制转储工具进行检查,例如:
od -c <script_file>
... 并寻找 \r\n 而不仅仅是 \n。
似乎(并且this article 支持它)CR 字符阻止“shebang”工作,因为它被解释为 shell 可执行文件的文件名的一部分。
(出现行尾本身是因为文件来自 git 存储库并通过 Windows 机器传输)。
【讨论】:
【参考方案3】:我在尝试以 root 身份安排数据库备份时也遇到了这个问题,这让我大吃一惊!我正在开发一个 CentOS 7 机器。
每当我检查/var/spool/mail/root
时,我都会看到一个日志:
sh: root: command not found
,但该命令将在终端中完美运行。
这对我有用:
我在以 root 身份登录时使用 crontab -e
创建了 crontab 条目。
以上面的命令为例:
* * * * 1-5 root /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
我删除了 root 用户条目,例如:
* * * * 1-5 /home/xxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/jmeter-cron-randomise.sh >> /home/xxxxxxx/jmeter/VerificationService-0.0.1-SNAPSHOT/cron.log
这解决了我的问题。
【讨论】:
以上是关于当它从命令行 bash 工作时,无法从 crontab 运行 bash 脚本的主要内容,如果未能解决你的问题,请参考以下文章
当它从一个 collectionView 移动到另一个时,如何实现单元格动画?
Python脚本在几秒钟后自动关闭,当它从IP摄像机对RTSP实时源进行对象检测时?