【Linux】【AWS Lambda】Cron形式の設定マニュアル

#### 背景

WEBサイトのクローリング、サーバーの死活監視データベースのバックアップ など、ものごとを定期的に行なう際に、スケジュール実行を可能とするCron形式について、Linuxでの設定方法・設定例と、AWS Lambdaにおける設定方法や設定例をまとめます。

先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが自分のメモとしても、こちらへまとめておきます。

#### 環境
- AWS EC2 (Amazon Linux 2)
- AWS Lambda
- Python 3.7.9　　　　※2020/12/10時点のAmazon Linux2でのデフォルト
- Django 3.1.3
- PostgreSQL 11.5　　※同上
- Nginx 1.12　　　　　※同上
- Gunicorn
- PuTTY 0.74


# 1. Linux における設定方法・設定例

### 1-1. 形式

```cron
<分> <時> <日> <月> <曜日> <コマンド>
```

### 1-2. パラメータ

- すべてのパラメータが必須です。
- タイムゾーンはUTC（協定世界時）のみで変更不可。<font color=#0000FF>**JST（日本標準時）として指定するには、UTCに対して「-9時間」とする（9時間を差し引く）必要があります。**</font>
- 分未満（秒単位）の指定はサポートされていません。

|No.|フィールド|値|ワイルドカード|
|:---:|:---|:---|:---:|
|1|分|0～59|「/」(スラッシュ)、「*」(アスタリスク)「-」(ハイフン)、「,」(カンマ)|
|2|時|0～23|「/」(スラッシュ)、「*」(アスタリスク)「-」(ハイフン)、「,」(カンマ)|
|3|日|1～31|「/」(スラッシュ)、「*」(アスタリスク)「-」(ハイフン)、「,」(カンマ)|
|4|月|1～12 または JAN～DEC|「/」(スラッシュ)、「*」(アスタリスク)「-」(ハイフン)、「,」(カンマ)|
|5|曜日|1～7 または SUN～SAT|「/」(スラッシュ)、「*」(アスタリスク)「-」(ハイフン)、「,」(カンマ)|
|6|コマンド|任意のコマンド|（なし）|


### 1-3. ワイルドカード

- 分未満（秒単位）の指定はサポートされていません。
- 実際に指定する際に、ワイルドカードに「」は記述不要です。

|No.|文字|定義|設定例|
|:---:|:---:|:---|:---|
|1|「/」(スラッシュ)|増分を指定する|<分>フィールドの0/10は、10分ごとに実行が発生する。5/15は、5・20・35・50分などを意味する。|
|2|「*」(アスタリスク)|すべての値を指定する|<日>フィールドで使用した場合、その月のすべての日が設定される。|
|3|「-」(ハイフン)|範囲を指定する|8-10 は、8・9および10が設定される。|
|4|「,」(カンマ)|追加の値を指定する|SUN・MON・TUEは、それぞれ日曜日・月曜日・火曜日が設定される。|


### 1-4. 設定例

```cron:crontab
# 毎日午前8時(UTC)に'backup.py'を実行する
 0 8 * * * source ~/venv_＜プロジェクト名＞/bin/activate; cd ~/venv_＜プロジェクト名＞/＜プロジェクト名＞; python manage.py backup > ~/cron.log 2>&1

# 毎日午後11時45分(UTC)にNginxをリロードする
 45 23 * * * sudo systemctl reload nginx.service

# 毎月1日の17時30分(UTC)にLet's EncryptのSSL証明書を更新する
 30 17 1 * * /home/＜スーパーユーザー＞/certbot/certbot-auto renew -q --renew-hook "/usr/bin/sysytemctl reload nginx.service"
# または
 30 17 1 * * /home/＜スーパーユーザー＞/certbot/certbot-auto renew -q --renew-hook "/usr/bin/sysytemctl reload nginx.service"

# 月曜～金曜(UTC)は5分ごとに固定IPへのpingを実行する
 0/5 * * MON-FRI * ping ＜Elastic IP＞
# または
 0/5 * * 2-6 * ping ＜Elastic IP＞
```


# 2. AWS Lambda における設定方法・設定例

### 2-1. 形式

```cron
cron <分> <時> <日> <月> <曜日> <年>
```

### 2-2. パラメータ

