【问题标题】:Running rake tasks from crontab从 crontab 运行 rake 任务
【发布时间】:2019-05-31 11:55:51
【问题描述】:

我遇到了一个我无法想象解决方案的问题,并且让我困了一个星期。我在sudo crontab -e 中有以下两行。

* * * * * echo "crontab can log to reports" >> /var/log/mazer-reports.log
* * * * * /bin/bash -l -c 'cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log'

这是我的“mazer-reports.log”在 10 分钟左右后的样子:

crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports
crontab can log to reports

所以,第一个命令正在触发,并且记录正常。但是,第二个命令既不是记录,也不是触发适当的 rake 任务(在我的 Rails 应用程序中看不到任务的效果)。此外,我知道该命令没有任何问题,因为如果我只是获取命令本身并在我的控制台中运行它:

/bin/bash -l -c 'cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log'

然后我将以下内容附加到我的“mazer-reports.log”中,这是正确的:

   (0.8ms)  SELECT MAX("delayed_jobs"."priority") FROM "delayed_jobs" WHERE "delayed_jobs"."queue" = $1  [["queue", "RunReports"]]
   [ActiveJob]    (0.1ms)  BEGIN
   [ActiveJob]   SQL (0.4ms)  INSERT INTO "delayed_jobs" ("handler", "run_at", "queue", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  
   [["handler", "--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper\njob_data:\n  job_class: RunReportsSplitMasterJob\n  job_id: 79333d26-4917-4226-8d86-8fef481c86d0\n  provider_job_id: \n  queue_name: RunReports\n  priority: \n  arguments: []\n  executions: 0\n  locale: en\n"], ["run_at", "2019-01-04 22:06:35.189280"], ["queue", "RunReports"], ["created_at", "2019-01-04 22:06:35.189369"], ["updated_at", "2019-01-04 22:06:35.189369"]]
   [ActiveJob]    (0.5ms)  COMMIT
   [ActiveJob] Enqueued RunReportsSplitMasterJob (Job ID: 79333d26-4917-4226-8d86-8fef481c86d0) to DelayedJob(RunReports)

而且我还可以看到在我的 rails 应用程序上触发的任务的影响,而我无法从 crontab 中看到它,所以这不仅仅是一个日志记录问题。 crontab 根本不喜欢这个命令。这是sudo grep CRON /var/log/syslog的输出:

Jan  4 22:12:01 shopify-inventory-reports CRON[24417]: (root) CMD (echo "crontab can log to reports" >> /var/log/mazer-reports.log)
Jan  4 22:12:03 shopify-inventory-reports CRON[24415]: (CRON) info (No MTA installed, discarding output)
Jan  4 22:13:01 shopify-inventory-reports CRON[24453]: (root) CMD (/bin/bash -l -c 'cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log')
Jan  4 22:13:01 shopify-inventory-reports CRON[24454]: (root) CMD (echo "crontab can log to reports" >> /var/log/mazer-reports.log)
Jan  4 22:13:03 shopify-inventory-reports CRON[24452]: (CRON) info (No MTA installed, discarding output)
Jan  4 22:14:01 shopify-inventory-reports CRON[24490]: (root) CMD (/bin/bash -l -c 'cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log')
Jan  4 22:14:01 shopify-inventory-reports CRON[24491]: (root) CMD (echo "crontab can log to reports" >> /var/log/mazer-reports.log)
Jan  4 22:14:04 shopify-inventory-reports CRON[24489]: (CRON) info (No MTA installed, discarding output)
Jan  4 22:15:01 shopify-inventory-reports CRON[24528]: (root) CMD (/bin/bash -l -c 'cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log')

您可以从那里看到 cron 每分钟都在运行这两个命令(应该如此),并且没有在似乎什么都不做的命令上向 syslog 发布错误。相当混乱!

我在 Ubuntu 18 安装上运行 rails 5、puma 和 rbenv。所有这些东西都安装在名为deploy 的sudoer 用户上。下面是ls -l /var/log/mazer-reports.log的输出:

-rw-rw-rw- 1 root root 1543 Jan  4 22:10 mazer-reports.log

2018 年 1 月 6 日更新 Romeo Ninov 在评论中指出,我应该考虑 shell 与 cronjob 中的环境变量。果然,* * * * * /bin/bash -l -c 'echo $RAILS_ENV' >> /var/log/mazer-reports.log 的输出是空白的,这意味着 rake 不知道在需要生产时从 crontab 运行哪个 rails 环境。为了尝试解决这个问题,我将环境变量放在 crontab 中的命令本身中,如下所示:

 0 * * * * cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake RAILS_ENV=production run_split_accounting_after_close_master >> /var/log/mazer-reports.log`

但是,这仍然不能解决问题。命令仍然没有触发,也没有记录到指定的日志文件。我没有考虑其他一些必要的 rake 环境变量? Systemd 已经使用应用程序密码和数据库用户名和密码运行 puma。我从没想过 rake 会需要这样的东西,但如果我错了,请告诉我


2018 年 1 月 7 日更新 好的,很明显这是一个环境变量问题。我创建了一个名为“run_accounting”的单独 bash 文件,如罗密欧的回答中所述:

#!/bin/bash
source ~/.bashrc
echo "stuff from run_accounting bash" >> /var/log/mazer-reports.log
env >> /var/log/mazer-reports.log
cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log

现在,奇怪的是,如果我从终端点击 sudo ./run_accounting,rake 任务就会触发,我会在我的 mazer-reports.log 中得到以下输出:

stuff from run_accounting bash
SHELL=/bin/bash
TERM=xterm-256color
USER=root
SUDO_USER=deploy
SUDO_UID=1000
USERNAME=root
RACK_ENV=production
MAIL=/var/mail/root
PATH=/home/deploy/.rbenv/shims:/home/deploy/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
SECRET_KEY_BASE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PWD=/home/deploy
LANG=en_US.UTF-8
RBENV_SHELL=bash
SHLVL=1
SUDO_COMMAND=./run_accounting
HOME=/home/deploy
RAILS_ENV=production
LOGNAME=root
SHOPIFY_PULL_AND_STORE_DATABASE_USER=shopify_pull_and_store
LESSOPEN=| /usr/bin/lesspipe %s
SHOPIFY_PULL_AND_STORE_DATABASE_PASSWORD=XXXXXXXX
SUDO_GID=1000
LESSCLOSE=/usr/bin/lesspipe %s %s
_=/usr/bin/env
(0.6ms)  SELECT MAX("delayed_jobs"."priority") FROM "delayed_jobs" WHERE "delayed_jobs"."queue" = $1  [["queue", "RunReports"]]
[ActiveJob]    (0.1ms)  BEGIN
[ActiveJob]   SQL (0.9ms)  INSERT INTO "delayed_jobs" ("handler", "run_at", "queue", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  
[["handler", "--- !ruby/object:ActiveJob::QueueAdapters::DelayedJobAdapter::JobWrapper\njob_data:\n  job_class: RunReportsSplitMasterJob\n  job_id: 7dfd28bd-a47c-475d-9ccf-5a5d8ef756e7\n  provider_job_id: \n  queue_name: RunReports\n  priority: \n  arguments: []\n  executions: 0\n  locale: en\n"], ["run_at", "2019-01-07 18:02:57.355453"], ["queue", "RunReports"], ["created_at", "2019-01-07 18:02:57.355521"], ["updated_at", "2019-01-07 18:02:57.355521"]]
[ActiveJob]    (0.6ms)  COMMIT
[ActiveJob] Enqueued RunReportsSplitMasterJob (Job ID: 7dfd28bd-a47c-475d-9ccf-5a5d8ef756e7) to DelayedJob(RunReports)

但是,在我的 crontab 中使用 * * * * * /home/deploy/run_accounting,任务不会触发,我可以看到所需的环境变量没有加载,如下所示:

stuff from run_accounting bash
SHELL=/bin/sh
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env

为什么从终端运行该 bash 脚本时 bashrc 源,但从 crontab 运行相同命令时却没有?

【问题讨论】:

  • 您是否检查了在您的 shell 中设置但未在 cron 中设置的环境变量?
  • 是的,我在发帖后就真的想到了这一点。我在 crontab 中添加了/bin/bash -l -c 'echo $RAILS_ENV' >> /var/log/mazer-reports.log,它发布为空,这意味着该任务没有理由认为它应该在生产环境中运行。以为我解决了它,我尝试了以下命令:cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake RAILS_ENV=production run_split_accounting_after_close_master >> /var/log/mazer-reports.log 但是,这也不起作用。
  • 也许我应该考虑在命令本身中设置其他环境变量?

标签: ruby-on-rails cron ruby-on-rails-5 ubuntu-18.04 rake-task


【解决方案1】:

您可以尝试在 bundle exec 之前声明环境变量并使用您的项目 bin/bundle:

 0 * * * * cd /home/deploy/shopify_pull_and_store && RAILS_ENV=production bin/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log

2019-01-07 更新

尝试像这样设置到您的 .bashrc 的路由:

#!/bin/bash
source /home/deploy/.bashrc
echo "stuff from run_accounting bash" >> /var/log/mazer-reports.log
env >> /var/log/mazer-reports.log
cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log

或者像这样:

source ~deploy/.bashrc

【讨论】:

  • 是的,我刚刚发现我需要 RAILS_ENV,还需要我的数据库密码才能运行 rake 任务。由于我不想将我的数据库内容放在多个地方,我现在正在尝试获取 bashrc 来获取它们,但在我的最新更新中遇到了上述问题
  • 是的,做到了!应该考虑到波浪号路径是用户相关的事实
【解决方案2】:

根据您的 cmets,您似乎需要设置环境变量。我将推荐下一种方法:创建包含您的命令并获取您的 .bashrc 文件的 shell 脚本:

#!/bin/bash
. /home/deploy/.bashrc
# can be also
# . /home/deploy/.bash_profile
cd /home/deploy/shopify_pull_and_store && /home/deploy/.rbenv/shims/bundle exec rake run_split_accounting_after_close_master >> /var/log/mazer-reports.log

您也可以尝试使用.bashrc 来代替.bash_profile

然后在 cron 中运行这个 shell 脚本。不要忘记使这个脚本可执行。

附:也许您还需要添加/home/deploy/.bash_profile 一般来说,从用户的主文件夹(在这种情况下为root)添加这些文件是明智的。请检查 /etc/passwd 用户 root 的家在哪里

【讨论】:

  • 我刚刚在上面尝试过这个更新。如果你知道我在这里的最后一个问题的解决方案,我会给你赏金。
  • @ColinBrogan,会尽力帮助您,请参阅我的更新答案
猜你喜欢
  • 2010-10-09
  • 2012-11-15
  • 1970-01-01
  • 2014-12-05
  • 2011-06-22
  • 1970-01-01
  • 2011-07-27
  • 2010-09-23
  • 2013-02-18
相关资源
最近更新 更多