yum-cronでメール通知入り日次updateまたは、週次updateする

記事を書いてから１年半が経過し、その後運用で回るようになったので、記事をアップデートして週次アップデートを加えました。

## 動機

* yum update手間
* yum updateはリポジトリ先を追加していくと、たまにサーバ再起動時に起動しなくなる事があるため、自動怖いなぁ
* でも自動でできるyum-cronあるなぁ。試したい。試す。
* yum-cronで週次アップデートしたいなぁ。対応できた。

## コマンド

### yum-cronインストール
```
yum install yum-cron -y
```

### メールで通知設定

```
vi /etc/yum/yum-cron.conf

[commands]
# Whether a message should be emitted when updates are available,
# were downloaded, or applied.
# 更新が利用可能なときにメッセージを発行するかどうか、
# ダウンロードまたは適用されました。
update_messages = yes

# Whether updates should be downloaded when they are available.
# 更新が利用可能になったときにダウンロードするかどうか。
download_updates = yes

# Whether updates should be applied when they are available.  Note
# that download_updates must also be yes for the update to be applied.
# 更新が利用可能なときに適用する必要があるかどうか。 注意
# アップデートを適用するには、download_updatesもyesでなければなりません。
#apply_updates = no
apply_updates = yes

# Maximum amout of time to randomly sleep, in minutes.  The program
# will sleep for a random amount of time between 0 and random_sleep
# minutes before running.  This is useful for e.g. staggering the
# times that multiple systems will access update servers.  If
# random_sleep is 0 or negative, the program will run immediately.
# 6*60 = 360
# ランダムにスリープする最大時間（分単位）。 プログラム
# 0からrandom_sleepの間のランダムな時間スリープします
# 実行の数分前。 これは、たとえば よろめく
# 複数のシステムが更新サーバーにアクセスする回数。 もし
# random_sleepが0または負の場合、プログラムはすぐに実行されます。
# 6 * 60 = 360
random_sleep = 360

[emitters]
# メールで通知設定
#emit_via = stdio
emit_via = email

[email]
# メールで通知設定
#email_from = root@localhost
email_from = <通知したいメールアドレス>

[base]
# This section overrides yum.conf
# このセクションはyum.confをオーバーライドします(!?)

# 以下は追記したもの
# 個別のリポジトリーの有効化または無効化
#reposdir=/etc/yum-cron.repos.d

# その他不明な設定は、Google翻訳で翻訳すれば、だいたい設定の意味はつかめる
```

### 自動起動・起動・起動状態確認 

```
systemctl enable yum-cron
systemctl restart yum-cron
systemctl stats yum-cron
```

### yum-cronの時だけ、epelなどの追加リポジトリを有効化する

`/etc/yum/yum-cron.conf`の`[base]`以下は英語コメントにある通り、設定を書くと `yum.conf` を内容を上書きしてくれます。
そのため、`reposdir`を `yum.conf`とは別のディレクトリ指定し、`yum.conf` とは異なる設定にしてあげれば、例えばepelリポジトリを使っていて、
通常はepelリポジトリを無効にしている場合に、yum-cronの時だけ有効にする、といった設定が可能です。

```
vi /etc/yum/yum-cron.conf

[base]
# This section overrides yum.conf
# このセクションはyum.confをオーバーライドします(!?)

# 以下は追記したもの
# 個別のリポジトリーの有効化または無効化
reposdir=/etc/yum-cron.repos.d
```

```
// --- epelのyum updateが必要な場合
// yumリポジトリディレクトリをコピー
cp -r /etc/yum.repos.d /etc/yum-cron.repos.d

// /etc/yum-cron.repos.dディレクトリのepel.repoの6行目を置換して有効化
sed -i -e "6 s/enabled=0/enabled=1/g" /etc/yum-cron.repos.d/epel.repo

// 置換後にdiffコマンドで確認
diff /etc/yum.repos.d/epel.repo /etc/yum-cron.repos.d/epel.repo
```

#### リポジトリ一覧確認

epelなどの追加リポジトリを使っているかどうかは、下記コマンドで確認できます。

```
yum repolist all
```

### 自動再起動

yum-cronはサーバの再起動する機能を持っていません。
そのためサーバ再起動は、yum-cron以外で対応する事を検討します。

今回はcrontabに時間指定で対応しました。
再起動を時間指定したため、再起動前にyum updateが終わって欲しいので、yum-cronの時間指定も併せて対応しました。

