Man sollte sich in jedem Fall im Klaren sein, dass mit 256MB Ram heute kein Blumentopf mehr zu gewinnen ist, aber eine bedachte Paketauswahl macht das System zu einem schnellen und leisen Server. (Ich habe z.B. mini-httpd statt Apache installiert, PHP ist bei mir der größte Speicherfresser, daher nutze ich es sehr sparsam. Eine Datenbank kommt nicht zum Einsatz - die Festplatte soll schließlich die meiste Zeit schlafen.)
Im Falle der Neuformatierung der Datenplatte (wegen 16k PageSize) erledigt das ein:
mkfs.ext4 -b 16384 -m 0 /dev/sda4 mount /dev/sda4 /media
Die Swap-Partition wird neu initialisiert mit:
mkswap /dev/sda3 swapon /dev/sda3
Will man nicht mehr ins alte System booten, können die Raid-Informationen auch gelöscht werden, so dass /dev/sda2 normal gemountet werden kann:
apt-get install nullmailer mdadm parted /dev/sda set 1 raid off parted /dev/sda set 2 raid off mdadm --zero-superblock /dev/sda2 mount /dev/sda2 /mnt
Nun können die beiden Zeilen in der fstab auch wieder auskommentiert werden.
Die letzte Zeile der fstab mountet das Logverzeichnis als TMPFS, d.h. die Festplatte muss nicht aus dem Standby geholt werden. Da das Ramlog Paket für Jessie nicht zur Verfügung steht müssen wir uns selbst behelfen:
#!/bin/sh # # /usr/local/sbin/ramlog.sh # . /lib/lsb/init-functions start() { log_begin_msg "RAMLOG: Read files from disk.." tar xfz /var/ram_log.tar.gz -C / log_end_msg 0 } stop() { log_begin_msg "RAMLOG: Write files to disk.." tar cfz /var/ram_log.tar.gz --directory=/ var/log/ log_end_msg 0 } case "$1" in start) start ;; stop) stop ;; flush) stop ;; *) echo "Usage: $0 {start|stop|flush}" exit 1 esac
Und der entsprechende Service Eintrag für Systemd
#/etc/systemd/system/ramlog.service [Unit] Description=Ramlog After=local-fs.target Before=cron.service syslog.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/ramlog start ExecStop=/usr/local/sbin/ramlog stop [Install] WantedBy=multi-user.targetDem MyBook Live fehlt außerdem eine RTC, daher sollte die per NTP geholte Zeit gelegntlich zwischengespeichert werden, damit sie z.B. beim Starten gleich zur Verfügung steht. Das macht das Script /etc/init.de/saveclock.sh aus dem Original-Image:
#!/bin/sh # # /etc/init.d/saveclock.sh ### BEGIN INIT INFO # Provides: saveclock # Required-Start: # Required-Stop: # Default-Start: S # Default-Stop: 0 1 6 # Short-Description: periodically save clock to disk # Description: save clock to disk on startup and periodically ### END INIT INFO . /lib/lsb/init-functions saveclock=0 buildtime=0 [ -f /var/local/saveclock ] && saveclock=`cat /var/local/saveclock` [ -f /etc/version.buildtime ] && buildtime=`cat /etc/version.buildtime` case "$1" in start) log_daemon_msg "Retrieving saved clock" if [ "$saveclock" -lt "$buildtime" ]; then saveclock=$buildtime fi if [ "$saveclock" != "0" ]; then date -s @$saveclock echo $saveclock > /var/local/saveclock echo "Set clock to `date`" fi log_end_msg 0 ;; stop|reload) date +%s > /var/local/saveclock ;; *) echo "Usage: /etc/init.d/saveclock.sh {start|stop|reload}" exit 1 ;; esac exit 0
Und alles Aktivieren (auch gleich noch das /tmp Verzeichnis als TMPFS anlegen):
/usr/local/sbin/ramlog flush rm -rf /var/log/* mount /var/log systemctl enable ramlog.service systemctl start ramlog.service systemctl enable tmp.mount systemctl start tmp.mount rm /lib/systemd/system/getty.target.wants/getty-static.service cd /etc/init.d/ /usr/sbin/update-rc.d saveclock.sh defaults /usr/sbin/update-rc.d saveclock.sh enable
Da irgendwann das /var/log überlaufen würde, müssen die Log-Dateien von Zeit zu Zeit bereinigt werden. Dazu benutze ich ebenfalls ein original WD-Script (/usr/local/sbin/rotateLogs.sh):
# /etc/crontab: system-wide crontab 2 */4 * * * root [ ! -f /tmp/standby ] && /etc/init.d/saveclock.sh reload > /dev/null 2>&1 2 */4 * * * root [ ! -f /tmp/standby ] && /usr/local/sbin/rotateLogs.sh > /dev/null 2>&1 2 */4 * * * root [ ! -f /tmp/standby ] && /usr/local/sbin/ramlog flush > /dev/null 2>&1 14 07 * * * root /usr/sbin/ntpdate-debian >> /dev/null
#!/bin/sh # # 2010 Western Digital Technologies, Inc. All rights reserved. # # /usr/local/sbin/rotateLogs.sh - calls logrotate and purglogs ## PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin # check for log files larger than 1MB & do cleanup /usr/local/sbin/purgelogs.sh # check if /var/log/messages file is removed, re-create if [ ! -e /var/log/messages ]; then logrotate -f /etc/logrotate.conf fi # check if logs are full, cleanup rotated logs if so dfout=`df | grep "/var/log"` percent=`echo "$dfout" | awk '{printf("%.0f\n", $5) }'` if [ "$percent" -gt "90" ]; then logger "Logs getting full, remove all rotated logs" rm -f /var/log/*.1* rm -f /var/log/*.2* fi
#!/bin/bash # # 2012 Western Digital Technologies, Inc. All rights reserved. # # /usr/local/sbin/purgelogs.sh - purges logfiles in order to keep the log TMPFS in check ## PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin do_start() { # check for log files larger than 1MB and remove MAX_SIZE="1M" N_LINES="1000" purgeRecord="/var/log/purge.log" FILE_LIST=( `find /var/log/* -type f -size +$MAX_SIZE` ) if [ ! -z "$FILE_LIST" ]; then echo `date` >> $purgeRecord dfout=`df | grep "/var/log"` percent=`echo "$dfout" | awk '{printf("%.0f\n", $5) }'` # if ramlog full remove files, else keep last N lines if [ "$percent" -gt "90" ]; then for i in "${FILE_LIST[@]}" do echo "ramlog is full, removing files:" >> $purgeRecord size=$(stat -c%s "$i") echo "$i $size" >> $purgeRecord rm -f $i done else for i in "${FILE_LIST[@]}" do if [[ "$i" == *.gz ]]; then echo "removed: $i" >> $purgeRecord rm -f $i else echo "pruned: $i" >> $purgeRecord tail -n $(($N_LINES)) $i > tmp.log rm -f $i mv tmp.log $i fi done fi fi } case "$1" in start|"") do_start ;; restart|reload|force-reload) echo "Error: argument '$1' not supported" >&2 exit 3 ;; stop) # No-op ;; *) echo "Usage: purgelogs.sh [start|stop]" >&2 exit 3 ;; esac
Um die Festplatte schlafen zu legen, benutze ich das monitorio.sh Script von Western Digital und wandle es leicht ab:
#!/bin/bash # # (c) 2011 Western Digital Technologies, Inc. All rights reserved. # # /usr/local/sbin/monitorio.sh - Monitor disk activity, and put system into standby. Also, monitor to trigger file tally process ## PATH=/sbin:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin . /lib/lsb/init-functions MIN_SINCE_DISK_ACCESS=/tmp/minutes_since_disk_access dataVolumeDevice=/dev/sda4 declare -i sleepcount declare -i rootdisk_thresh declare -i enterStandbyTime=0 rm -f /tmp/standby source /usr/local/etc/standby.conf resetSleepCount() { sleepcount=0 source /usr/local/etc/standby.conf rootdisk_thresh=$((standby_time-1)) } currentRootDevice=`cat /proc/cmdline | awk '/root/ { print $1 }' | cut -d= -f2` rootDisk=`basename ${currentRootDevice}` dataVolumeDisk=`basename ${dataVolumeDevice}` drivelist=(${dataVolumeDevice}) echo "0" > ${MIN_SINCE_DISK_ACCESS} if [ "$1" == "debug" ]; then echo "1" > /proc/sys/vm/block_dump dmesg -c > /dev/null fi while :; do for i in ${drivelist[@]}; do hdparm -C $i | grep -q "standby" standby_test=$? [ "$standby_test" -eq "1" ] && break done if [ "$standby_test" -eq "0" ]; then sleep 5 continue else if [ -f /tmp/standby ]; then standby_since=`stat --format %z /tmp/standby` rm -f /tmp/standby # Cancel blue color and turn on green if applicable echo green > /sys/class/leds/a3g_led/color currentTime=`date +%s` timeInStandby=`expr $currentTime - $enterStandbyTime` echo "exit standby after $timeInStandby (since $standby_since)" logger "exit standby after $timeInStandby (since $standby_since)" if [ "$1" == "debug" ]; then dmesg -c fi fi resetSleepCount echo $sleepcount > ${MIN_SINCE_DISK_ACCESS} ior_root=`awk -v disk="${rootDisk}" '{if ($3==disk) print $6}' /proc/diskstats` iow_root=`awk -v disk="${rootDisk}" '{if ($3==disk) print $10}' /proc/diskstats` ior_datavol=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $6}' /proc/diskstats` iow_datavol=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $10}' /proc/diskstats` if [ "$1" == "debug" ]; then echo "Init ior_datavol=$ior_datavol ior_datavol2=$ior_datavol2" echo " iow_datavol=$iow_datavol iow_datavol2=$iow_datavol2" echo " ior_root=$ior_root ior_root2=$ior_root2" echo " iow_root=$iow_root iow_root2=$iow_root2" dmesg -c fi while :; do # Wait for 60 seconds sleep 60 ior_root2=`awk -v disk="${rootDisk}" '{if ($3==disk) print $6}' /proc/diskstats` iow_root2=`awk -v disk="${rootDisk}" '{if ($3==disk) print $10}' /proc/diskstats` ior_datavol2=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $6}' /proc/diskstats` iow_datavol2=`awk -v disk="${dataVolumeDisk}" '{if ($3==disk) print $10}' /proc/diskstats` # use data volume writes until near sleep threshold, then check all disk writes old_sleepcount=sleepcount if [ $((sleepcount)) -eq $((rootdisk_thresh)) ] && [ "$ior_root" -eq "$ior_root2" ] && [ "$iow_root" -eq "$iow_root2" ]; then sleepcount=$((sleepcount+1)) elif [ $((sleepcount)) -lt $((rootdisk_thresh)) ] && [ "$ior_datavol" -eq "$ior_datavol2" ] && [ "$iow_datavol" -eq "$iow_datavol2" ]; then sleepcount=$((sleepcount+1)) else resetSleepCount fi echo $sleepcount > ${MIN_SINCE_DISK_ACCESS} if [ "$1" == "debug" ]; then [ "$sleepcount" != "0" ] && echo "sleepcount: $sleepcount" [ "$sleepcount" == "0" ] && echo "Disk activity:" echo "... ior_datavol=$ior_datavol ior_datavol2=$ior_datavol2" echo "... iow_datavol=$iow_datavol iow_datavol2=$iow_datavol2" echo "... ior_root=$ior_root ior_root2=$ior_root2" echo "... iow_root=$iow_root iow_root2=$iow_root2" # dmesg -c fi ior_datavol=$ior_datavol2 iow_datavol=$iow_datavol2 ior_root=$ior_root2 iow_root=$iow_root2 if [ "$standby_enable" == "enabled" ] && [ "$sleepcount" -eq "$standby_time" ] ; then touch /tmp/standby enterStandbyTime=`date +%s` echo "Enter standby" if [ "$1" == "debug" ]; then echo "`date`: Enter standby " dmesg -c > /dev/null fi for i in ${drivelist[@]}; do hdparm -y $i >/dev/null done # turn on solid blue if applicable echo blue > /sys/class/leds/a3g_led/color sleep 5 break fi done fi done
Damit das Script funktioniert, muss noch eine Config Datei angelegt werden:
#/usr/local/etc/standby.conf standby_enable=enabled standby_time=14
Und eine entsprechende Systemd Unit:
#/etc/systemd/system/monitorio.service [Unit] Description=Disk Sleep Daemon After=local-fs.target [Service] ExecStart=/usr/local/sbin/monitorio.sh ExecStop=/usr/bin/killall monitorio.sh [Install] WantedBy=multi-user.target
Um aus dem RAM auch noch das letzte Quäntchen herauszubekommen, nutze ich ein Kompressions-Modul und damit ca 75% des Speichers als komprimierten SWAP.
Dazu muss das "zram" Modul beim start geladen werden:
# /etc/modules: kernel modules to load at boot time. # # This file contains the names of kernel modules that should be loaded # at boot time, one per line. Lines beginning with "#" are ignored. zram
Die Einrichtung erfolgt wieder über eine Systemd Unit:
[Unit] Description=Activate zram swap device After=systemd-modules-load.service #zram module must be loaded (e.g. put it into /etc/modules) ConditionPathExists=/sys/module/zram [Service] #the zram device to be used Environment=ZRAM_DEVICE=0 #the size of the zram swap disk in bytes (K,M,G suffix allowed) #75% of 256MB Environment=ZRAM_DISKSIZE=197197824 #the swap priority Environment=ZRAM_SWAP_PRIO=20 Type=oneshot RemainAfterExit=yes ExecStart=/bin/sh -c "echo 1 > /sys/block/zram$ZRAM_DEVICE/reset" ExecStart=-/bin/sh -c "echo $(nproc --all) > /sys/block/zram$ZRAM_DEVICE/max_comp_streams" ExecStart=/bin/sh -c "echo $ZRAM_DISKSIZE > /sys/block/zram$ZRAM_DEVICE/disksize" ExecStart=/sbin/mkswap /dev/zram${ZRAM_DEVICE} ExecStart=/sbin/swapon -p ${ZRAM_SWAP_PRIO} /dev/zram${ZRAM_DEVICE} ExecStop=/sbin/swapoff /dev/zram${ZRAM_DEVICE} ExecStop=/bin/sh -c "echo 1 > /sys/block/zram$ZRAM_DEVICE/reset" [Install] WantedBy=multi-user.target
Keine Kommentare:
Kommentar veröffentlichen