hdd-spindown.sh
Mal wieder Zeit gefunden, einen schon leicht angestaubten Punkt auf meiner 2code-Liste abzuhaken:
Ein Bash-Script, das Platten bei Inaktivität nach definierbarem Timeout per hdparm -y in Standby schickt. Für mich sehr nützlich bei SATA-Platten, die sich nicht per hdparm -S konfigurieren lassen.
Gehostet wie immer auf github, oder direkt hier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #!/bin/bash # # Automatic disk standby using kernel diskstats and hdparm # # Version 1.1, 2011 by Alexander Koch <lynix47@gmail.com> # # DEVICES syntax: DEVICE:TIMEOUT_SEC DEVICES=( "sda:120" "sdb:120" ) function device_worker() { test -e "/dev/$1" || return 1 logger -t hdd-spindown.sh "spawned monitor thread for $1" COUNT_R=0 COUNT_W=0 while true; do NEW_R=$(awk '{print $1}' /sys/block/$1/stat) NEW_W=$(awk '{print $5}' /sys/block/$1/stat) if [ $COUNT_R -eq $NEW_R ] && [ $COUNT_W -eq $NEW_W ]; then if hdparm -C /dev/$1 | grep active &>/dev/null; then logger -t hdd-spindown.sh "suspending $1" hdparm -qy /dev/$1 if [ $? -gt 0 ]; then logger "failed to suspend $1" return 1 fi fi else COUNT_R=$NEW_R COUNT_W=$NEW_W fi sleep $2 done } for D in ${DEVICES[@]}; do device_worker $(echo "$D" | cut -d ':' -f 1) $(echo "$D" | cut -d ':' -f 2) & done exit 0 |
Auf Performance-Optimierungen habe ich bewusst verzichtet und alles möglichst simpel gehalten.
Funktionsbedingt ist der einstellbare Wert für den Timeout (T) übrigens nicht hart; die reale Zeit an Inaktivität ti genügt der Bedingung T ≤ ti < 2T.
aerotools Update
Dank der Semesterferien fand ich nun endlich Zeit, mein aerotools-Projekt auf Vordermann zu bringen. Neben einigen Bugfixes und Vereinfachungen am Daemon habe ich die Library auf libusb-1.0 portiert, was laut Homepage die empfohlene, aktuelle Version ist. Unter Arch coexistiert sie als libusb1 neben der libusb, die standardmäßig installiert wird - etwas verwirrend, wenn man den Hinweistext auf der Homepage nicht gelesen hat
Alle aquaero®-Besitzer seien also herzlich eingeladen, die neue Version zu testen! Bugreports sind immer willkommen, am Besten über die "Issues"-Funktion auf Github.
logcheck-rules prüfen
Beim Ändern von ignore-Regelsätzen für logcheck unterlaufen mir ganz gern Tippfehler in komplexeren Ausdrücken. Dumm nur, wenn ich das erst beim nächsten Cron-Run merke, in Form einer solchen Meldung:
egrep: Unmatched ) or \)
Toll: weder Regelsatz noch Zeilennummer werden genannt, also manuell suchen. Da es sich aber meist um umfangreiche Regelsätze handelt und ich (selbst bei gefundenem Satz) keine Möglichkeit gefunden habe, egrep die Zeilennummer des ungültigen Ausdrucks zu entlocken, entstand auf die Schnelle folgendes simples Script:
#!/bin/bash if [ $# -ne 1 ]; then echo "usage: $0 RULES_FILE" exit 1 fi if ! [ -r "$1" ]; then echo "unable to read $1" exit 1 fi LINES=$(wc -l "$1" | cut -d ' ' -f 1) for I in $(seq $LINES); do echo "line $I..." echo "foo" | egrep "$(cat "$1" | head -n $I | tail -n 1)" done exit 0
Es gibt bestimmt auch irgendeine elegantere Lösung, aber vielleicht erspart es ja jemandem die nervige Sucherei
Arch ramdisk-script 1.4
In meinem Arch Ramdisk-Script <1.4 hatte sich ein dämlicher Bug eingeschlichen: bei sämtlichen rsync-Aufrufen fehlte das --delete.
Das bewirkt z.B. bei Verwendung mit Firefox, dass der Cache nie geleert wird und (streng) monoton wächst - unschön.
Hier die gefixte Version
#!/bin/sh # # Manages outsourcing of specified directories into memory on bootup and # takes care of synchronization/backup on system shutdown. # # Version 1.4, 2010-04-26, by Alexander Koch # # includes . /etc/rc.conf . /etc/rc.d/functions # configuration (syntax is: [persist. storage]:[mountpoint]:[mount options]) DISKS=('/home/alex/.ramdisks/_mozilla:/home/alex/.mozilla:size=100M,uid=1000,gid=100' \ 'empty:/home/alex/.adobe:size=10M,uid=1000,gid=100' \ 'empty:/home/alex/.macromedia:size=10M,uid=1000,gid=100') # helper functions function activate_rd() { [ -d "$1" ] || [ "$1" = "empty" ] || return 1 [ -d "$2" ] || return 1 mount | grep "$2" &>/dev/null && return 1 MNT="mount -t tmpfs" [ -z "$3" ] || MNT="$MNT -o $3" $MNT none "$2" [ $? -gt 0 ] && return 1 if [ "$1" != "empty" ]; then for D in $1/.* $1/*; do [ "$(basename "$D")" == "." ] && continue [ "$(basename "$D")" == ".." ] && continue rsync -axq "$D" "$2" &>/dev/null if [ $? -gt 0 ]; then umount "$2" return 1 fi done fi return 0 } function backup_rd() { mount | grep "$1" &>/dev/null || return 0 if [ "$2" != "empty" ]; then for D in $1/.* $1/*; do [ "$(basename "$D")" == "." ] && continue [ "$(basename "$D")" == ".." ] && continue rsync -axq --delete "$D" "$2" &>/dev/null if [ $? -gt 0 ]; then tar -cf "/root/$(basename "$2")-failed.tar" "$1" return 1 fi done fi umount "$1" || return 1 return 0 } # main logic case $1 in start) stat_busy "Mounting ramdisks" error=0 for M in ${DISKS[@]}; do FROM="$(echo "$M" | cut -d ':' -f 1)" TO="$(echo "$M" | cut -d ':' -f 2)" OPTS="$(echo "$M" | cut -d ':' -f 3)" activate_rd "$FROM" "$TO" "$OPTS" || error=1 done if [ $error -eq 0 ]; then add_daemon ramdisks stat_done else stat_fail exit 1 fi ;; stop) stat_busy "Saving ramdisks" error=0 for M in ${DISKS[@]}; do FROM="$(echo "$M" | cut -d ':' -f 2)" TO="$(echo "$M" | cut -d ':' -f 1)" backup_rd "$FROM" "$TO" || error=1 done if [ $error -eq 0 ]; then rm_daemon ramdisks stat_done else stat_fail echo -n "WARNING: failed to save ramdisk(s), tried to make " echo "backup(s) under /root." echo "Hit enter to proceed shutdown." read DUMMY exit 1 fi ;; restart) if ! ck_daemon ramdisks; then "$0" stop && sleep 3 fi "$0" start ;; *) echo "usage: $0 {start|stop|restart}" ;; esac exit 0
Arch ramdisk-script 1.3
Mein Arch ramdisk-script hat ein weiteres Update erfahren, die Konfiguration ist nun mehr nach KISS und dot-Ordner werden korrekt behandelt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #!/bin/sh # # Manages outsourcing of specified directories into memory on bootup and # takes care of synchronization/backup on system shutdown. # # Version 1.3, 2010-03-15, by Alexander Koch # # includes . /etc/rc.conf . /etc/rc.d/functions # configuration (syntax is: [persist. storage]:[mountpoint]:[mount options]) DISKS=('/home/alex/.ramdisks/_mozilla:/home/alex/.mozilla:size=100M,uid=1000,gid=100' \ 'empty:/home/alex/.adobe:size=10M,uid=1000,gid=100' \ 'empty:/home/alex/.macromedia:size=10M,uid=1000,gid=100') # helper functions function activate_rd() { [ -d "$1" ] || [ "$1" = "empty" ] || return 1 [ -d "$2" ] || return 1 mount | grep "$2" &>/dev/null && return 1 MNT="mount -t tmpfs" [ -z "$3" ] || MNT="$MNT -o $3" $MNT none "$2" [ $? -gt 0 ] && return 1 if [ "$1" != "empty" ]; then for D in $1/.* $1/*; do [ "$(basename "$D")" == "." ] && continue [ "$(basename "$D")" == ".." ] && continue rsync -axq "$D" "$2" &>/dev/null if [ $? -gt 0 ]; then umount "$2" return 1 fi done fi return 0 } function backup_rd() { mount | grep "$1" &>/dev/null || return 0 if [ "$2" != "empty" ]; then for D in $1/.* $1/*; do [ "$(basename "$D")" == "." ] && continue [ "$(basename "$D")" == ".." ] && continue rsync -axq "$D" "$2" &>/dev/null if [ $? -gt 0 ]; then tar -cf "/root/$(basename "$2")-failed.tar" "$1" return 1 fi done fi umount "$1" || return 1 return 0 } # main logic case $1 in start) stat_busy "Mounting ramdisks" error=0 for M in ${DISKS[@]}; do FROM="$(echo "$M" | cut -d ':' -f 1)" TO="$(echo "$M" | cut -d ':' -f 2)" OPTS="$(echo "$M" | cut -d ':' -f 3)" activate_rd "$FROM" "$TO" "$OPTS" || error=1 done if [ $error -eq 0 ]; then add_daemon ramdisks stat_done else stat_fail exit 1 fi ;; stop) stat_busy "Saving ramdisks" error=0 for M in ${DISKS[@]}; do FROM="$(echo "$M" | cut -d ':' -f 2)" TO="$(echo "$M" | cut -d ':' -f 1)" backup_rd "$FROM" "$TO" || error=1 done if [ $error -eq 0 ]; then rm_daemon ramdisks stat_done else stat_fail echo -n "WARNING: failed to save ramdisk(s), tried to make " echo "backup(s) under /root." echo "Hit enter to proceed shutdown." read DUMMY exit 1 fi ;; restart) if ! ck_daemon ramdisks; then "$0" stop && sleep 3 fi "$0" start ;; *) echo "usage: $0 {start|stop|restart}" ;; esac exit 0 |
Automatische Vhosts mit Lighttpd
Mein bereits erwähntes lighttpd-vhost-script hat ein Update erfahren und unterstützt jetzt Subdomains und Vhost- sowie Subdomain-spezifische configs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #!/bin/bash VHOST_ROOT="/var/www" VHOST_DEF="default" VHOST_CONF="vhost.conf" SBD_ROOT="subdomains" DOC_ROOT="htdocs" for VHOST in $(find $VHOST_ROOT -mindepth 1 -maxdepth 1 -type d -exec basename {} \;); do # skip default vhost if [ "$VHOST_DEF" == "$VHOST" ]; then continue fi echo "\$HTTP[\"host\"] =~ \"^(www\.|)$VHOST\" {" echo " server.document-root = \"$VHOST_ROOT/$VHOST/$DOC_ROOT\"" echo " accesslog.filename = \"/var/log/lighttpd/$VHOST.access.log\"" if [ -e "$VHOST_ROOT/$VHOST/$VHOST_CONF" ]; then # include vhost config cat "$VHOST_ROOT/$VHOST/$VHOST_CONF" fi echo "}" echo "" # subdomains if [ -d "$VHOST_ROOT/$VHOST/$SBD_ROOT" ]; then for SBD in $(find $VHOST_ROOT/$VHOST/$SBD_ROOT -mindepth 1 -maxdepth 1 -type d -exec basename {} \;); do echo "\$HTTP[\"host\"] =~ \"^$SBD.$VHOST\" {" echo " server.document-root = \"$VHOST_ROOT/$VHOST/$SBD_ROOT/$SBD/$DOC_ROOT\"" echo " accesslog.filename = \"/var/log/lighttpd/$VHOST.access.log\"" if [ -e "$VHOST_ROOT/$VHOST/$SBD_ROOT/$SBD/$VHOST_CONF" ]; then # include subdomain's custom config cat "$VHOST_ROOT/$VHOST/$SBD_ROOT/$SBD/$VHOST_CONF" fi echo "}" done echo "" fi done |
etc-update
Aus meiner Gentoo-Zeit habe ich oft etc-update vermisst, was sich um das Aktualisieren von Configs kümmert. Als Arch-Pendant hier mal mein Ansatz in Form eines Bash-Scripts. Es findet aktualisierende und verwaiste .pacnew, sowie überholte .pacsave und arbeitet sie interaktiv sequentiell ab.
#!/bin/sh
DIR="/etc"
if [ $(id -u) -gt 0 ]; then
sudo $0
exit $?
fi
function work()
{
ANS="z"
while echo "$ANS" | egrep -v '^[0-3]$' &>/dev/null; do
echo "$1:"
echo " [0] colordiff (old->new)"
echo " [1] upgrade (overwrite)"
echo " [2] keep (delete .pacnew)"
echo " [3] skip"
echo -n "choice: "
read ANS
done
case $ANS in
0)
colordiff "$1" "$2"
work "$1" "$2"
;;
1)
mv "$2" "$1" || exit 1
;;
2)
rm "$2" || exit 1
;;
3)
true
;;
*)
work "$1" "$2"
;;
esac
}
PACNEW="$(find $DIR -iname '*.pacnew' 2>/dev/null)"
PACSAV="$(find $DIR -iname '*.pacsave' 2>/dev/null)"
for FILE in $PACNEW; do
CONF="${FILE%.pacnew}"
if [ -e "$CONF" ]; then
work "$CONF" "$FILE"
else
echo -n "$FILE orphaned, delete? [Y/n] "
read ANS
if [ "$ANS" == "Y" -o "$ANS" == "y" -o "$ANS" == "" ]; then
rm "$FILE" || exit 1
fi
fi
done
for FILE in $PACSAV; do
CONF="${FILE%.pacsave}"
if [ -e "$CONF" ]; then
echo -n "$CONF obsolete ($(basename $CONF) present), delete? [Y/n] "
else
echo -n "$FILE remaining, delete? [Y/n] "
fi
read ANS
if [ "$ANS" == "Y" -o "$ANS" == "y" -o "$ANS" == "" ]; then
rm "$FILE" || exit 1
fi
done
exit 0
Wie immer der Hinweis: Benutztung auf eigene Gefahr!
Update: Ja, ich kenne yaourt und weiß um yaourt -C Bescheid *grml*, aber warum yaourt benutzen, wenn man auch ein Bashscript schreiben kann?
vcp – Verbose cp
Eine Sache, die mich seit einigen Monaten immer wieder ganze Abende gekostet hat und über die ich schon lange bloggen wollte, aber nie Zeit fand: Verbose cp, aka vcp.
vcp soll das Gleiche tun wie cp, allerdings mit Fortschrittsanzeige und ETA. Geboren wurde die Idee dafür, als ich einen Aufhänger gesucht habe, endlich mal richtig C zu lernen, und mich daran erinnerte, wie sehr ich die gepatchten coreutils aus Gentoo-Zeiten vermisse, wenn ich in einer ssh-Session mal wieder am Verschieben einer größeren Datei bin und mich frage, wann das dämliche Ding endlich fertig ist.
Ich habe versucht, den Code so simpel wie möglich zu halten, um KISS treu zu bleiben. Gelungen ist mir das sicher nicht überall, aber da es ja ein Lernprojekt ist und ich noch keinen umfassenden Überblick über die Standardbibliotheken habe, sehe ich das nicht als tragisch an.
Im Moment befindet sich das Tool in einer schon recht brauchbaren Phase: reguläre Dateien und Ordner (yey, Rekursion!
) können bereits kopiert werden, die Fortschrittsanzeige ist ebenfalls implementiert und liefert Datei- und Jobstatus, sowie ETA und gemittelte Geschwindigkeit. Ebenfalls praktisch: fehlgeschlagene Dateien werden übergangen und erst am Ende bemängelt, d.h. man muss nicht bei jedem Fehler immer von vorne beginnen, sondern kann sich beim zweiten Versuch auf die Problemfälle konzentrieren und bereits vorhandene Dateien automatisch überspringen lassen.
Um nicht in detaillierte Beschreibungen der Funktionalität abzudriften sei an dieser Stelle genug der Vorstellung, wer bereits einen Blich auf meine Arbeit werfen möchte, kann den Code (steht unter GPLv3) über http://github.com/lynix/vcp beziehen und ausprobieren. Es sei noch darauf hingewiesen, dass sich das Tool in der Entwicklung befindet, Benutzung auf eigene Gefahr!
Sobald ich mehr Zeit habe, bekommt das Ding dann auch noch eine rudimentäre Homepage mit besserer Dokumentation.
Link-Grabbing per Fake-Downloader
Wer über Nacht große Downloads auf der Xorg-losen Box laufen lassen will, braucht einen wget-tauglichen Link. Oft wird gerade dieser jedoch von der anbietenden Seite auf Biegen und Brechen zu verschleiern versucht. Es gibt zwar für jede Taktik auch eine geeignete Gegenmaßnahme (sonst würde der Download per Browser ja auch nicht funktionieren), wer sich aber das Suchen und Basteln sparen möchte und auch gern mal viele Links ohne großen Aufwand zusammenklicken will, kann folgende Methode nutzen:
Über das Firefox-Addon FlashGot lässt sich ein benutzerdefinierter Downloadmanager einrichten, an den FlashGot dann die URL und wahlweise diverse andere Informationen wie Header, etc. weiter gibt.
Als so ein Downloadmanager dient beispielsweise folgendes kleines Bash-script, welches alle ihm übergebenen Links eines bekannten 1-Click-Hosters (
) unter ~/links.txt ablegt:
#!/bin/sh echo "$1" | sed -e 's/\/.*\.rapid/\/\/rapid/' >> ~/links.txt exit 0
