mattintosh note

どこかのエンジニアモドキの備忘録

Armbianで/var/logの割り当てサイズを変更する

自宅サーバ用として ROCK64 というシングルボードコンピュータを使用しています。無線は搭載されていませんが、GbE で 4 GB RAM、USB 3.0 搭載で秋月電子で 5,000 円前後で購入することが出来ます(Raspberry Pi 4 が出るまでは旧 Raspberry Pi を大きく突き放すスペックでした)。

使用可能な OS は何種類かありますが、現在は Armbian で運用しています。この Armbian は名前の通り Debian ベースの ARM マシン向け OS です。シングルボードコンピュータでは microSD が使われることが多いですが耐久性に難があります。そこで、Armbian では /var/log に ZRAM が使われています。

ZRAM の状態は zramctl で確認できますが、デフォルトでは /var/log への割り当ては 50 MB と、運用によってはかなり少ない割り当てになっています。

$ sudo zramctl
NAME       ALGORITHM DISKSIZE  DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram1 lzo             1G 29.3M  7.7M  8.5M       4 [SWAP]
/dev/zram0 lz4hc          50M  2.8M  655K  1.1M       4 /var/log

この設定を変更するために設定ファイルを探したりすることになったのでメモを残しておきます。

/etc/default/armbian-ramlog が設定ファイルで、SIZE= に指定した容量が /var/log に割り当てられます。

$ cat /etc/default/armbian-ramlog
# configuration values for the armbian-ram-logging service
#
# enable the armbian-ram-logging service?
ENABLED=true
#
# size of the tmpfs mount -- please keep in mind to adjust /etc/default/armbian-zram-config too when increasing
SIZE=50M
#
# use rsync instead of cp -r
# requires rsync installed, may provide better performance
# due to copying only new and changed files
USE_RSYNC=true

設定を変更したら再起動します。

システム稼働中は armbian-ramlog というサービスが稼働しています。なお、このサービスを再起動しても割当量の変更は行われません。

$ systemctl status armbian-ramlog
● armbian-ramlog.service - Armbian memory supported logging
   Loaded: loaded (/lib/systemd/system/armbian-ramlog.service; enabled; vendor preset: enabled)
   Active: active (exited) since Sun 2020-04-19 01:13:48 JST; 5s ago
  Process: 6108 ExecStart=/usr/lib/armbian/armbian-ramlog start (code=exited, status=0/SUCCESS)
 Main PID: 6108 (code=exited, status=0/SUCCESS)

Apr 19 01:13:45 rock64 systemd[1]: Starting Armbian memory supported logging...
Apr 19 01:13:45 rock64 armbian-ramlog[6108]: Mounting /dev/zram0 as /var/log/
Apr 19 01:13:45 rock64 armbian-ramlog[6108]: Sun 19 Apr 2020 01:13:45 AM JST: Loading logs from storage
Apr 19 01:13:46 rock64 armbian-ramlog[6108]: sending incremental file list
Apr 19 01:13:47 rock64 armbian-ramlog[6108]: sent 1,514 bytes  received 28 bytes  1,028.00 bytes/sec
Apr 19 01:13:47 rock64 armbian-ramlog[6108]: total size is 1,522,657  speedup is 987.46
Apr 19 01:13:48 rock64 systemd[1]: Started Armbian memory supported logging.

ブロックデバイスの情報は /sys/block 以下に格納されています。

