How to enable linux swap on boot?

土日に突然メモリ空き容量アラートがたくさん来たのでmackerelみてみたら、swap領域が消えてた!

journal logの該当の時間帯をjournalctl --since="2016-10-02 02:00:00" --until="2016-10-02 02:30:00"で見てみると、システムがrebootされていた。

10月 02 02:22:06 ponpokopon.me systemd-logind[446]: Power key pressed.  
10月 02 02:22:06 ponpokopon.me systemd-logind[446]: Powering Off...  
10月 02 02:22:06 ponpokopon.me systemd-logind[446]: System is powering down.  

サーバはdigitaloceanで動いていて、そういえばメンテナンスのためにリブートするよってメールが来ていたのを思い出して漁ってみたらずばりそうであった(JSTだと2016-10-02 01:00 ~ 2016-10-02 07:00)。

メールを確認したときにはまあ影響ないでしょって思ってたけどswapのことをすっかり忘れていた。digitaloceanはawsのec2と同じように基本単一パーティション(/のみ)なので、swap領域は無い。そこで、以下のようにswapファイルを作成しそのファイルをswapとして使うことでswapを確保していた。

sudo fallocate -l 2G /swapfile  
sudo chmod 600 /swapfile  
sudo mkswap /swapfile  
sudo swapon /swapfile  

fallocateはファイルに割り当てられるディスクスペースを操作するコマンドで、ddコマンドで0埋めするのと違ってディスクへの書き込みがないので、ドチャクソ早い。ddは指定したサイズ分の実データを用意するが、fallocateは指定したサイズの領域を確保するみたいなイメージ(あってるかな?)。

mkswapとswaponはその名の通り指定したデバイス・ファイルをswap化するのと、有効化するコマンド。


さて、ここでなぜ再起動するとswapが消えてしまうか今更ながら気になった。そりゃfstabに書いてないからだよと思うけど、fstabってマウントしたいディスク(パーティション)を書くイメージが強い。manにもファイルシステムをマウントするものって書いてあるし…。

The file fstab contains descriptive information about the filesystems the system can mount. fstab is only read by programs, and not written; it is the duty of the system administrator to properly create and maintain this file. The order of records in fstab is important because fsck(8), mount(8), and umount(8) sequentially iterate through fstab doing their thing.

fstab(5) - Linux manual page

じゃあswapはマウントされるものなのかと思ったけどmountコマンドのmanページ見てもswapをマウントするようなオプションはなさそう。てことはswaponコマンドがswapデバイス、ファイルをマウント(?)する特別なコマンドなのかな?ということはfstabとswaponは関係がある?

ということでswaponのmanを見てみると、起動クリプトによって全てのswapデバイスに対して行われると書いてある。

Calls to swapon normally occur in the system boot scripts making all swap devices available, so that the paging and swapping activity is interleaved across several devices and files.

swapon(8) - Linux manual page

起動スクリプトはsystemdとかsysvinitとかのアレだよね。systemdはまだあんまり慣れてないので、centos6のinitスクリプトを探索してみる。適当にgrepしてみると、何やらそれっぽいスクリプトありけり。

$ grep -r swapon /etc/rc*
/etc/rc.d/rc.sysinit:action $"Enabling /etc/fstab swaps: " swapon -a -e
/etc/rc.d/rc.sysinit:                   echo $curswap | grep -qw "$majmin" || action $"Enabling local swap partitions: " swapon $partition
/etc/rc.sysinit:action $"Enabling /etc/fstab swaps: " swapon -a -e
/etc/rc.sysinit:                        echo $curswap | grep -qw "$majmin" || action $"Enabling local swap partitions: " swapon $partition

/etc/rc.d/rc.sysinitといえばカーネルが最初に実行する/sbin/initが実行された後に起動されるスクリプトなので、まさにこれが「起動クリプトによって全てのswapデバイスに対して行われる」を含む部分なのではないかな?

642行目あたりからswapの設定が始まる箇所があった。swapon -a -eが実行されてる。

# Start up swapping.
update_boot_stage RCswap  
action $"Enabling /etc/fstab swaps: " swapon -a -e  
if [ "$AUTOSWAP" = "yes" ]; then  
        curswap=$(awk '/^\/dev/ { print $1 }' /proc/swaps | while read x; do get_numeric_dev dec $x ; echo -n " "; done)
        swappartitions=$(blkid -t TYPE=swap -o device)
        if [ x"$swappartitions" != x ]; then
                for partition in $swappartitions ; do
                        [ ! -e $partition ] && continue
                        majmin=$(get_numeric_dev dec $partition)
                        echo $curswap | grep -qw "$majmin" || action $"Enabling local swap partitions: " swapon $partition
                done
        fi
fi  

-a, -eオプションてなんだろう。manを見ると、

-a, --all All devices marked as ‘‘swap’’ in /etc/fstab are made available, except for those with the ‘‘noauto’’ option. Devices that are already being used as swap are silently skipped.

-e, --ifexists Silently skip devices that do not exist.

とある。-aは/etc/fstabnoautoオプションが有るものを除く全てのswapマークが有るデバイスに対してswaponするもので、-eがfstabに書いてはいるけど認識されてないデバイスがあった場合華麗にスルーするオプション。なるほど…!こいつが!!


ほかにもいろいろ条件分岐したりゴニョゴニョしてるけど、満足したのでかんべんしてやろう。

ハイパー横道にそれたけど要するにスワップを永続化するには/etc/fstab/swapfile swap swap sw 0 0って書けばOK。

rebootしてみると起動スクリプトによってswap onされたのが確認できる。

$ sudo dmesg| grep swap
[    3.763404] Adding 2097148k swap on /swapfile.  Priority:-1 extents:11 across:3178492k FS

まとめ

  • 起動時のswapの自動有効化は/etc/rc.d/rc.sysinitによってfstabにswapとして書かれているデバイス全てに対しswaponコマンドが実行されることによって実現されている
  • メンテナンスの時間はカレンダーに入れよう!

参考リンク