![]() |
![]() |
|
15.4.3 Varianten der Sicherungen
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Vollsicherung – dabei werden alle zu sichernden Daten vollständig gesichert. Der Vorteil ist, dass man jederzeit ohne größeren Aufwand die gesicherten Daten wieder zurückladen kann. Man sollte allerdings bedenken, ob man bestimmte Daten bei einer Vollsicherung ausgrenzen sollte – besonders die sicherheitsrelevanten. Der Nachteil daran ist ganz klar: Eine Vollsicherung kann eine ganz schöne Menge an Platz (und auch Zeit) auf einem Speichermedium verbrauchen. |
| Inkrementelle Sicherung – hierbei wird nur einmal eine Vollsicherung vorgenommen. Anschließend werden immer nur diejenigen Daten gesichert, die sich seit der letzten Sicherung verändert haben. Hierbei wird weniger Platz auf einem Speichermedium (und auch Zeit) benötigt. |
Hierzu einige kurze Vorschläge, wie man bestimmte Bereiche sinnvoll sichert.
| Einzelne Dateien – einzelne Dateien kann man mal schnell mit cp oder scp auf eine andere Festplatte, Diskette oder ein anderes Verzeichnis übertragen. Natürlich steht Ihnen hierzu auch die Möglichkeit mittels tar, afio oder cpio zur Verfügung, um die Daten auf externe Datenträger zu sichern. Gewöhnlich werden diese Archive auch noch mittels gzip oder bzip2 komprimiert. Gern werden hierzu auch Datenträger wie CD oder DVD verwendet. |
| Dateibäume – ganze Dateibäume beinhalten häufig eine Menge Daten. Hier verwendet man als Speichermedium häufig Streamer, Magnetbänder oder optische Datenträger (CD, DVD), je nach Umfang. Als Werkzeuge werden gewöhnlich tar, afio und cpio eingesetzt. Aber auch Programme zur Datensynchronisation wie rsync oder unison werden oft genutzt. Zum Sichern auf optische Speichermedien wie CD oder DVD werden gewöhnlich die Tools mkisofs, (oder mit GUI) xcdroast, K3b oder gtoaster verwendet. |
| Ganze Festplatte – zum Sichern ganzer Festplatten verwendet man unter Linux häufig das Programmpaket amanda (Advanced Maryland Automatic Network Disk Archiver), das ein komplettes Backup-System zur Verfügung stellt. Da es nach dem Client-Server-Prinzip arbeitet, ist somit auch eine Datensicherung über das Netzwerk möglich. Der Funktionsumfang von amanda ist gewaltig, weshalb ich hier auf die Webseite http://www.amanda.org. |
| Dateisysteme – mithilfe des Kommandos dd lässt sich ein komplettes Dateisystem auf eine andere Platte oder auf ein Band sichern. Beachten Sie allerdings, dass beim Duplizieren beide Partitionen die gleiche Größe haben müssen (falls Sie Festplatten duplizieren wollen) und bestenfalls beide Platten nicht gemountet sind (zumindest nicht die Zielplatte). Da dd selbst physikalisch Block für Block kopiert, kann das Tool nicht auf defekte Blöcke überprüfen. Daher sollte man hierbei auch gleich noch mit dem Kommando badblocks nach defekten Blöcken suchen. Natürlich müssen Sie auch beim Zurückspielen darauf achten, dass die Zielpartition nicht kleiner als die Quellpartition ist. Ein anderes Tool, das auch auf Low-Level-Ebene und fehlertolerant arbeitet, ist dd_rescue. |
| Ein weiteres hervorragendes Tool zum Sichern und Wiederherstellen ganzer Partitionen ist partimage, welches auch wie dd und dd_rescue in der Lage ist, unterschiedliche Dateisysteme zu sichern (ext2/ext3; reiserfs, xfs, UFS (Unix), HFS (MAC), NTFS/FAT16/FAT32 (Win32)), da es wie die beiden anderen genannten Tools auf Low-Level-Ebene arbeitet. Mehr zu partimage entnehmen Sie bitte http://www.partimage.org. Natürlich bietet sich Ihnen auch die Möglichkeit, Dateisysteme zu synchronisieren. Hierbei stehen Ihnen Werkzeuge wie rsync, unision, WebDAV usw. zur Verfügung. | |
Das Sichern von Dateien zwischen Servern ist eigentlich mit dem Kommando scp recht einfach:
scp some-archive.tgz user@host:/home/backups
Nachteile von scp beim Durchlaufen ganzer Verzeichnisbäume (mit der Option –r) sind die vielen Kommandoaufrufe (alles wird einzeln kopiert) und die unflexiblen Kompressionsmöglichkeiten.
Hierzu wird in der Praxis oft tar verwendet. Verknüpfen wir nun tar mit ssh, haben wir exakt das, was wir wollen. Wenn Sie nämlich ssh ohne eine interaktive Login-Sitzung starten, erwartet ssh Daten von der Standardeingabe und gibt das Ergebnis auf die Standardausgabe aus. Das hört sich stark nach der Verwendung einer Pipe an. Wollen Sie beispielsweise alle Daten aus Ihrem Heimverzeichnis auf einem entfernten Rechner archivieren, können Sie wie folgt vorgehen:
tar zcvf – /home | ssh user@host "cat > homes.tgz"
Natürlich ist es möglich, das komprimierte Archiv auch auf ein Magnetband des entfernten Rechners zu schreiben (entsprechendes Medium und Rechte vorausgesetzt):
tar zcvf – /home | ssh user@host "cat > /dev/tape"
Wollen Sie stattdessen eine Kopie einer Verzeichnisstruktur auf Ihrer lokalen Maschine direkt auf das Filesystem einer anderen Maschine kopieren, so können Sie dies so erreichen (Sie synchronisieren das entfernte Verzeichnis mit dem lokalen):
cd /home/us10129/www.pronix.de ; tar zcf – html/ \ | ssh user@host \ "cd /home/us10129/www.pronix.de; mv html html.bak; tar zpxvf -"
Hier sichern Sie u. a. auch das Verzeichnis html auf host, indem Sie es umbenennen (html.bak) – für den Fall der Fälle. Dann erstellen Sie eine exakte Kopie von /home/us10129/www.pronix.de/html – Ihrem lokalen Verzeichnis – mit sämtlichen identischen Zugriffsrechten und der Verzeichnisstruktur auf dem entfernten Rechner. Da hierbei tar mit der Option z verwendet wird, werden die Daten vor dem »Hochladen« komprimiert, was natürlich bedeutet, dass eine geringere Datenmenge transferiert werden muss und der Vorgang erheblich schneller vonstatten gehen kann. Natürlich ist dies abhängig von der Geschwindigkeit beider Rechner, also wie schnell bei diesen die (De-)Kompression durchgeführt werden kann.
Müssen Sie auf dem entfernten Rechner etwas wiederherstellen und verfügen über ein Backup auf der lokalen Maschine, ist dies mit folgender Kommandoverkettung kein allzu großes Unterfangen mehr:
ssh user@host "cd /home/us10129/www.pronix.de; tar zpvxf -" \ < big-archive.tgz
So stellen Sie das komplette Verzeichnis /home/us10129/www.pronix.de/ mit dem Archiv big-archive.tgz wieder her. Gleiches können Sie natürlich auch jederzeit in die andere Richtung vornehmen:
ssh user@host "cat big-archive.tgz" | tar zpvxf -
Damit Sie nicht andauernd ein Passwort eingeben müssen, empfiehlt es sich auch hier, SSH-Schlüssel zu verwenden (siehe Abschnitt 14.12.12). Das folgende Script demonstriert Ihnen die Möglichkeit, ssh und tar in einem Backup-Script zu verwenden.
#!/bin/sh
# Name: ssh_tar
# Backups mit tar über ssh
# Konfiguration, entsprechend anpassen
#
SSH_OPT="-l"
SSH_HOST="192.135.147.2"
SSH_USER="jwolf"
# Default-Angaben
#
LOCAL_DIR="/home/tot/backups"
REMOTE_DIR="/home/jwolf/backups"
stamp=`date +%d_%m_%Y`
BACKUP_FILE="backup_${stamp}.tgz"
usage() {
echo "usage: star [-ph] [-pl] [-sh] [-sl] [-r] [-l] ..."
echo
echo "Optionen : "
echo " –ph : (lokales) Verzeichnis packen und hochladen " \
" (remote) in 'REMOTE_DIR'"
echo " Beispiel: star -ph lokalesVerzeichnis "
echo " -pl = (remote) Verzeichnis packen und runterladen"\
" (lokal) in 'LOCAL_DIR'"
echo " Beispiel: star -pl remoteVerzeichnis "
echo " -sh = Synchronisiert ein Host-Verzeichnis mit einem "\
"lokalen Verzeichnis"
echo " Beispiel: star -sh lokalesVerzeichnis "\
"remoteVerzeichnis syncVerzeichnis "
echo " -sl = Synchronisiert ein lokales Verzeichnis mit "\
"einem Host-Verzeichnis"
echo " Beispiel: star -sl remoteVerzeichnis "\
"lokalesVerzeichnis syncVerzeichnis "
echo " -r = (remote) Wiederherstellen eines"\
" Host-Verzeichnisses"
echo " Beispiel: star -r remoteVerzeichnis "\
"lokalTarArchiv.tgz"
echo " -l = (lokal) Wiederherstellen eines lokalen "\
"Verzeichnisses"
echo " Beispiel: star -l lokalesVerzeichnis "\
"remoteTarArchiv.tgz"
# ...
exit 1
}
case "$1" in
-ph)
if [ $# -ne 2 ]
then
usage
else
cd $2; tar zcvf – "." | \
ssh $SSH_OPT $SSH_USER $SSH_HOST \
"cat > ${REMOTE_DIR}/${BACKUP_FILE}"
echo "Verzeichnis '$2' nach "\
"${SSH_HOST}:${REMOTE_DIR}/${BACKUP_FILE} "\
"gesichert"
fi ;;
-pl)
if [ $# -ne 2 ]
then
usage
else
ssh $SSH_OPT $SSH_USER $SSH_HOST \
"cd $2; tar zcvf – ." | \
cat > ${LOCAL_DIR}/${BACKUP_FILE}
echo "Verzeichnis ${SSH_HOST}:${2} nach "\
"${LOCAL_DIR}/${BACKUP_FILE} gesichert"
fi ;;
-sh)
if [ $# -ne 4 ]
then
usage
else
cd $2
tar zcf – $4/ |
ssh $SSH_OPT $SSH_USER $SSH_HOST \
"cd $3; mv $4 ${4}.bak; tar zpxvf -"
echo "Verzeichnis ${2}/${4} mit"\
" ${SSH_HOST}:${3}/${4} synchronisiert"
fi ;;
-sl)
if [ $# -ne 4 ]
then
usage
else
cd $3; mv $4 ${4}.bak
ssh $SSH_OPT $SSH_USER $SSH_HOST "cd ${2}; tar zcvf – ${4}"\
| tar zpvxf -
echo "Verzeichnis ${SSH_HOST}:${2}/${4} mit"\
" ${3}/${4} synchronisiert"
fi ;;
-r)
if [ $# -ne 3 ]
then
usage
else
ssh $SSH_OPT $SSH_USER $SSH_HOST \
"cd ${2}; tar zpvxf -" < $3
echo "${SSH_HOST}:$2 mit dem Archiv $3 "\
"Wiederhergestellt"
fi ;;
-l)
if [ $# -ne 3 ]
then
usage
else
cd $2
ssh $SSH_OPT $SSH_USER $SSH_HOST "cat $3" | \
tar zpvxf -
echo "$2 mit dem Archiv ${SSH_HOST}:${3} "\
"Wiederhergestellt"
fi ;;
-*) usage;;
*) usage;;
esac
Das Script bei der Ausführung:
you@host > ./ssh_tar -ph Shellbuch_aktuell/ ./ ./kap004.txt ./kap005.txt ... ... ./Kap013.txt ./Kap014.txt Verzeichnis 'Shellbuch_aktuell/' nach 192.135.147.2:/home/jwolf/backups/backup_20_05_2005.tgz gesichert
Ein Blick zum Rechner »192.135.147.2«:
jwolf@jwolf$ ls backups/ backup_20_05_2005.tgz you@host > ./ssh_tar -pl backups/ ./ ./backup_20_05_2005.tgz ./kap004.txt ./kap005.txt ... ... ./Kap012.txt ./Kap013.txt ./Kap014.txt Verzeichnis 192.135.147.2:backups/ nach /home/you/backups/ backup_20_05_2005.tgz gesichert you@host > ls backups/ backup_07_05_2005.tgz backup_20_05_2005.tgz Shellbuch
Erstellt im Remoteverzeichnis backups ein Ebenbild des Verzeichnisses Shellbuch_aktuell aus dem Heimverzeichnis des lokalen Rechners:
you@host > ./ssh_tar -sh $HOME backups Shellbuch_aktuell Shellbuch_aktuell/ Shellbuch_aktuell/kap004.txt Shellbuch_aktuell/kap005.txt ... Shellbuch_aktuell/Kap013.txt Shellbuch_aktuell/Kap014.txt Verzeichnis /home/you/Shellbuch_aktuell mit 192.135.147.2:backups/Shellbuch_aktuell synchronisiert
Erstellt im lokalen Heimverzeichnis $HOME/backup eine exakte Kopie des entfernten Remote-Verzeichnisses backups/Shellbuch:
you@host > ./ssh_tar -sl backups $HOME/backups Shellbuch_aktuell Shellbuch_aktuell/ Shellbuch_aktuell/kap004.txt Shellbuch_aktuell/kap005.txt ... ... Shellbuch_aktuell/Kap013.txt Shellbuch_aktuell/Kap014.txt Verzeichnis 192.135.147.2:backups/Shellbuch_aktuell mit /home/tot/backups/Shellbuch_aktuell synchronisiert you@host > ls backups/ backup_07_05_2005.tgz backup_20_05_2005.tgz Shellbuch_aktuell Shellbuch_aktuell.bak you@host > ls backups/Shellbuch_aktuell Kap003.txt kap005.txt Kap007.txt Kap010.txt Kap013.txt ...
Wiederherstellen eines entfernten Verzeichnisses mit einem lokalen Archiv. Im Beispiel wird das entfernte Verzeichnis backups/Shellbuch_aktuell mit dem lokalen Archiv backup_20_05_2005.tgz wiederhergestellt:
you@host > ls backups/ backup_07_05_2005.tgz backup_20_05_2005.tgz Shellbuch_aktuell Shellbuch_aktuell.bak you@host > ./ssh_tar -r backups/Shellbuch_aktuell > backups/backup_20_05_2005.tgz ./ ./kap004.txt ./kap005.txt ... ... ./Kap013.txt ./Kap014.txt 192.135.147.2:backups/Shellbuch_aktuell mit dem Archiv backups/backup_20_05_2005.tgz wiederhergestellt
Dasselbe Beispiel in anderer Richtung. Hier wird das lokale Verzeichnis backups/Shellbuch_aktuell mit dem Archiv backup_20_05_2005.tgz, welches sich auf dem entfernten Rechner im Verzeichnis backups befindet, wiederhergestellt:
you@host > ./ssh_tar -l backups/Shellbuch_aktuell > backups/backup_20_05_2005.tgz ./ ./kap004.txt ./kap005.txt ... ... ./Kap013.txt ./Kap014.txt backups/Shellbuch_aktuell mit dem Archiv 192.135.147.2:backups/backup_20_05_2005.tgz wiederhergestellt
|
Hinweis Natürlich funktioniert dieses Script wie hier demonstriert nur mit einem Key-Login (siehe Abschnitt 14.12.12). Da Backup-Scripts aber ohnehin chronolgoisch laufen sollten, ist ein ssh-key immer sinnvoll, da man das Passwort nicht in einer Textdatei speichern muss. |
Was sich mit ssh und tar realisieren lässt, gelingt natürlich auch mit rsync. Das folgende einfache Script synchronisiert entweder ein lokales Verzeichnis mit einem entfernten Verzeichnis oder umgekehrt. Um hierbei auch die Vertraulichkeit zu gewährleisten, »tunnelt« man das Ganze durch ssh. Das folgende Script demonstriert Ihnen, wie Sie rsync zum komfortablen Synchronisieren zweier entfernter Verzeichnisse verwenden können.
#!/bin/sh
# ssyncron
# Script zum Synchronisieren von Daten
usage() {
echo "usage: prgname [-option] [Verzeichnis]"
echo
echo "-u : Ein Verzeichnis auf dem Server mit einem"\
" lokalen synchronisieren"
echo "-d : Ein lokales Verzeichnis mit einem Verzeichnis"\
" auf dem Server synchronisieren"
exit 1
}
# Konfigurationsdaten
#
# Pfad zu den Daten (Lokal)
local_path="$HOME/"
# Pfad zu den Dateien (Server)
remote_path="/home/us10129"
# Loginname
username="us10129@myhoster.de"
# Optionen zum Download '-d'
D_OPTIONS="-e ssh -av --exclude '*.xvpics' --exclude 'cache' --exclude 'bestellen'"
# Optionen zum Hochladen '-u'
U_OPTIONS="-e ssh -av"
# rsync vorhanden ...
if [ `which rsync` = "" ]
then
echo "Das Script benötigt 'rsync' zur Ausführung ...!"
exit 1
fi
# Pfad zu rsync
RSYNC=`which rsync`
site=$2
case "$1" in
# Webseite herunterladen – Synchronisieren Lokal mit Server
-d)
[ -z $2 ] && usage # Verzeichnis fehlt ...
$RSYNC $D_OPTIONS \
$username:${remote_path}/${site}/ ${local_path}${site}/ ;;
# Webseite updaten – Synchronisieren Server mit Lokal
-u)
$RSYNC $U_OPTIONS \
${local_path}${site}/ $username:${remote_path}/${site}/ ;;
-*)
usage ;;
*)
usage ;;
esac
Das Script bei der Ausführung:
Entferntes Verzeichnis mit dem lokalen Verzeichnis synchronisieren:
you@host > ./ssyncron -d backups/Shellbuch receiving file list ... done ./ Martin/ Kap001.doc Kap001.sxw Kap002.sxw Kap003.txt Kap007.txt ... ... Martin/Kap001.doc Martin/Kap002.sxw Martin/Kap003.sxw Martin/Kap004.sxw Martin/Kap005.sxw kap004.txt kap005.txt newfile.txt whoami.txt wrote 516 bytes read 1522877 bytes 38566.91 bytes/sec total size is 1521182 speedup is 1.00
Eine neue lokale Datei atestfile.txt erzeugen und in das entfernte Verzeichnis synchronisieren:
you@host > touch backups/Shellbuch/atestfile.txt you@host > ./ssyncron -u backups/Shellbuch building file list ... done Shellbuch/ Shellbuch/atestfile.txt wrote 607 bytes read 40 bytes 86.27 bytes/sec total size is 1521182 speedup is 2351.13
Einige Dateien im lokalen Verzeichnis Shellbuch löschen (Datenverlust simulieren) und anschließend mit dem entfernten Verzeichnis Shellbuch wiederherstellen (synchronisieren):
you@host > rm backups/Shellbuch/Kap00[1–9]* you@host > ./ssyncron -d backups/Shellbuch receiving file list ... done ./ Kap001.doc Kap001.sxw Kap002.sxw Kap003.txt Kap007.txt Kap008.txt Kap009.txt wrote 196 bytes read 501179 bytes 28650.00 bytes/sec total size is 3042364 speedup is 6.07
Wenn in beiden Richtungen nichts mehr zu tun ist, dann ist alles synchronisiert:
you@host > ./ssyncron -u backups/Shellbuch building file list ... done wrote 551 bytes read 20 bytes 87.85 bytes/sec total size is 1521182 speedup is 2664.07 you@host > ./ssyncron -d backups/Shellbuch receiving file list ... done wrote 56 bytes read 570 bytes 96.31 bytes/sec total size is 1521182 speedup is 2430.00
|
Hinweis In der Praxis würde es sich außerdem anbieten, rsync mit den Optionen -b für Backup zu verwenden, womit Backup-Kopien alter Dateiversionen angelegt werden, sodass man gegebenenfalls auf mehrere Versionen zurückgreifen kann, und die Option -z zu nutzen, mit der Kompression möglich ist. Hinweis Hier gilt dasselbe wie schon beim Script zuvor. Hier sollten Sie ebenfalls einen ssh-key für ein Key-Login verwenden (siehe Abschnitt 14.12.12). |
Sie wollen sich ein Backup mit cpio erstellen und es sich automatisch zukommen lassen. Als einfachster Weg würde sich hier der Transfer per E-Mail als Anhang eignen. Dank megabyteschwerer Postfächer sollte dies heutzutage kein Problem mehr sein. Allerdings lässt sich ein Anhang nicht einfach so hinzufügen. Hierzu benötigen Sie uuencode (siehe Abschnitt 14.12.6). Zuerst müssen Sie also cpio-typisch ein komplettes Verzeichnis durchlaufen und die Ausgabe gefundener Dateien (mit find) durch eine Pipe an cpio übergeben. Damit daraus eine einzige Datei als Anhang wird, schickt cpio wiederum die Ausgabe durch die Pipe an gzip, um das vollständige Verzeichnis zu komprimieren. Diesen »gzipten« Anhang müssen Sie nun mit uuencode enkodieren, um ihn daraufhin mit mail oder mailx (oder ggf. mit sendmail) an den gewünschten Absender zu schicken. Alle diese Aktionen werden durch eine Pipe an das andere Kommando geschickt:
find "$Dir" -type f -print |
cpio -o${option} |
gzip |
uuencode "$Archive" |
$Mail -s "$Archive" "$User" || exit 1
Hierzu das komplette Script:
#!/bin/sh
# Name: mailcpio
# Archiviert Dateien und Verzeichnisse per cpio, komprimiert mit
# gzip und verschickt das Archiv an eine bestimmte E-Mail-Adresse
PROGN="$0"
# Benötigte Programme: mail oder mailx...
if [ "`which mailx`" != "" ]
then
Mail="mailx"
if [ "`which mail`" != "" ]
then
Mail="mail"
fi
else
echo "Das Script benötigt 'mail' bzw. 'mailx' zur Ausführung!"
exit 1
fi
# Benötigt 'uuencode' für den Anhang
if [ "`which uuencode`" = "" ]
then
echo "Das Script benötigt 'uuencode' zur Ausführung!"
exit 1
fi
# Benötigt 'cpio'
if [ "`which cpio`" = "" ]
then
echo "Das Script benötigt 'cpio' zur Ausführung!"
exit 1
fi
Usage () {
echo "$PROGN – Versendet ganze Verzeichnisse per E-Mail"
echo "usage: $PROGN [option] e-mail-adresse"\
" {datei|Verzeichnis} [datei|Verzeichnis] ..."
echo
echo "Hierbei werden alle angegebenen Dateien und "\
"Verzeichnisse (inskl. Unterverzeichnisse)"
echo "an eine angegebene Mail-Adresse gesendet. Das"\
" Archiv wird mittels gzip komprimiert."
echo "Option:"
echo "-s : Keine Ausgabe von cpio"
echo "-v : Macht cpio gesprächig"
exit 1
}
while [ $# -gt 0 ]
do
case "$1" in
-v) option=Bv ;;
-s) Silent=yes ;;
--) shift; break ;;
-*) Usage ;;
*) break ;;
esac
shift
done
if [ $# -lt 2 ]
then
Usage
fi
User="$1"; shift
for Dir
do
Archive="${Dir}.cpio.gz"
# Verzeichnis nicht lesbar ...
if [ ! -r "$Dir" ]
then
echo "Kann $Dir nicht lesen – (wird ignoriert)"
continue
fi
[ "$Silent" = "" ] && echo "$Archive -> "
find "$Dir" -type f -print |
cpio -o${option} |
gzip |
uuencode "$Archive" |
$Mail -s "$Archive" "$User" || exit 1
done
Das Script bei der Ausführung:
you@host > ./mailcpio-s pronix@t-online.de logfiles 3 blocks you@host > ./mailcpio -v pronix@t-online.de logfiles logfiles.cpio.gz -> logfiles/testscript.log.mail logfiles/testscript.log 1 block
Wenn der Kernel gestartet wurde, kann dieser vorerst nur im Lese-Modus auf die Root-Partition zugreifen. Als ersten Prozess startet der Kernel init (/sbin/init) mit der PID 1. Dieser Prozess gilt ja als Elternteil aller weiteren Prozesse, die noch gestartet werden. Der Prozess init kümmert sich zunächst um die Konfiguration des Systems und den Start von zahlreichen Daemon-Prozessen.
|
Hinweis Es muss gleich darauf hingewiesen werden, dass sich über init keine hundertprozentigen Aussagen treffen lassen. Hier kochen die jeweiligen Distributionen häufig Ihr eigenes Süppchen. Die Unterschiede beziehen sich wieder insbesondere auf diejenigen Verzeichnisse, in denen sich die Init-Dateien befinden, und auf die hierbei berücksichtigten Konfigurationsdateien. Natürlich heißt dies auch, dass die Init-Pakete verschiedener Distributionen gewöhnlich gänzlich inkompatibel sind und nicht untereinander ausgetauscht werden können. Daher folgt hier zunächst ein allgemeiner Überblick über den Init-Prozess (genauer System-V-init). |
Bevor hier ein wenig ins Detail gegangen wird, zunächst ein kurzer Init-Überblick über einen normalen Systemstart:
| Nach dem Systemstart, wenn der Kernel geladen wurde, startet dieser das Programm (besser den Prozess) /sbin/init mit der PID 1. |
| init wertet zunächst die Konfigurationsdatei /etc/inittab aus. |
| Jetzt führt init ein Script zur Systeminitialisierung aus. Name und Pfad des Scripts sind stark distributionsabhängig. |
| Als Nächstes führt init das Script rc aus, welches sich auch an unterscheidlichen Orten (und eventuell unter verschiedenen Namen) auf den Distributionen befindet. |
| rc startet nun einzelne Scripts, die sich in einem Verzeichnis namens rc[n].d befinden. n ist hierbei der Runlevel. Diese Scriptdateien in den Verzeichnissen rc[n].d starten nun die Systemdienste (Daemonen), auch Startup-Scripts genannt. Der Speicherort dieser Verzeichnisse ist distributionsabhängig. Für gewöhnlich finden Sie die Verzeichnisse unter /etc oder unter /etc/init.d. |
Normalerweise verwendet init sieben Runlevel, die jeweils eine Gruppe von Diensten enthalten, die das System beim Starten (oder Beenden) ausführen soll. Sicherlich haben Sie schon davon gehört, dass Linux/UNIX ein Multi-User-Betriebssystem ist, also im Multi-User-Modus läuft. Es ist aber auch möglich, dass Sie Linux/UNIX im Single-User-Modus starten. Dass dies überhaupt realisiert werden kann, ist den verschiedenen Runlevel zu verdanken.
In der Datei /etc/inittab wird unter Linux der »default runlevel« festgelegt, es ist stark distributionsabhängig. Welcher Runlevel welche Dienste startet, ist von »Symlinks« in den einzelnen Verzeichnissen rc[n].d abhängig. Diese »Symlinks« zeigen meist auf die Startscripts der Dienste, die im Allgemeinen unter /etc/init.d abgelegt sind.
Zunächst ein kurzer Überblick zu den unterschiedlichen Runleveln und ihren Bedeutungen bei den gängigsten Distributionen:
| Runlevel | Bedeutung |
| 0 | Dieser Runlevel hält das System komplett an (Shutdown mit Halt). |
| 1 oder S | Single-User-Modus (Einzelbenutzer-Modus) |
| 2 oder M | Multi-User-Modus (Mehrbenutzer-Modus) ohne Netzwerk |
| 3 | Multi-User-Modus (Mehrbenutzer-Modus) mit einem Netzwerk, aber ohne X–Start |
| 4 | Dieser Runlevel wird gewöhnlich nicht verwendet und steht somit zur freien Verfügung. |
| 5 | Multi-User-Modus (Mehrbenutzer-Modus) mit einem Netzwerk und einem grafischen Login (X-Start). Nach dem Login wird gewöhnlich die grafische Oberfläche gestartet. |
| 6 | Dieser Runlevel startet das System neu (Shutdown mit Reboot). |
Wie Sie sehen konnten, handelt es sich bei den Runleveln 0 und 6 um spezielle Fälle, in denen sich das System nicht lange halten kann. Hierbei wird das System heruntergefahren (Runlevel 0) oder eben neu gestartet (Runlevel 1). Zumeist werden die Runlevel 2 und 3 und die Mehrbenutzer-Level l und 5 verwendet, womit eine X-Anmeldeprozedur (wie xdm, kdm, gdm etc.) gestartet wird. Runlevel 1 (bzw. S) ist für die meisten Systeme unterschiedlich definiert und Runlevel 4 wird fast nie benutzt.
|
Hinweis Linux unterstützt übrigens 10 Runlevel, wobei die Runlevel 7 bis 9 nicht definiert sind. |
Im Runlevel 1, dem Einzelbenutzer-Modus, werden meist alle Mehrbenutzer- und Anmeldeprozesse beendet. Somit ist sicher, dass das System mit geringem Aufwand ausgeführt wird. Natürlich bietet Runlevel 1 vollen root-Zugriff auf das System. Damit ein System in Runlevel 1 auch nach einem root-Passwort abfragt, wurde der Runlevel S entwickelt. Unter System-V-init existiert kein echter Runlevel S und er dient daher nur dazu, das root-Passwort abzufragen. Dieser Runlevel ist gewöhnlich dazu gedacht, dass Administratoren diverse Patches einspielen können.
In der Datei /etc/inittab steht, was init auf den verschiedenen Runleveln zu tun hat. Wenn der Rechner gestartet wird, durchläuft init Runlevel 0 bis hin zum Runlevel, der in /etc/inittab als Standard (default runlevel) festgelegt wurde. Damit der Übergang von einem Level zum nächsten reibungslos läuft, führt init die in /etc/inittab angegebenen Aktionen aus. Dasselbe geschieht natürlich auch im umgekehrten Fall beim Herunterfahren bzw. Neustarten des Systems.
Die Verwendung von inittab ist allerdings nicht unbedingt das Gelbe vom Ei, weshalb noch zusätzliche Schichten in Form eines Scripts für das Wechseln der Runlevel eingebaut wurden. Dieses Script (rc – zu finden meist unter /etc/init.d/rc oder /etc/rc.d/rc) wird gewöhnlich aus inittab aufgerufen. Es (rc) führt wiederum weitere Scripts in einem vom Runlevel abhängigen Verzeichnis aus, um das System in seinen neuen (Runlevel-)Zustand zu versetzen.
In vielen Büchern wird jetzt hier die Datei /etc/inittab etwas genauer zerlegt und beschrieben (bspw. inittab-Schlüsselwörter), was natürlich sehr lehrreich ist, doch in der Praxis müssen Sie sich als Systemadministrator eigentlich nicht damit befassen, da die eben erwähnte Schnittstelle für jede Anwendung geeignet ist.
Die Terminologie von Startup-Scripts ist häufig nicht einfach zu durchschauen, weshalb hier ein Beispiel gegeben werden soll. Gewöhnlich finden Sie die Hauptkopien der Startup-Scripts im Verzeichnis /etc/inid.d.
you@host > ls -l /etc/init.d/ insgesamt 308 -rwxr-xr-x 1 root root 2570 2005–03–02 18:45 acpid -rwxr-xr-x 1 root root 1098 2005–02–24 10:29 acpi-support -rwxr-xr-x 1 root root 11038 2005–03–25 23:08 alsa -rwxr-xr-x 1 root root 1015 2004–11–26 12:36 anacron -rwxr-xr-x 1 root root 1388 2005–03–01 04:11 apmd -rwxr-xr-x 1 root root 1080 2005–02–18 11:37 atd -rw-r--r-- 1 root root 2805 2005–01–07 19:35 bootclean.sh -rwxr-xr-x 1 root root 1468 2005–01–07 19:36 bootlogd -rwxr-xr-x 1 root root 1371 2005–01–07 19:35 bootmisc.sh -rwxr-xr-x 1 root root 1316 2005–01–07 19:35 checkfs.sh -rwxr-xr-x 1 root root 7718 2005–01–07 19:35 checkroot.sh -rwxr-xr-x 1 root root 5449 2004–12–26 14:12 console-screen.sh -rwxr-xr-x 1 root root 1168 2004–10–29 18:05 cron ...
Jedes dieser Scripts ist für einen Daemon oder einen anderen Aspekt des Systems verantwortlich. Und jedes dieser Scripts verarbeitet die Argumente »start« und »stop«, womit Sie den entsprechenden Dienst initialisieren oder beenden können, zum Beispiel:
# /etc/init.d/cron * Usage: /etc/init.d/cron start|stop|restart|reload|force-reload
Hier haben Sie versucht, das Script »cron«, welches für die Ausführung und Beendung des cron-Daemons verantwortlich, ist aufzurufen. Sie bekommen hierbei die möglichen Argumente mitgegeben, wie Sie das Script aufrufen können. Neben »start« und »stop« finden Sie häufig auch noch »restart«, was im Prinzip dasselbe bewirkt, wie ein »stop« mit anschließendem »start«. Des Weiteren findet man gewöhnlich auch eine Option »reload«, die den Dienst nicht beendet, sondern ihn auffordert, seine Konfiguration neu einzulesen (meist per Signal SIGHUP).
Im folgenden Beispiel soll das Script »sleep_daemon« beim Systemstart automatisch gestartet und beim Beenden wieder automatisch beendet werden. Hier das Script:
#!/bin/sh # Name : sleep_daemon sleep 1000 &
Das Script macht nichts anderes, als einen »schlafenden Dämon« zu erzeugen. Neben einfachen Shellscripts können Sie in der Praxis natürlich jedes andere Programm – sei es nun ein Binary oder ein Script – in beliebiger Sprache ausführen lassen. Tatsächlich können Sie alle Shellscripts in diesem Buch dazu verwenden (ob sinnvoll oder nicht). Dieses Script »sleep_daemon« habe ich nun in das Verzeichnis /usr/sbin verschoben und natürlich entsprechende Ausführrechte (für alle) gesetzt. Für diesen Vorgang werden Sie wohl root-Rechte benötigen. Alternativ können Sie auch das Verzeichnis /usr/local/sbin verwenden.
Folgendermaßen sieht nun das Startup-Script aus, womit Sie »sleep_daemon« starten, beenden und neu starten können.
#!/bin/sh
# Name : sleep_daemon
DAEMON="/usr/sbin/sleep_daemon"
test -f $DAEMON || exit 0
case "$1" in
start)
echo -n "Starte sleep_daemon"
$DAEMON
echo "."
;;
stop)
echo -n "Stoppe sleep_daemon"
killall sleep
echo "."
;;
restart)
echo -n "Stoppe sleep_daemon"
killall sleep
echo "."
echo -n "Starte sleep_daemon"
$DAEMON
echo "."
;;
# Hierzu wird auch gern folgende Sntax eingesetzt:
# $0 stop
# $0 start;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
Ich habe hier denselben Namen verwendet, was Sie in der Praxis nicht tun müssen. Dieses Startup-Script können Sie nun in das Verzeichnis /etc/init.d verschieben und müssen es auch wieder ausführbar machen. Theoretisch können Sie jetzt schon den Dienst von Hand starten bzw. beenden:
# /etc/init.d/sleep_daemon start Starte sleep_daemon. # /etc/init.d/sleep_daemon restart Stoppe sleep_daemon. Starte sleep_daemon. # /etc/init.d/sleep_daemon stop Stoppe sleep_daemon.
Damit unser Dienst auch automatisch beim Eintreten bzw. Austreten eines bestimmten Runlevels gestartet bzw. beendet wird, benötigt das von init gestartete Master-Controll-Script (rc) zusätzliche Informationen, welche Scripts ausgeführt werden sollen. Denn anstatt im Verzeichnis /etc/init.d nachzublättern, wann bei welchem Runlevel ein Script gestartet werden muss, sieht das Master-Controll-Script in einem Verzeichnis namens rc[n].d (bspw. rc1.d; rc2.d; ... rc6.d) nach. n steht für den Runlevel, in den es gelangen will. Zum Beispiel hier unter »Ubuntu Linux« im Verzeichnis rc2.d:
# ls -l /etc/rc2.d/ lrwxrwxrwx 1 root root 17 K11anacron -> ../init.d/anacron lrwxrwxrwx 1 root root 17 S05vbesave -> ../init.d/vbesave lrwxrwxrwx 1 root root 18 S10sysklogd -> ../init.d/sysklogd lrwxrwxrwx 1 root root 15 S11klogd -> ../init.d/klogd lrwxrwxrwx 1 root root 14 S12alsa -> ../init.d/alsa lrwxrwxrwx 1 root root 13 S14ppp -> ../init.d/ppp lrwxrwxrwx 1 root root 16 S19cupsys -> ../init.d/cupsys lrwxrwxrwx 1 root root 15 S20acpid -> ../init.d/acpid lrwxrwxrwx 1 root root 14 S20apmd -> ../init.d/apmd ...
Sie können gleich erkennen, dass diese Einträge in rc[n].d gewöhnlich symbolische Links sind, die auf die Startup-Scripts im init.d-Verzeichnis verweisen. Wenn Sie die anderen Runlevel-Verzeichnisse ebenfalls ansehen, werden Sie feststellen, dass hierbei alle Namen der symbolischen Links entweder mit einem »S« oder einen »K«, gefolgt von einer Nummer und dem eigentlichen Dienst beginnen (bspw. S14alsa). Auch dies ist recht schnell erklärt. Steigt init von einem Runlevel in den nächst höheren Level auf, werden alle Scripts mit »S« beginnend ausgeführt. Diese Scripts werden also mit dem Argument »start« ausgeführt. Wenn init hingegen von einem höheren Runlevel in einen niedrigeren wechselt, werden alle Scripts mit »K« (kill) beginnend ausgeführt. Hierbei wird gewöhnlich das Script mit dem Argument »stop« ausgeführt. Die Nummern haben eine Art Prioritätsbedeutung. Die Scripts im Runlevel-Verzeichnis werden bei der Option »start« in alphabetischer und bei »stop« in umgekehrter Reihenfolge ausgeführt. Somit bedient man sich einer Nummerierung, um die Reihenfolge der Ausführung zu beeinflussen.
Jetzt wollen Sie natürlich auch Ihr Startup-Script hinzufügen. Um also dem System mitzuteilen, dass Sie einen Daemon starten wollen, müssen Sie ebenfalls einen symbolischen Link in das entsprechende Verzeichnis setzen. Die meisten Dienste starten Ihre Dämonen im Runlevel 2, weshalb hier ebenfalls ein Eintrag vorgenommen wird. Um den Daemon auch ordentlich wieder zu beenden, müssen Sie natürlich auch einen Link im Runlevel 0 eintragen. Da es bei einigen Systemen Unterschiede zwischen Shutdown und Reboot gibt, sollten Sie auch einen Eintrag im Runlevel 6 erstellen, um auf Nummer sicher zu gehen, dass sich der Daemon beim Neustart korrekt beendet hat.
# ln -s /etc/init.d/sleep_daemon /etc/rc2.d/S23sleep_daemon # ln -s /etc/init.d/sleep_daemon /etc/rc0.d/K23sleep_daemon # ln -s /etc/init.d/sleep_daemon /etc/rc6.d/K23sleep_daemon
Mit der ersten Zeile weisen Sie das System nun an, das Startup-Script /etc/init.d/sleep_daemon mit dem Argument »start« auszuführen, wenn es im Runlevel 2 angelangt ist. Mit der zweiten Zeile legen Sie fest, dass /etc/init.d/sleep_daemon beim Herunterfahren des Systems mit dem Argument »stop« beendet wird, wenn es im Runlevel 0 angekommen. ist. Gleiches nehmen Sie auch mit der dritten Zeile vor, nur eben für den Neustart des Systems in Runlevel 6.
Wenn Sie jetzt das System beenden und wieder hochfahren, können Sie in der Startup-Sitzung (sofern diese sichtbar ist) Ihren Dienst beim Starten beobachten. Hier werden Sie irgendwann ein Zeile wie
Starte sleep_daemon.
finden. Beim Beenden bzw. Neustarten des Systems entsteht diese Meldung, nur dass eben der »sleep_daemon« beendet wurde.
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.
| << zurück |
|
||||||||||||
|
||||||||||||
|
||||||||||||
Copyright © Rheinwerk Verlag GmbH 2005
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.