#### 再起動Shell作成と配置

再起動時にメールをなげてほしかったので、Shellを作成しました。
（メール通知不要であればこのShellは不要で、再起動コマンド`/sbin/shutdown -r now`を直接crontabに書けば事足りると思います）

```
// 再起動時のメール通知のため、mailxをインストールする
yum install mailx -y
```

`ZZ_reboot_and_send_mail.sh`を配置します。
ここでは `/srv/scripts/yum-cron/bin/` に配置します。

```
mkdir -p /srv/scripts/yum-cron/bin/
vi /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh
```

```shell:ZZ_reboot_and_send_mail.sh
#!/bin/bash

title_server="[`hostname` ここはサーバ名に変更する]"

message=$title_server"\n\ncronにより1分後に自動再起動します。"
message=$message"\n\n"

# reboot & send mail
message=$message"/sbin/shutdown -r +1\n"
# 1分後reboot & 標準エラーを標準出力にリダイレクト & 結果を変数にセット
#   ※１：メール通知は、`/sbin/shutdown -r now`だとメール飛ばないため、1分後に再起動にしました。
#   ※２：`/sbin/shutdown -r +1`(１分後再起動)は正常でも、標準エラーで「Shutdown scheduled for 月 2020-08-24 04:01:01 JST, use 'shutdown -c' to cancel.」が表示されるため、標準エラーを標準出力にリダイレクトしました。
message_shutdown=`/sbin/shutdown -r +1 2>&1`
# 文字連結
message=$message$message_shutdown
# mail
echo -e $message | mail -s "${title_server} reboot after 1 min!" -r from-mail@example.com to-mail@example.com
```

```
// 実行権限をつけます。
chmod 775 /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh
```

#### yum-cron再設定

yum-cronは通常毎日実行されます。
実体は`/etc/cron.daily/0yum-daily.cron` で中身はShellです。

```shell:0yum-daily.cron
#!/bin/bash

# Only run if this flag is set. The flag is created by the yum-cron init
# script when the service is started -- this allows one to use chkconfig and
# the standard "service stop|start" commands to enable or disable yum-cron.
if [[ ! -f /var/lock/subsys/yum-cron ]]; then
  exit 0
fi

# Action!
exec /usr/sbin/yum-cron
```

日次アップデートではなく週次や月次でアップデートしたい場合は、このShellと設定ファイルをコピーして指定する事で
対応する事ができます。

##### /etc/yum/yum-cron.confの無効化

`/etc/yum/yum-cron.conf`は、`/etc/cron.daily/0yum-daily.cron`で動作するため、無効化します。
sedコマンドで設定ファイルを置換して全offにします。

```
// yum-cronの毎日update設定は全offにする
sed -i"."`date +\%Y\%m\%d` "s/^update_messages = yes$/update_messages = no/g" /etc/yum/yum-cron.conf
sed -i "s/^download_updates = yes$/download_updates = no/g" /etc/yum/yum-cron.conf
sed -i "s/^apply_updates = yes$/apply_updates = no/g" /etc/yum/yum-cron.conf
less /etc/yum/yum-cron.conf
```

##### 日次時間指定のyum-cronの設定

```
cp /etc/cron.daily/0yum-daily.cron /srv/scripts/yum-cron/bin/0yum-daily.cron
cp /etc/yum/yum-cron.conf /srv/scripts/yum-cron/conf/yum-cron-daily.conf
vi /srv/scripts/yum-cron/bin/0yum-daily.cron
```

```shell:0yum-weekly.cron
#!/bin/bash

# Only run if this flag is set. The flag is created by the yum-cron init
# script when the service is started -- this allows one to use chkconfig and
# the standard "service stop|start" commands to enable or disable yum-cron.
if [[ ! -f /var/lock/subsys/yum-cron ]]; then
  exit 0
fi

# 下記追加
yum clean all

# Action!
# 下記変更
#exec /usr/sbin/yum-cron
exec /usr/sbin/yum-cron /srv/scripts/yum-cron/conf/yum-cron-daily.conf
```

```
// 実行権限をつけます。
chmod 775 /srv/scripts/yum-cron/bin/0yum-daily.cron

// 日次時間指定yum updateを設定する。設定内容はお好みで。
vi /srv/scripts/yum-cron/conf/yum-cron-daily.conf
```

