从 centos 到 Ubuntu 的 Cronjobs 很难

从 centos 到 Ubuntu 的 Cronjobs 很难

我正在将我的 vps 服务器从 centos 切换到 ubuntu。因为社区(jeej,这是我向该社区提出的第一个问题)。

我的 cronjobs 在我的 centos vps 上完美运行,如下所示:

01 22 * * * source /home/crawler2/env/bin/activate && cd /home/crawler2/project_spiderrooy && scrapy crawl spiderrooy > /home/crawler2/logs/spiderrooy_log_$(date '+\%Y-\%m-\%d').txt 2>&1

在我的 ubuntu vps 上试了几次,但没用。在网上找到一个代码片段(这里某处 bash 和 dash 的工作方式不同,所以尝试了这个:

01 22 * * * "$(command -v bash)" 'source /home/crawler1/env/bin/activate && cd /home/crawler1/project_spiderrooy && scrapy crawl spiderrooy > /home/crawler1/online/flask/static/logs/spiderrooy_log_$(date '+\%Y-\%m-\%d').txt 2>&1'

也不起作用,尝试过不写日志,但仍然不起作用。手动命令确实有效。

sudo grep CRON /var/log/syslog:

Jan 13 12:11:01 crawler2 CRON[2906]: (crawler2) CMD (-v bash)"  'source /home/crawler2/env/bin/activate && cd /home/crawler2/project_spiderahridderkerk && scrapy crawl spiderahridderkerk')
Jan 13 12:11:01 crawler2 CRON[2905]: (CRON) info (No MTA installed, discarding output)

使用我的所有变体,我都无法写入日志文件,也无法执行命令,即使没有不带日期的 logwrite 日志写入也是如此。

问题是,我如何在 ubuntu 中运行这个 centos cron,并使用 logwrite 日期,以及如何停止未安装 MTA 的垃圾?

谢谢。

答案1

根本问题source巴什主义- 这在 Ubuntu 中是一个问题,因为 的默认 shellcron/bin/sh- 并且解析为dashshell。

处理这个问题的最佳方法取决于许多因素。你在其他地方找到的修复方法是使用command -v bash(完全合格的)bash shell 显式运行命令,这是一种选择(尽管如heemayl 的回答,你错过了-c命令字符串之前的;基于 syslog 条目

Jan 13 12:11:01 crawler2 CRON[2906]: (crawler2) CMD (-v bash)"  'source /home/crawler2/env/bin/activate && cd /home/crawler2/project_spiderahridderkerk && scrapy crawl spiderahridderkerk')

它实际上看起来更像你的 crontab 条目

01 22 * * * "($command -v bash)" source /home/crawler1/env/bin/activate && cd /home/crawler1/project_spiderrooy && scrapy crawl spiderrooy > /home/crawler1/online/flask/static/logs/spiderrooy_log_$(date '+\%Y-\%m-\%d').txt 2>&1'

扩展($command -v bash)到也( -v bash)试图-v bash在子shell中执行,而不是command -v bash在命令替换中运行)。

实际上,plain 不太可能(考虑到 cron 相当受限制的默认参数)bash解析为不同于 的任何内容$(command -v bash),因此恕我直言,plainbash -c '. . .'/bin/bash -c '. . .'也是可以接受的。

在评论中,你指出你自己的解决方案是添加SHELL=/bin/bash- 我个人对此没有问题:如果你担心 bash 与 dash 的开销,你可以始终将范围限制为特定条目或条目组,例如

# default shell
*/3 * * * * /bin/echo "Job 1 run with \$SHELL=$SHELL" >> $HOME/crontab.log

SHELL=/bin/bash
*/5 * * * * /bin/echo "Job 2 run with \$SHELL=$SHELL" >> $HOME/crontab.log

SHELL=/bin/sh
*/7 * * * * /bin/echo "Job 3 run with \$SHELL=$SHELL" >> $HOME/crontab.log

结果是

$ tail -f ~/crontab.log
Job 1 run with $SHELL=/bin/sh
Job 3 run with $SHELL=/bin/sh
Job 2 run with $SHELL=/bin/bash
Job 1 run with $SHELL=/bin/sh
Job 1 run with $SHELL=/bin/sh
Job 2 run with $SHELL=/bin/bash
Job 3 run with $SHELL=/bin/sh

最后,如果/home/crawler1/env/bin/activate实际上是一个 POSIX 脚本(或者可以相对轻松地制作成 POSIX 脚本),并且作业中的其余命令是二进制可执行文件或具有自己有效 shebang 行的脚本,那么您可以简单地将命令更改source为其 POSIX 等效命令,.以便所有内容都在默认dashshell 中运行。

答案2

您应该在命令之后运行任何内容$(command -v bash)bashbash -c ...,否则整个内容将被视为要由的文件进行解释bash

做:

"$(command -v bash)" -c 'source ...'

因此,在crontab

01 22 * * * "$(command -v bash)" -c 'source ...'

相关内容