Rails 每当 gem 不使用 Ubuntu 和 Docker Compose 执行重复的 crontab 任务时

问题描述

我正在尝试使用适用于我的 Rails 应用程序的 Every gem 运行重复性任务。它在使用 Docker Compose 创建并托管在 Ubuntu 服务器上的 Docker 容器中运行。

我可以使用每当 gem 成功创建和更新 crontab 文件,但它似乎没有执行任务。

我想在应用运行时在后台重复执行的任务是:

rake searchkick:reindex CLASS=Property

我通常在使用 'docker-compose run web bash' 创建 web 运行容器后从终端成功执行此命令。这会使用 searchkick gem 重新索引我的 ElasticSearch 服务器。

相关版本如下:

- ruby 2.7.2p137
- rails (6.0.3.6)
- elasticsearch (6.8.3)
  - elasticsearch-api (= 6.8.3)
  - elasticsearch-transport (= 6.8.3)
- searchkick (4.4.4)
  - activemodel (>= 5)
  - elasticsearch (>= 6)
  - hashie
- whenever (1.0.0)
  - chronic (>= 0.6.3)

Cron 是使用 Dockerfile 安装的:

RUN apt-get update -qq && \
    apt-get install -y curl \
    build-essential \
    libpq-dev \
    cron \
    vim \
    nano \
    postgresql \
    postgresql-contrib \
    postgresql-client

Dockerfile 在容器创建时运行一个脚本:

copY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

脚本 (entrypoint.sh) 创建一个 crontab 文件

#!/bin/bash
set -e

# For development check if the gems as installed,if not,then uninstall them.
if ! [ bundle check ]; then
    bundle install
fi

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Yarn - Check Files.
yarn install --check-files

# Create empty crontab file.
crontab -l | { cat; echo ""; } | crontab -

# Update crontab file using whenever command.
bundle exec whenever --set 'environment=production' --update-crontab

# Run the command - runs any arguements passed into this entrypoint file.
exec "$@"

上面的 'bundle exec Every --set 'environment=production' --update-crontab' 命令根据下面的 schedule.rb 文件更新 crontab 文件

set :output,"log/cron_log.log"
env :PATH,ENV['PATH']

# Reindex Property records every 3 mins.
every 3.minutes do
    rake "searchkick:reindex CLASS=Property"
end

我也试过使用这个:

every 3.minutes do
    command "cd /myapp && rake searchkick:reindex CLASS=Property"
end

当我执行 'docker-compose run web bash' 以使用 rails 终端时,我在最后看到了这个响应:

no crontab for root
[write] crontab file updated

为了检查它是否正确创建,我使用“crontab -l”查看 rails 应用程序中的 crontab 文件,它显示

# Begin Whenever generated tasks for: /myapp/config/schedule.rb at: 2021-04-24 13:07:12 +0000
PATH=/usr/local/bundle/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57 * * * * /bin/bash -l -c 'cd /myapp && RAILS_ENV=production bundle exec rake searchkick:reindex CLASS=Property --silent >> log/cron_log.log 2>&1'

# End Whenever generated tasks for: /myapp/config/schedule.rb at: 2021-04-24 13:07:12 +0000

更新:使用cron service statuscron service start后,myApp/log/cron_log.log中的日志显示如下:

bundler: Failed to load command: rake (/usr/local/bin/rake)
Bundler::GemNotFound: Could not find rake-13.0.3 in any of the sources
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:170:in `specs'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:237:in `specs_for'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:226:in `requested_specs'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in deFinition_method'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'
bundler: Failed to load command: rake (/usr/local/bin/rake)
Bundler::GemNotFound: Could not find rake-13.0.3 in any of the sources
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:86:in `block in materialize'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `map!'
  /usr/local/lib/ruby/2.7.0/bundler/spec_set.rb:80:in `materialize'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:170:in `specs'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:237:in `specs_for'
  /usr/local/lib/ruby/2.7.0/bundler/deFinition.rb:226:in `requested_specs'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:101:in `block in deFinition_method'
  /usr/local/lib/ruby/2.7.0/bundler/runtime.rb:20:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler.rb:149:in `setup'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `block in <top (required)>'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:136:in `with_level'
  /usr/local/lib/ruby/2.7.0/bundler/ui/shell.rb:88:in `silence'
  /usr/local/lib/ruby/2.7.0/bundler/setup.rb:20:in `<top (required)>'

所以它似乎已经设置了 crontab 文件并且 cronjob 正在尝试运行但它没有找到 rake-13.0.3。我将检查这是否是 bundler gem 版本与 gemfile 中内容的问题。

感谢任何帮助。

解决方法

  1. 您可以在您的 cron 中运行 entrypoint.sh 来启动 cron 服务 (linux)
# Update crontab file using whenever command.
cron && bundle exec whenever --set 'environment=production' --update-crontab
  1. schedule 不知道 gems 路径,因此抛出 Bundler::GemNotFound 错误,要解决此问题,您可以通过在 schedule.rb 中设置所有 ENV 来避免丢失路径
set :output,"log/cron_log.log"
ENV.each { |k,v| env(k,v) }
# ...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...