$ ll /sys/block/zram0/
total 0
drwxr-xr-x  7 root root    0 Apr 18 19:29 ./
drwxr-xr-x 14 root root    0 Apr 18 19:29 ../
-r--r--r--  1 root root 4.0K Apr 19 01:20 alignment_offset
lrwxrwxrwx  1 root root    0 Apr 19 01:20 bdi -> ../../bdi/252:0/
-r--r--r--  1 root root 4.0K Apr 19 01:20 capability
--w-------  1 root root 4.0K Apr 19 01:20 compact
-rw-r--r--  1 root root 4.0K Apr 18 19:29 comp_algorithm
-r--r--r--  1 root root 4.0K Apr 19 01:20 debug_stat
-r--r--r--  1 root root 4.0K Apr 18 19:29 dev
-r--r--r--  1 root root 4.0K Apr 19 01:20 discard_alignment
-rw-r--r--  1 root root 4.0K Apr 19 01:21 disksize
-r--r--r--  1 root root 4.0K Apr 19 01:20 ext_range
drwxr-xr-x  2 root root    0 Apr 18 19:29 holders/
-r--r--r--  1 root root 4.0K Apr 19 01:20 inflight
-r--r--r--  1 root root 4.0K Apr 19 01:20 initstate
-r--r--r--  1 root root 4.0K Apr 19 01:20 io_stat
-rw-r--r--  1 root root 4.0K Apr 18 19:29 max_comp_streams
--w-------  1 root root 4.0K Apr 19 01:20 mem_limit
--w-------  1 root root 4.0K Apr 19 01:20 mem_used_max
-r--r--r--  1 root root 4.0K Apr 18 19:29 mm_stat
drwxr-xr-x  2 root root    0 Apr 18 19:29 power/
drwxr-xr-x  2 root root    0 Apr 18 19:29 queue/
-r--r--r--  1 root root 4.0K Apr 19 01:20 range
-r--r--r--  1 root root 4.0K Apr 19 01:20 removable
--w-------  1 root root 4.0K Apr 19 01:20 reset
-r--r--r--  1 root root 4.0K Apr 19 01:20 ro
-r--r--r--  1 root root 4.0K Apr 18 19:29 size
drwxr-xr-x  2 root root    0 Apr 18 19:29 slaves/
-r--r--r--  1 root root 4.0K Apr 19 01:20 stat
lrwxrwxrwx  1 root root    0 Apr 18 19:29 subsystem -> ../../../../class/block/
drwxr-xr-x  2 root root    0 Apr 18 19:29 trace/
-rw-r--r--  1 root root 4.0K Apr 18 19:29 uevent

ZRAM の初期化は起動時に armbian-zram-config サービスから /usr/lib/armbian/armbian-zram-config が実行され、その中で設定が行われます。

$ systemctl cat armbian-zram-config
# /lib/systemd/system/armbian-zram-config.service
# Armbian ZRAM configuration service
# Create 1 + number of cores compressed block devices
# This service may block the boot process for up to 30 sec

[Unit]
Description=Armbian ZRAM config
DefaultDependencies=no
After=local-fs.target
Before=armbian-ramlog.target
Conflicts=shutdown.target

[Service]
Type=oneshot
ExecStart=/usr/lib/armbian/armbian-zram-config start
ExecStop=/usr/lib/armbian/armbian-zram-config stop
RemainAfterExit=yes
TimeoutStartSec=30sec

[Install]
WantedBy=sysinit.target

/usr/lib/armbian/armbian-zram-config の中身はシェルスクリプトで、activate_ramlog_partition 関数によって /var/log の初期化が行われています。

:
中略
:
activate_ramlog_partition() {
    # /dev/zram0 will be used as a compressed /var/log partition in RAM if
    # ENABLED=true in /etc/default/armbian-ramlog is set
    ENABLED=$(awk -F"=" '/^ENABLED/ {print $2}' /etc/default/armbian-ramlog)
    [[ "$ENABLED" != "true" ]] && return

    # read size also from /etc/default/armbian-ramlog
    ramlogsize=$(awk -F"=" '/^SIZE/ {print $2}' /etc/default/armbian-ramlog)
    disksize=$(sed -e 's/M$/*1048576/' -e 's/K$/*1024/' <<<${ramlogsize:=50M} | bc)

    # choose RAMLOG_ALGORITHM if defined in /etc/default/armbian-zram-config
    # otherwise try to choose most efficient compression scheme available.
    # See https://patchwork.kernel.org/patch/9918897/
    if [ "X${RAMLOG_ALGORITHM}" = "X" ]; then
        for algo in lz4 lz4hc quicklz zlib brotli zstd ; do
            echo ${algo} >/sys/block/zram0/comp_algorithm 2>/dev/null
        done
    else
        echo ${RAMLOG_ALGORITHM} >/sys/block/zram0/comp_algorithm 2>/dev/null
    fi
    echo -n ${disksize} > /sys/block/zram0/disksize

    # if it fails, select $swap_algo. Workaround for some older kernels
    if [[ $? == 1 ]]; then
        echo ${swap_algo} > /sys/block/zram0/comp_algorithm 2>/dev/null
        echo -n ${disksize} > /sys/block/zram0/disksize
    fi

    mkfs.ext4 -O ^has_journal -s 1024 -L log2ram /dev/zram0
    algo=$(sed 's/.*\[\([^]]*\)\].*/\1/g' </sys/block/zram0/comp_algorithm)
    echo -e "### Activated Armbian ramlog partition with ${algo} compression" >>${Log}
} # activate_ramlog_partition
:
中略
:

