cronjob 不执行独立运行的脚本
Posted
技术标签:
【中文标题】cronjob 不执行独立运行的脚本【英文标题】:cronjob does not execute a script that works fine standalone 【发布时间】:2016-08-21 12:29:04 【问题描述】:我的 php 脚本文件位于 /var/www/html/dbsync/index.php
。当cd /var/www/html/dbsync/
并运行php index.php
时,它可以完美运行。
我想通过sh文件调用php文件,sh文件的位置如下
/var/www/html/dbsync/dbsync.sh
这是dbsync.sh
文件的内容是:
/usr/bin/php /var/www/html/dbsync/index.php >> /var/www/html/dbsync/myscript.log 2>&1 -q -f
当我 cd /var/www/html/dbsync/
并运行 ./dbsync.sh
时,它也能完美运行。
现在如果我如下设置 crontab:
1 * * * * /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
但是,这个 crontab 没有按预期工作。
有什么问题?
【问题讨论】:
第二个 /var/www/html/dbsync 是干什么用的? /var/www/html/dbsync - dbsync 是 index.php 和 dbsync.sh 文件的保存目录。 现在我想尝试每一秒。稍后,如果执行所需的结果,我将每天设置为午夜 你能把所有这些命令放在另一个文件中,让它以chmod +x filename
执行,然后将该文件添加到crontab 中吗?让我知道结果。
你应该指定二进制文件来执行 sh 脚本 --> 1 * * * * /bin/sh /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
或者你说which sh
得到的任何东西。
【参考方案1】:
正如在 cmets 中看到的那样,问题在于您没有定义应该使用什么程序来执行脚本。考虑到 cronjob 是在很小的环境中执行的;在那里,不能假设太多。这就是我们定义完整路径等的原因。
所以你需要这样说:
1 * * * * /bin/sh /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
# ^^^^^^^
/bin/sh
是您要用于执行脚本的二进制文件。
否则,您可以为脚本设置执行权限并添加shell-script header 告诉它使用什么解释器:
#!/bin/sh
如果这样做,则不需要添加二进制文件的路径。
来自Troubleshooting common issues with cron jobs:
使用相对路径。如果您的 cron 作业正在执行一些脚本 种类,您必须确保在该脚本中仅使用绝对路径。 例如,如果您的脚本位于 /path/to/script.php 并且 您正在尝试在同一目录中打开一个名为 file.php 的文件, 您不能使用诸如 fopen(file.php) 之类的相对路径。该文件必须 从其绝对路径调用,如下所示:fopen(/path/to/file.php)。 这是因为 cron 作业不一定从目录中运行 脚本所在的位置,所以必须专门调用所有路径。
另外,我了解您希望每分钟运行一次。如果是这样,1 * * * *
就不行了。 Intead,它将运行at every 1st minute past every hour。因此,如果您想每分钟运行一次,请说* * * * *
。
【讨论】:
谢谢@fedorqui 这工作得很好,我会记住要提到应该使用哪个程序来执行脚本。 @sanainfotech 不客气 :) 你提供了很多细节,所以我试图使答案足够通用,以便在其他情况下用作参考。【参考方案2】:理解“login shell”和“interactive shell”的含义很重要。
login shell:当您使用 ssh session 登录并获得一个终端窗口时,您可以在其中输入 shell 命令。登录后系统会执行一些文件(.bashrc)并为您设置一些环境变量,例如PATH变量。 交互式shell:登录系统后,您可以手动启动shell终端。系统执行分配给您帐户的一些配置文件(.bash_profile、.bash_login、.profile)。该文件还为您手动打开的 shell 会话设置一些环境变量并初始化 PATH 变量。由操作系统启动的 shell 脚本和 cron 作业不适合上述启动 shell 的方式。因此不会执行任何系统脚本(.bashrc)或用户配置文件。这意味着我们的 PATH 变量没有被初始化。找不到 Shell 命令,因为 PATH 变量未指向正确的位置。
这解释了为什么您的脚本在手动启动时运行成功,但在您通过 crontab 启动时失败。
解决方案 1: 使用每个 shell 命令的绝对路径,而不是仅使用脚本文件中使用的命令名称。
使用“/usr/bin/awk”代替“awk” 用“/bin/sed”代替“sed”Solution-2:在执行shell脚本之前初始化环境变量,尤其是PATH变量!
【讨论】:
因为可以在 在 crontab 本身中设置一个PATH
(即使在初始条目中,但在文件的顶部 - 任何 key=value
对会自动导出到环境中),这个答案似乎没有明确讨论这种简单的方法来完成它的命令。【参考方案3】:
方法一,在你的dbsync.sh中添加这个头文件:
#!/bin/bash -l
方法2,在你的cron文件中添加bash -l:
1 * * * * bash -l /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
【讨论】:
请问#!/bin/bash -l
是什么意思
阅读手册。 -l
选项表示将 Bash 作为登录 shell 调用,它会读取更多的配置文件(尽管仍与指定 interactive 模式的-i
完全相同)。以上是关于cronjob 不执行独立运行的脚本的主要内容,如果未能解决你的问题,请参考以下文章