Dokkuでcronが動かない件の対応

Railsタスクをcronで動かそうと思い、設定を進めた。Dokkuのcron設定マニュアルをじっくり読まずにフィーリングで設定を進めた結果、cronが動かない状況に遭遇。

現象1 cronを同時に複数動かす(未検証)

$ dokku run <app> <command> を実行すると、ターミナルで直接実行する場合には動くが、cronを複数同時に実行すると動かなくなる(っぽい)。
デフォルトは同時に動かせないため、 --rm 引数を使うことで並走実行が可能(と思われる。未検証)。

現象2 sudoがなんたらと怒られる

cron実行ログに sudo: no tty present and no askpass program specified dokku が出力される。
dokkuユーザーのcrontab以外で実行しているため、このエラーが出力される(たとえばubuntuユーザーのcrontabで実行する、など)。

DokkuでRailsタスクを実行するコマンド

Railsタスクは $ dokku --rm <app> <railsタスクコマンド> で実行できる。
Railsタスクコマンド一覧は $ rails -T で確認できる。
自分の場合は rails bot_comments:first_waves というRailsタスクコマンドを作成した。

Dokkuのcron設定方法

Dokku公式サイト – One-off Processes and Cron の最下部にcronのサンプルファイルがあるため、まずそれをコピペして、cronの実行コマンド箇所のみ削除する。

以下、自分の設定例。cronをRailsタスクでボットを動かすように記述。

ubuntu$ sudo cron -u dokku -e

# server cron jobs
PATH=/usr/local/bin:/usr/bin:/bin
SHELL=/bin/bash

# m   h   dom mon dow   username command
# *   *   *   *   *     dokku    command to be executed
# -   -   -   -   -
# |   |   |   |   |
# |   |   |   |   +----- day of week (0 - 6) (Sunday=0)
# |   |   |   +------- month (1 - 12)
# |   |   +--------- day of month (1 - 31)
# |   +----------- hour (0 - 23)
# +----------- min (0 - 59)

# Reference: http://dokku.viewdocs.io/dokku/deployment/one-off-processes/

### Update below
### HIGH TRAFFIC TIME IS B/W xx:xx - xx:xx AND xx:xx - xx:xx
### RUN YOUR TASKS FROM xx:xx - xx:xx
### KEEP SORTED IN TIME ORDER

### PLACE ALL CRON TASKS BELOW

# DO NOT REMOVE. Default cron job.
@daily /var/lib/dokku/plugins/available/letsencrypt/cron-job

# gnote app: run gnote bot
*/5 * * * * dokku --rm run gnote rails bot_comments:first_waves > /var/log/cron-ubuntu.log 2>&1
0 * * * *   dokku --rm run gnote rails bot_comments:second_waves > /var/log/cron-ubuntu.log 2>&1
*/10 *  * * *   dokku --rm run gnote rails bot_likes:first_waves > /var/log/cron-ubuntu.log 2>&1

### PLACE ALL CRON TASKS ABOVE, DO NOT REMOVE THE WHITESPACE AFTER THIS LINE

cronが動いたか確認する。「CMD」の箇所でコマンドが実行されたことがわかる。

ubuntu$ tail /var/log/cron.log

Aug 27 23:38:01 cron[29535]: (ubuntu) RELOAD (crontabs/ubuntu)
Aug 27 23:45:01 CRON[13571]: (root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)
Aug 27 23:47:05 crontab[13609]: (ubuntu) BEGIN EDIT (ubuntu)
Aug 27 23:47:09 crontab[13609]: (ubuntu) END EDIT (ubuntu)
Aug 27 23:47:11 crontab[13620]: (ubuntu) LIST (ubuntu)
Aug 27 23:48:06 crontab[13632]: (root) BEGIN EDIT (dokku)
Aug 27 23:49:08 crontab[13632]: (root) REPLACE (dokku)
Aug 27 23:49:08 crontab[13632]: (root) END EDIT (dokku)
Aug 27 23:50:01 cron[29535]: (dokku) RELOAD (crontabs/dokku)
Aug 27 23:50:01 CRON[13672]: (dokku) CMD (dokku --rm run gnote rails bot_comments:first_waves >> /var/log/cron-ubuntu.log 2>&1)

今回は /var/log/cron-ubuntu.log に最新ログのみ出力するようにしたため、状況を確認する。Railsタスクの実行結果がSQL出力されているため、正常に動いていることが確認できた。

ubuntu$ tail /var/log/cron-ubuntu.log

no matching process entry found
D, [2019-08-27T14:50:10.243125 #11] DEBUG -- :   Message Load (3.4ms)  SELECT "messages".* FROM "messages" WHERE "messages"."created_at" BETWEEN $1 AND $2 AND (length(body) > 8) ORDER BY "messages"."id" ASC  [["created_at", "2019-08-27 13:50:10.224354"], ["created_at", "2019-08-27 14:50:10.224503"]]
ubuntu@ik1-401-32643:~$ tail /var/log/cron-ubuntu.log
D, [2019-08-27T15:10:11.459989 #11] DEBUG -- :   Message Load (1.4ms)  SELECT "messages".* FROM "messages" WHERE "messages"."created_at" BETWEEN $1 AND $2 AND (length(body) > 8) ORDER BY "messages"."id" ASC  [["created_at", "2019-08-27 14:10:11.450627"], ["created_at", "2019-08-27 15:10:11.450781"]]
D, [2019-08-27T15:10:11.542722 #11] DEBUG -- :   Comment Create Many Without Validations Or Callbacks (7.4ms)  INSERT INTO "comments" ("id","body","author_hash_ip","created_at","updated_at","message_id","user_id") VALUES (nextval('public.comments_id_seq'),'癒やされた',NULL,'2019-08-27 15:10:11.527416','2019-08-27 15:10:11.527416',20,1),(nextval('public.comments_id_seq'),'ナイス',NULL,'2019-08-27 15:10:11.527416','2019-08-27 15:10:11.527416',21,1) RETURNING "id"
0m  SELECT  "messages".* FROM "messages" WHERE "messages"."id" = $1 LIMIT $2  [["id", 21], ["LIMIT", 1]]
D, [2019-08-27T15:10:11.556827 #12] DEBUG -- :   Message Update All (1.1ms)  UPDATE "messages" SET "likes_count" = COALESCE("likes_count", 0) + 3 WHERE "messages"."id" = $1  [["id", 21]]

参考サイト

cron設定を進める場合は、このページを最後までじっくり読む。

メモ

ubuntuユーザーに登録したcronのエラーメッセージ(メール)を確認する場合

You have mail.

ubuntu$ less /var/mail/ubuntu