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