上記の関数で mkfs.ext4 を実行しているので /var/log 以下はまっさらな状態になりますが、armbian-ramlog サービスによってログのバックアップとリストアが行われています。こちらのスクリプト/usr/lib/armbian/armbian-ramlog にあります。もう一度 armbian-ramlog サービスを確認してみます。

$ systemctl cat armbian-ramlog
# /lib/systemd/system/armbian-ramlog.service
# Armbian ramlog service
# Stores logs in (compressed) memory
# This service may block the boot process for up to 30 sec

[Unit]
Description=Armbian memory supported logging
DefaultDependencies=no
Before=rsyslog.service sysinit.target syslog.target
After=armbian-zram-config.service
Conflicts=shutdown.target
RequiresMountsFor=/var/log /var/log.hdd
IgnoreOnIsolate=yes

[Service]
Type=oneshot
ExecStart=/usr/lib/armbian/armbian-ramlog start
ExecStop=/usr/lib/armbian/armbian-ramlog stop
ExecReload=/usr/lib/armbian/armbian-ramlog write
RemainAfterExit=yes
TimeoutStartSec=30sec

[Install]
WantedBy=sysinit.target

/usr/lib/armbian/armbian-ramlog を見てみると syncToDisk 関数と syncFromDisk 関数で /var/log/var/log.hdd のやり取りをしているのがわかります。

:
中略
:
syncToDisk () {
        isSafe

        echo -e "\n\n$(date): Syncing logs to storage\n" | $LOG_OUTPUT

        if [ "$USE_RSYNC" = true ]; then
                ${NoCache} rsync -aXWv --delete --exclude "lost+found" --exclude armbian-ramlog.log --links $RAM_LOG $HDD_LOG 2>&1 | $LOG_OUTPUT
        else
                ${NoCache} cp -rfup $RAM_LOG -T $HDD_LOG 2>&1 | $LOG_OUTPUT
        fi

        sync
}

syncFromDisk () {
        isSafe

        echo -e "\n\n$(date): Loading logs from storage\n" | $LOG_OUTPUT

        if [ "$USE_RSYNC" = true ]; then
                ${NoCache} rsync -aXWv --delete --exclude "lost+found" --exclude armbian-ramlog.log --exclude *.gz --exclude='*.[0-9]' --links $HDD_LOG $RAM_LOG 2>&1 | $LOG_OUTPUT
        else
                ${NoCache} find $HDD_LOG* -maxdepth 1 -type f -not \( -name '*.[0-9]' -or -name '*.xz*' -or -name '*.gz' \) | xargs cp -ut $RAM_LOG
        fi

        sync
}
:
中略
:

syncToDisk は cron によって一日一回行われているようです。

$ cat /etc/cron.daily/armbian-ram-logging
#!/bin/sh
/usr/lib/armbian/armbian-ramlog write >/dev/null 2>&1

ZRAM はメモリ上に展開しているためシャットダウンするとデータが消失してしまいます。ルートファイルシステムに含まれる /var/log.hdd にバックアップを取り、起動時はそこからリストアを行うことで恒久化しているようです。

ログを確実に残しておきたいような場合は /etc/default/armbian-ramlogENABLEDtrue 以外にして ZRAM を無効にしておいた方がいいかもしれません。(microSD の寿命を縮めるかもしれませんが)