zur Übersicht: Linux: meine Software und Konfigurationstipps
03.02.2006
Neulich flippte irgendein KDE-Prozess völlig aus, riss die gesamte I/O-Bandbreite des Systems an sich und brachte es damit quasi zum Stillstand. Ich konnte mich auch nicht mehr als root einloggen, um den Übeltäter zu beseitigen. Es dauerte nach der Eingabe des Logins schon etwa eine Minute, bis überhaupt der Passwortprompt erschien. Danach war dann Ende. Vermutlich wäre fünf Minuten später der Shellprompt da gewesen, aber so lange will ich nicht warten müssen.
Seit Kernel 2.6.13 gibt es den CFQ-I/O-Scheduler (siehe auch mein Programm ioniced). Damit ist es möglich, Prozessen eine höhere I/O-Priorität zuzuweisen als den anderen. Das Problem sollte zu lösen sein, indem man eine der virtuellen Konsolen mit maximaler I/O- und CPU-Priorität laufen lässt. Dann dauert lediglich der Wechsel vom X-Server auf die Konsole noch lange. Das Login sollte mit maximaler Geschwindigkeit ablaufen, und die aus dieser root-Shell gestarteten Prozesse sollten ebenfalls höchste Priorität haben. Auf diese Weise sollte es unproblematisch sein, mit top
und ps
den Übeltäter zu identifizieren und per ionice
zu entschärfen oder gleich mit kill
zu entsorgen. Das waren viele Konjunktive in diesem Absatz, was ich damit entschuldigen möchte, dass solche Situationen selten vorkommen und die hier vorgestellte Lösung daher noch nicht unter realistischen Bedingungen getestet werden konnte. Selbst ein find
mit Echtzeit-I/O-Priorität beeinträchtigt mein System nicht; damit wollte ich einen Test vornehmen.
Ich habe mich für tty2 entschieden. Ich lasse den getty-Prozess dort mit maximaler Priorität laufen. Ursprünglich habe ich in den bash-Startdateien eine Abfrage gehabt, ob sich root einloggt, aber da ich bei meinem Problem ewig auf den Shellprompt warten musste, löst das womöglich das Problem nicht. Da sich auch User auf tty2 einloggen können, muss die gestartete Shell die Priorisierung in diesem Fall loswerden. Allerdings gilt das nur für Systeme, auf denen User mit lokaler Loginmöglichkeit wirklich Ärger machen könnten. Über DoS gehen deren Möglichkeiten ja nicht hinaus, und wer sich eingeloggt hat, loggt das System mit, bevor der Shellprompt kommt... Dieses Problem ist also eher theoretischer Natur, aber ich wollte darauf hinweisen.
Die getty-Prozesse werden von init
über die Datei /etc/inittab gestartet. Es muss also das getty für tty2 mit der gewünschten höheren Priorität gestartet werden. Nach dem Editieren der Datei muss init
mit Hilfe des Befehls telinit q
dazu gebracht werden, die Datei neu einzulesen. Ansonsten wird die Änderung erst nach dem nächsten Reboot wirksam. Es ist also die folgende Änderung vorzunehmen (unter SuSE 10.0; bei anderen Distributionen mag die Zeile geringfügig anders aussehen, ist aber analog anzupassen:
2:2345:respawn:/sbin/mingetty tty2
2:2345:respawn:ionice -c1 nice --19 /sbin/mingetty tty2
Die Shells führen mehrere Startdateien aus, insbesondere systemglobale und vom jeweiligen User zu modifizierende. Um auszuschließen, dass schon in den Startdateien irgendwas ist, was durch den Amok laufenden Prozess blockiert wird, setze ich den entsprechenden Code ganz an den Anfang der systemglobalen Datei. Das bringt das Problem mit sich, dass sie bei jedem Update der Distribution Gefahr läuft, überschrieben zu werden. Die Änderungen sind dann also erneut vorzunehmen – was man nur allzu leicht vergisst, wenn der Rechner dies nicht prüft und einen daran erinnert.
Aus /etc/profile:
*/bash) is=bash ;;
*/bash) is=bash if [ $(/bin/ps -o tty -p $$ | tail -n 1) = tty2 ] then if [ "$UID" -eq 0 ] then renice -19 -p $$ &>/dev/null ionice -c1 -p $$ &>/dev/null echo "This is the emergency root shell: highest CPU and I/O priority." echo "Keep that in mind." else type sudo &>/dev/null && sudo /sbin/ionice-c2 &>/dev/null renice 0 -p $$ &>/dev/null fi fi ;;
Das muss ggf. auch für andere Shells gemacht werden.
# /bin/ps a -o pid,tty,nice,args PID TT NI COMMAND 4895 tty7 0 /usr/X11R6/bin/X -br :0 vt7 -auth /var/lib/xdm/authdir/authfiles/A:0-eRE8qA 6035 tty1 0 /sbin/mingetty --noclear tty1 6039 tty2 -19 /sbin/mingetty tty2 6043 tty3 0 /sbin/mingetty tty3 6045 tty4 0 /sbin/mingetty tty4 6047 tty5 0 /sbin/mingetty tty5 6051 tty6 0 /sbin/mingetty tty6 # ionice -p 6039 realtime: prio 4
Und nach dem Login:
# /bin/ps -t tty2 -o pid,tty,nice,args PID TT NI COMMAND 16391 tty2 -19 -bash # ionice -p 16391 realtime: prio 4
Es könnte sinnvoll sein, auch den X-Server mit höherer Priorität laufen zu lassen, damit der die Umschaltung schnell hinbekommt.