- すべてのパラメータが必須です。
- タイムゾーンはUTC（協定世界時）のみで変更不可。<font color=#0000FF>**JST（日本標準時）として指定するには、UTCに対して「-9時間」とする（9時間を差し引く）必要があります。**</font>
- 分未満（秒単位）の指定はサポートされていません。
- 実際に指定する際に、ワイルドカードに「」は記述不要です。

|No.|フィールド|値|ワイルドカード|
|:---:|:---|:---|:---:|
|1|分|0～59|「/」(スラッシュ)、「*」(アスタリスク)、「-」(ハイフン)、「,」(カンマ)|
|2|時|0～23|「W」、「L」、「/」(スラッシュ)、「?」(クエスチョンマーク)、「*」(アスタリスク)、「-(ハイフン)、「,」(カンマ)|
|3|日|1～31|「/」(スラッシュ)、「*」(アスタリスク)、「-」(ハイフン)、「,」(カンマ)|
|4|月|1～12 または JAN～DEC|「/」(スラッシュ)、「*」(アスタリスク)、「-」(ハイフン)、「,」(カンマ)|
|5|曜日|1～7 または SUN～SAT|「#」(シャープ)、「L」、「/」(スラッシュ)、「?」(クエスチョンマーク)、「*」(アスタリスク)、「-」(ハイフン)、「,」(カンマ)|
|6|年|1970～2199|「/」(スラッシュ)、「*」(アスタリスク)、「-」(ハイフン)、「,」(カンマ)|


### 2-3. ワイルドカード

- 分未満（秒単位）の指定はサポートされていません。
- 実際に指定する際に、ワイルドカードに「」は記述不要です。
- 日または週のどちらかの値は、「?」（クエスチョンマーク）である必要があります。

|No.|文字|定義|設定例|
|:---:|:---:|:---|:---|
|1|「/」(スラッシュ)|増分を指定する|<分>フィールドの0/10は、10分ごとに実行が発生する。5/15は、5・20・35・50分などを意味する。|
|2|「L」|『最後』を指定する|①<日>フィールドに指定された場合は、その月の末日が設定される。②<週>フィールドに指定された場合は、その週の最後の曜日（＝土曜日）が設定される。|
|3|「W」|平日を指定する|日付とともに指定した場合（例：3/Wなど）、その月の3日に最も近い平日が設定される。3日が土曜日の場合は、その前日の金曜日に実行される。3日が日曜日の場合は、その翌日の月曜日に実行される。|
|4|「#」(シャープ)|その月のn番目の日を指定する|4#3と指定した場合は、その月の第3水曜日が設定される。（※水曜日＝週7日のうち4番目の曜日）|
|5|「*」(アスタリスク)|すべての値を指定する|<日>フィールドで使用した場合、その月のすべての日が設定される。|
|6|「?」(クエスチョンマーク)|値を指定しない|指定した別の値とともに設定される。例として、ある特定の日付を指定したが、その日が何曜日であっても実行する場合。|
|7|「-」(ハイフン)|範囲を指定する|8-10 は、8・9および10が設定される。|
|8|「,」(カンマ)|追加の値を指定する|SUN・MON・TUEは、それぞれ日曜日・月曜日・火曜日が設定される。|


### 2-4. 設定例

```cron
# 毎日午前8時(UTC)に実行する
cron(0 8 * * ? *)

# 毎日午後12時45分(UTC)に実行する
cron(45 12 * * ? *)

# 月曜～金曜の午後5時30分(UTC)に実行する
cron(30 17 ? * MON-FRI *)
# または
cron(30 17 ? * 2-6 *)

# 月曜～金曜(UTC)は5分ごとに実行する
cron(0/5 * ? * MON-FRI *)
# または
cron(0/5 * ? * 2-6 *)
```


---
#### (参考)
AWS公式サイト(Lambda)：
[Rate または Cron を使用したスケジュール式](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/services-cloudwatchevents-expressions.html)
[ルールのスケジュール式](https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html)　(英語)

---
#### (編集後記)
ついつい、JSTとUTCとの時差（▲9時間）を忘れがちです。
月末の夜間に動かしたいにも関わらず、月初の昼間に動いてしまってアラートが挙がる！といったことの無いよう、設定する際には必ずこのマニュアルを見ることにしました。