在 AWS 上的 Ubuntu 安裝 zram-config 出錯

放在 Amazon Web Services (AWS) 上的機器因為用途跟價格的關係, ram 的規格開很小,靠 swap 來緩衝的話吃 IO 吃比較兇會被多收錢,想要用 zram 來壓記憶體

zram 的說明可以參考 Wikipediahttp://zh.wikipedia.org/wiki/Zram

zram 是 Linux 核心的一個模組,之前被稱為「compcache」。zram 透過在RAM內的壓縮塊裝置上分頁,直到必須使用硬碟上的交換空間,以避免在磁碟上進行分頁,從而提高效能。由於 zram 可以用記憶體替代硬碟為系統提供交換空間的功能,zram 可以讓 Linux 在需要大量 RAM 的情況下在記憶體上進行交換/分頁,而提高記憶體的使用率,顯著得減少系統啟動時(此時 Linux 還不能使用外部儲存)對記憶體大小的要求。在實體記憶體較少的舊電腦上,尤其如此。

Lubuntu (13.10 開始) 以及 Chrome OS 預設都有啟用這項功能
所以就來安裝 zram-config,沒想到竟然失敗 …

錯誤訊息大概是這樣:

testuser@ubuntu:~$ sudo apt-get install zram-config
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
zram-config
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/3,078 B of archives.
After this operation, 42.0 kB of additional disk space will be used.
Selecting previously unselected package zram-config.
(Reading database ... 107939 files and directories currently installed.)
Unpacking zram-config (from .../zram-config_0.1_all.deb) ...
Processing triggers for ureadahead ...
Setting up zram-config (0.1) ...
start: Job failed to start
invoke-rc.d: initscript zram-config, action "start" failed.
dpkg: error processing zram-config (--configure):
subprocess installed post-installation script returned error exit status 1
Errors were encountered while processing:
zram-config
E: Sub-process /usr/bin/dpkg returned an error code (1)

從這邊看只知道 post-installation script returned error exit status 1
可能資質比較鈍 … 把 script 挖出來看也沒看出所以然 …

後來看到另一個 script:
https://github.com/gionn/etc/blob/edac27cf705d8ca12d39effa0f80ba62e3907288/init.d/zram

#!/bin/bash

### BEGIN INIT INFO
# Provides: zram
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Increased Performance In Linux With zRam (Virtual Swap Compressed in RAM)
# Description: Adapted from systemd scripts at https://github.com/mystilleef/FedoraZram
### END INIT INFO

DEFAULTS="/etc/default/zram"

# Include defaults if available
[ -r "$DEFAULTS" ] && . "$DEFAULTS"

# Get lsb functions
. /lib/lsb/init-functions

start() {
    # Add support of defaults file parameter - ZRAM_NDEVS
    if [ -z "$ZRAM_NDEVS" ] || [ "$ZRAM_NDEVS" -le "0" ]; then
	# get the number of CPUs
	num_cpus=$(grep -c processor /proc/cpuinfo)
    else
	# or just use user specified
	num_cpus=$ZRAM_NDEVS
    fi

    # if something goes wrong, assume we have 1
    [ "$num_cpus" != 0 ] || num_cpus=1

    decr_num_cpus=$((num_cpus - 1))

    # find module and it's param name
    error_file=$(mktemp ${RC_NAME}XXXXXX) # storage for error message
    param_name=$(/usr/bin/env modinfo --parameters zram 2>$error_file | head -1 | cut -d: -f1)
    error_message=$(<$error_file)
    rm -f $error_file
    mod_found=$?


    # load dependency modules
    if [ "$mod_found" == 0 ]; then
	log_begin_msg "Loading zRAM kernel module"
	modprobe zram "$param_name=$num_cpus"
	log_end_msg $?
    else
	log_failure_msg "Failed to load zRAM kernel module: ${error_message}"
	# shit happens, yep.
	exit $mod_found
    fi

    # get the amount of memory in the machine
    mem_total_kb=$(fgrep MemTotal /proc/meminfo | grep -E --only-matching '[[:digit:]]+')
    mem_total=$((mem_total_kb * 1024))

    # Add support of defaults file parameter - ZRAM_USE_PERCENT
    if [ -z "$ZRAM_USE_PERCENT" ] || [ "$ZRAM_USE_PERCENT" -le "0" ] || [ "$ZRAM_USE_PERCENT" -gt "100" ]; then
	# use 100% of ram for zRAM storage (suitable for low-ram laptops)
	use_percent=100
    else
	# or just use user specified
	use_percent=$ZRAM_USE_PERCENT
    fi

    zsize=$((use_percent * mem_total / num_cpus / 100))

    # initialize the devices
    for i in $(seq 0 $decr_num_cpus); do
	echo $zsize > /sys/block/zram$i/disksize
    done

    # get page size
    page_size=$(/usr/bin/env getconf PAGESIZE || /usr/bin/env getconf PAGE_SIZE)

    # Creating swap filesystems
    for i in $(seq 0 $decr_num_cpus); do
	msg=">  Making swap on /dev/zram$i"
	mkswap -p $page_size /dev/zram$i 2>&1 >/dev/null
	[ "$?" -eq "0" ] && log_success_msg $msg || log_failure_msg $msg
    done

    # Switch the swaps on
    for i in $(seq 0 $decr_num_cpus); do
	msg=">>  Activating swap on /dev/zram$i"
	swapon -p 100 /dev/zram$i
	[ "$?" -eq "0" ] && log_success_msg $msg || log_failure_msg $msg
    done

    # TODO FIXME need strict error reporting
    # log_end_msg 0
}

stop() {
    # Switching off swap ASAP
    for zswap in $(fgrep /dev/zram /proc/swaps | cut -d' ' -f1); do
	    swapoff $zswap
    done

    # Custom kernels can contain zram compiled-in
    [ -z "$(fgrep zram /proc/modules)" ] || rmmod zram
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 3
        start
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        RETVAL=1
esac

把這拿來一用 … 馬上就看到是缺 zram module 了 Orz.. (可參考上方script第50行前後的code):
* Loading zRAM kernel module
FATAL: Module zram not found.

原來是 AWS 提供的 Ubuntu image 預設沒有 extra modules,按照 Linux kernel 版本把對應的 extra modules 裝上就行了:

$ sudo apt-get install linux-image-extra-virtual

得到結果:

testuser@ubuntu:~$ sudo apt-get install zram-config
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
zram-config
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/3,078 B of archives.
After this operation, 42.0 kB of additional disk space will be used.
Selecting previously unselected package zram-config.
(Reading database ... 97293 files and directories currently installed.)
Unpacking zram-config (from .../zram-config_0.1_all.deb) ...
Processing triggers for ureadahead ...
Setting up zram-config (0.1) ...
zram-config start/running

來確認一下:

testuser@ubuntu:~$ free -h
total used free shared buffers cached
Mem: 588M 536M 52M 0B 9.3M 338M
-/+ buffers/cache: 188M 400M
Swap: 294M 88K 294M

testuser@ubuntu:~$ cat /proc/swaps
Filename Type Size Used Priority
/dev/zram0 partition 301552 124 5

搞定收工啦!

害我抓了兩台 Ubuntu 13.04 來測試結果是好的, 還把它們升級 13.10 … 一不小心蓋掉了一份資料 … XD

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。