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