```conf:yum-cron-weekly.conf
[commands]
update_cmd = default
update_messages = yes
download_updates = yes
apply_updates = yes
random_sleep = 0

[emitters]
system_name = None

#emit_via = stdio
emit_via = email

output_width = 80

[email]
email_from = from-mail@example.com

#email_to = root
email_to = to-mail@example.com

email_host = localhost

[groups]
group_list = None
group_package_types = mandatory, default

[base]
debuglevel = -2
mdpolicy = group:main

# 個別のリポジトリーの有効化または無効化
reposdir=/etc/yum-cron.repos.d
```


#### crontabに設定

```
# 毎日2時にyum update, 4時にrebootを、crontabの最終行に挿入
sed -i -e '$ a 00  2  *  *  * root /bin/bash /srv/scripts/yum-cron/bin/0yum-daily.cron > /dev/null' /etc/crontab
sed -i -e '$ a 00  4  *  *  * root /bin/bash /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh > /dev/null' /etc/crontab

// 確認
cat /etc/crontab
```

```conf:crontab
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
 00  2  *  *  * root /bin/bash /srv/scripts/yum-cron/bin/0yum-daily.cron > /dev/null
 00  4  *  *  * root /bin/bash /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh > /dev/null
```



### 週次でyum-cronをする場合


```
cp /etc/cron.daily/0yum-daily.cron /srv/scripts/yum-cron/bin/0yum-weekly.cron
cp /etc/yum/yum-cron.conf /srv/scripts/yum-cron/conf/yum-cron-weekly.conf
vi /srv/scripts/yum-cron/bin/0yum-weekly.cron
```

```shell:0yum-weekly.cron
#!/bin/bash

# Only run if this flag is set. The flag is created by the yum-cron init
# script when the service is started -- this allows one to use chkconfig and
# the standard "service stop|start" commands to enable or disable yum-cron.
if [[ ! -f /var/lock/subsys/yum-cron ]]; then
  exit 0
fi

# 下記追加
yum clean all

# Action!
# 下記変更
#exec /usr/sbin/yum-cron
exec /usr/sbin/yum-cron /srv/scripts/yum-cron/conf/yum-cron-weekly.conf
```

```
// 実行権限をつけます。
chmod 775 /srv/scripts/yum-cron/bin/0yum-weekly.cron

// 週次yum updateを設定する。設定内容はお好みで。
vi /srv/scripts/yum-cron/conf/yum-cron-weekly.conf
```

```conf:yum-cron-weekly.conf
[commands]
update_cmd = default
update_messages = yes
download_updates = yes
apply_updates = yes
random_sleep = 0

[emitters]
system_name = None

#emit_via = stdio
emit_via = email

output_width = 80

[email]
email_from = from-mail@example.com

#email_to = root
email_to = to-mail@example.com

email_host = localhost

[groups]
group_list = None
group_package_types = mandatory, default

[base]
debuglevel = -2
mdpolicy = group:main

# 個別のリポジトリーの有効化または無効化
reposdir=/etc/yum-cron.repos.d
```


#### crontabに設定

```
# 毎週日曜2時にyum update, 4時にrebootを、crontabの最終行に挿入
sed -i -e '$ a 00  2  *  *  2 root /bin/bash /srv/scripts/yum-cron/bin/0yum-weekly.cron > /dev/null' /etc/crontab
sed -i -e '$ a 00  4  *  *  2 root /bin/bash /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh > /dev/null' /etc/crontab

// 確認
cat /etc/crontab
```

```conf:crontab
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
 00  2  *  *  2 root /bin/bash /srv/scripts/yum-cron/bin/0yum-weekly.cron > /dev/null
 00  4  *  *  2 root /bin/bash /srv/scripts/yum-cron/bin/ZZ_reboot_and_send_mail.sh > /dev/null
```

以上

## 参考リンク

* [yum-cronを使おう - Qiita](https://qiita.com/shimano_equipped/items/ff65ace63399435107f0)
    * 
* [yum を使って システムアップデートを行う (自動化も) | レンタルサーバー・自宅サーバー設定・構築のヒント](https://server-setting.info/centos/firststep.html#firststep_5)
    * 設定の詳細な記載あり
* [9.7. yum-cron を使用したパッケージデータベースの自動更新および更新のダウンロード - Red Hat Enterprise Linux 7公式](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-yum#sec-Automatically_refreshing_the_package_database_and_download_updates)