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

Rails Whenever gem not executing repetitive crontab task with Ubuntu and Docker Compose

我正在尝试 运行 使用 Whenever gem 为我的 rails 应用程序执行一项重复性任务。它 运行 在 Docker 容器中使用 Docker Compose 创建并托管在 Ubuntu 服务器上。

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

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

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 使用 Docker 文件安装:

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

Docker文件运行是创建容器时的脚本:

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 arguments passed into this entrypoint file.
exec "$@"

上面的“bundle exec whenever --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。我将检查这是否是捆绑器 gem 版本与 gem 文件中的问题。

感谢任何帮助。

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