Cronが動かないとは何ごとぞ！

### 背景

先日、Amazon EC2 (Amazon Linux 2) インスタンス（※1）起動時に自動でスクリプトを実行したく、cron を設定していたのですが、スクリプトが実行されない現象にぶつかりました。その際の対処をここにメモとして残しておきます。

（※1）インスタンスタイプ：**g4dn.xlarge**　...機械学習などに用いるGPUを利用できるインスタンスタイプです

　

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

### 環境

(本番)
- AWS EC2 (Amazon Linux 2)
- Python 3.7.9　　　　※2021/02/21時点のAmazon Linux2でのデフォルト
- Putty 0.74- AWS EC2 (Amazon Linux 2)


# 0. Cron とは

[IT用語辞典 e-Words ―cronの項目](https://e-words.jp/w/cron.html) より引用：

> cronとは、多くのUNIX系OSで標準的に利用される常駐プログラム（デーモン）の一種で、利用者の設定したスケジュールに従って指定されたプログラムを定期的に起動してくれるもの。
> 利用者はcrontab（“cron table”の略）コマンドで実行したいプログラムやコマンド、シェルスクリプトなどと実行日時を指定すると、同名のテキストファイル（crontabファイル）に設定が保存される。システムに常駐するデーモンの一つであるcrond（“cron daemon”の略）がcrontabファイルに書かれたスケジュールに従って、決まった日時に指定されたプログラムを実行する。




# 1. 現象 

cron で設定したスクリプトが、EC2 インスタンス起動時に起動しない。


# 2. 原因

まず考えられたのは、cron コマンドの設定ミス。
コマンドは、単純にリブート時にとあるスクリプトを実行するというもの。
しかしながら、何度見直してもコマンドの記述に間違いは見当たりません。

```cron:crontab
@reboot /home/(username)/app/on_start.sh
```

　

実行されるスクリプトの内容も、1つのpythonファイルを実行するだけの簡単なものです。
こちらもディレクトリの設定や処理内容に間違いはありませんでした。

```bash:on_start.sh
#!/bin/bash

cd `dirname $0`

SHELL=/bin/bash
# パスを通す
source /home/(username)/.bashrc
# 好きなPython環境を設定
source activate tensorflow2_latest_serving
# 起動から45分後にインスタンスを停止する
sudo shutdown +45

cd /home/(username)/app
python3 app.py
```

# 3. 対処

いろいろと調べていた中で末尾に記載した参考記事（特に [@nagimaruxxx](https://qiita.com/nagimaruxxx) 様の記事）を見付け、それに沿って以下を実行しました。

## a) crond ステータス確認

```Terminal
service crond status    # ステータス確認
service crond start     # 起動
```

⇒ crond は稼働していました。

　

※以降 b)～d) はルート権限で実行が必要。「sudo su -」コマンドでルート権限に移行する。
　ユーザー権限に戻る際は、「exit」を入力して[enter]キー押下。


## b) run level 確認

```Terminal
chkconfig --list crond
crond           0:off   1:off   2:on    3:on    4:on    5:on    6:off
```


　
⇒ 私の環境では、何故か上記コマンドを受け付けずに確認ができなかったため、確認なしで、直接に下記コマンドを実行しました。

```Terminal
chkconfig --level 2345 crond on    # run level 2,3,4,5 を on とする
```


## c) ファイルの実行権限

```Terminal
ls -l on_start.sh
-rw-r--r-- 1 dev dev 1  2月 25 10:51 2021 on_start.sh

chmod +x on_start.sh    # 権限を付与

ls -l on_start.sh
-rwxrwxr-x 1 dev dev 1  2月 25 10:52 2021 on_start.sh
```

⇒ 変更前は「644」でしたが、これに `+x` して「775」へ。
　一番の原因は、この実行権限だった模様。


## d) noanacron の導入

デフォルトで anacron という cron がインストールされていましたが、使いづらい点があり、私も [@nagimaruxxx](https://qiita.com/nagimaruxxx) 様の記事を参考に **noanacron** をインストールしました。

```Terminal
yum -y install cronie-noanacron
yum remove cronie-anacron
```


# 4. 結果

cronにより、EC2 インスタンス起動時（再起動時）に指定したスクリプト（上述の on_start.sh）が起動されるようになりました！
また、インスタンス起動から指定通り45分後にインスタンスが停止されることも確認できました。

めでたしめでたし。



---
### 参考

- [cronがどうやっても動かない時に考えられる原因とその対処法](https://qiita.com/nagimaruxxx/items/b7308644b5d2c9efbeea)　([@nagimaruxxx](https://qiita.com/nagimaruxxx) 様)

- [cron が実行されない　―ナクナイ 勉強用の備忘録](http://tamulapin.hatenablog.com/entry/2015/01/16/181207)

- [cron の設定ガイド](https://www.express.nec.co.jp/linux/distributions/knowledge/system/crond.html)


- [【Linux】【AWS Lambda】Cron形式の設定マニュアル](https://qiita.com/_whitecat_22/items/20987f265b97ec3fbacf)

---
#### (編集後記)

まさか cron が動かないとは思わず（まさしくタイトル通り「**Cronが動かないとは何ごとぞ！**」と思っていたため）、参考記事に辿り着くまで、さらには、ファイルの実行権限が原因であることを突き止めるまでに、多くの時間を費やしてしまいました。

私自身は通常、スクリプトファイルやPythonファイルを、Puttyからのコマンドや、WinSCPでローカルからEC2へコピーするなどしているのですが、その際に実行権限を確認することをあまり行なっておりませんでした。
今後は、追加・変更したファイルやディレクトリの実行権限を必ず確認するよう、手元のチェック項目へ追記しました。

皆様はこれを反面教師として考えていただけたら幸いです。

最後までお付き合いいただきまして、ありがとうございました。