logoOL.gif
user_gelb_schwarz_or.gif
logoUL.gif
logoUR.gif claim.gif
LinuxUser LinuxCommunity EasyLinux Linux-Magazin International
      Anzeige
TFT Monitor bei Mercateo kaufen.
Neues Netbook? Ein Preisvergleich lohnt sich.
Bei uns finden sie Notebooks, PDAs und Drucker mit Testberichten und Tipps.
Diamant Buchhaltungssoftware – transparent und detailliert auch für die Konzernbuchhaltung.
Günstige Shareware Programme als direkte Downloads im Software Portal.
Bis zu 70% sparen durch Preisvergleich.
      Anzeige

Erschienen in LinuxUser 02/2006   »   Ausgabe bestellen

Dateitransfers automatisieren

Freihändig


Immer wieder dieselbe langweilige Kombination aus Usernamen und Passwort zu tippen, kann auf Dauer ganz schön ermüden. Bei FTP-Downloads spart die textbasierte Makrosprache eine Menge Tipparbeit.

David Tansley

README

Der Standard-FTP-Client lässt sich mit Textbefehlen skripten. Im Zusammenspiel mit Shell-Skripts automatisieren Sie damit regelmäßige Dateitransfers.

Der De-facto-Standard für die Übertragung von Dateien via Internet heißt FTP (File Transfer Protocol). Das Protokoll existiert schon seit vielen Jahren, und obwohl es nicht besonders sicher ist, hat es aufgrund seiner Robustheit und Beliebtheit wohl noch eine lange Zukunft vor sich. Dieser Artikel verrät, wie Sie mit Hilfe eines Skripts eine Verbindung zu FTP-Servern aufbauen und Dateien herunterladen können.

.netrc richtig eingesetzt

Egal, ob Sie FTP im Batch- oder interaktiven Modus verwenden: Eine automatische Anmeldung bei der Gegenstelle spart das lästige Eintippen von Username und Passwort. Dafür sorgt eine Datei namens .netrc in Ihrem Home-Verzeichnis. Stellen Sie die Berechtigungen für .netrc auf Lesen/Schreiben nur für den Dateibesitzer (chmod 600): Benutzernamen und Passworte lagern dort im Klartext.

Die Datei kann mehrere Einträge für Remote-Sites enthalten. Sobald Sie eine .netrc besitzen und einen FTP-Befehl für eine dort aufgeführte Maschine eingeben, greift FTP auf den Benutzernamen und das Passwort des Eintrags zurück.

Die Einträge in der .netrc müssen in keinem bestimmten Format vorliegen; Sie können die einzelnen Informationen können wahlweise durch Leerzeichen, Tabulatoren oder Zeilenumbrüche trennen. Recht übersichtlich fällt aber die Variante unter Verwendung von Zeilenumbrüchen aus:

machine RemoteHost
        login LoginName
        password Passwort
        password PasswortFuerKonto

Für jeden Remote-Host enthält die Datei einen Eintrag. Als Passwort geben Sie das für den Aufbau der Verbindung erforderliche Passwort an. Ein PasswortFuerKonto brauchen Sie nur dann, wenn der Remote-Host eine zusätzliche Authentifizierung verlangt -- in der Regel genügen die ersten drei Einträge.

Listing 1 zeigt eine .netrc mit drei Einträgen, wobei hier alle Daten für eine Gegenstelle in einer Zeile stehen. Beim ersten Eintrag handelt es sich um einen öffentlichen FTP-Server im Web, deshalb der Loginname anonymous. Obwohl es als höflich gilt, die eigene E-Mail-Adresse als Passwort für die anonyme Anmeldung anzugeben, ist das nicht zwingend erforderlich. Die beiden anderen Zeilen stehen für Hosts im internen Netzwerk.

Listing 1
machine ftp.emea.ibm.com  login anonymous  password david.tansley@btinternet.com
machine uk01lx6001        login dxtans     password lOopy
machine uk04lx6003        login dxtans     password mas123

Um eine Verbindung zum Host uk01lx6001 aufzubauen, geben Sie ftp uk01lx6001 ein. Der FTP-Client sucht dann in .netrc nach dem Hostnamen uk01lx6001. Anschließend setzt er die Login- und Passworteinträge für den Verbindungsaufbau am Remote-Server ein. Einen Überblick über die Startoptionen des FTP-Kommandos gibt die Tabelle "FTP-Optionen".

FTP-Optionen
OptionBedeutung
-pVerwendet für Datenübertragung den so genannten passiven Modus. Er ist erste Wahl, wenn Ihr Rechner hinter einer Firewall steht, weil der Client dann dem Server den zu nutzenden Port mitteilt. Heute gilt der passive Modus als Standard, aber es gibt noch ältere Versionen, die diesen Modus nicht als Voreinstellung wählen.
-iDamit fragt der Client vor jedem FTP-Transfer noch einmal nach einer Bestätigung. Wenn Sie wissen, welche Dateien Sie abholen oder schreiben wollen, ist diese Option sehr nützlich.
-nUnterbindet die automatische FTP-Anmeldung beim Verbindungsaufbau. Wenn Auto-Login aktiviert ist, sucht FTP in .netrc nach den Login-Daten. Findet FTP keine passenden Informationen in .netrc, fragt es nach Benutzernamen und Passwort.
-vSetzt den so genannten Verbose-Modus, in dem FTP etwas detailliertere Informationen ausgibt.

Wie man Dateien abholt

Das erste FTP-Skript soll eine Verbindung zu einem Remote-Host aufbauen und die Datei /etc/hosts herunterladen (siehe Listing 2). Die erste Zeile nach dem Bash-Aufruf schaltet den interaktiven Modus von FTP aus und den Verbose-Modus ein.

Um ftp mit Befehlen zu füttern, kommt anschließend ein so genanntes Here-Dokument zum Einsatz. Alle Kommandos zwischen der Startmarke <<EOCMDS und der gleichnamigen Schlussmarke EOCMDS übergibt die Shell dem FTP-Client als Eingabe. Statt EOCMDS können sie dabei einen beliebigen Namen für die Marke verwenden.

Zunächst baut die Befehlsfolge eine Verbindung zum Host uk01lx6001 auf. Anschließend legt das Skript für die Übertragung mit ascii den ASCII-Modus fest. Lokal wechselt das Skript ins Verzeichnis /tmp, auf der Gegenseite nach /etc. Dann findet die eigentliche Übertragung der Datei hosts statt, die das Skript im Verzeichnis /tmp ablegt. Der Befehl quit beendet den FTP-Client.

Listing 2
#!/bin/bash
ftp -i -v <<EOCMDS
open uk01lx6001
ascii
lcd /tmp
cd /etc
get hosts
quit
EOCMDS

Sie können die Methode auch verwenden, um eine Liste der zu übertragenden Dateien anzugeben. Allerdings müssen Sie dann für jeden Transfer eine Verbindung auf- und wieder abbauen. Wie das funktioniert, zeigt Listing 3. Eine for-Schleife innerhalb des FTP-Codeblocks können Sie deshalb nicht verwenden, weil Sie an dieser Stelle mit der FTP-Verbindung zum Remote-Host arbeiten und nicht mit der Bash-Shell.

Listing 3
#!/bin/bash
list="hosts hosts.allow hosts.deny"
for files in ${list}; do
  ftp -i -v <<EOCMDS
    open uk01lx6001
    ascii
    lcd /tmp
    cd /etc
    get ${files}
    quit
  EOCMDS
done

.netrc-Tricks

Sie können in Ihrem Bash-Skript prüfen, ob .netrc existiert, und davon abhängig die Authentifizierungsmethode wählen. Listing 4 enthält dafür einen einfachen Test für das .netrc-Format aus Listing 1. Existiert die Datei .netrc und ist sie lesbar, übergibt das Script die Einträge an die Standardausgabe.

Listing 4
#!/bin/bash
netrc_file=$HOME/.netrc
if [ -r ${netrc_file} ]; then
  cat ${netrc_file} | awk '{print $2,$4}'
else
  echo "${netrc_file} not present"
fi

Um mit einem Shell-Skript eine Auswahl aus mehreren .netrc-Einträgen (wie in Listing 1) zu erzeugen, können Sie die Datei mit Hilfe von cat an die Standardausgabe übergeben. Die Option -n von Cat fügt noch Zeilennummern hinzu. Listing 5 zeigt eine mögliche Implementierung dafür.

Listing 5
#!/bin/bash
# ftp5
netrc_file=${HOME}/.netrc
if [ -r ${netrc_file} ]; then
  max_recs=$(cat ${netrc_file} | awk 'END{print NR}')
  cat -n ${netrc_file} | awk '{print $1,": connect to [",$3,"] as user [",$5,"]"}'
  echo -en "\n Select record to use [ 1 .. ${max_recs} ] : "
  read ans
  if [ ${ans} -ge 1 ] && [ ${ans} -le ${max_recs} ]; then
    host=$(cat ${netrc_file} | awk "NR==$ans"|awk '{print $2}')
    user=$(cat ${netrc_file} | awk "NR==$ans"|awk '{print $4}')
    password=$(cat ${netrc_file} | awk "NR==$ans"|awk '{print $6}')
  else
    echo "invalid choice, needs to be [ 1 .. ${max_recs} ]"
    exit 1
  fi # $ans in numeric range
  echo -e " selected info is:\n host [${host}]\n user [${user}]\n password [${password}]"
else
  echo " Sorry, cannot read ${netrc_file}"
fi # netrc present

Als erstes stellt das Skript wie im letzten Beispiel sicher, dass .netrc existiert und lesbar ist. Der dann folgenden Befehl zählt die Anzahl der Einträge in der Datei und legt sie in der Variablen max_recs ab. Der Befehl wc -l wäre zwar weniger aufwändig gewesen, aber leider verwendet er beim Ersetzen der Variablen Füllzeichen, sodass der Output über die Standardausgabe nicht sehr schön aussieht.

Der cat-Befehl gibt für alle Einträge lediglich die Host- und Login-Felder jedes Eintrags über die Standardausgabe aus (Abbildung ((1))). Als nächstes fordert das Skript den Benutzer dazu auf, die Nummer des Eintrags einzugeben, den er wählen möchte. Dabei greift es auf die oben belegte Variable max_recs zurück, die die Anzahl an Einträgen enthält. Nach der Auswahl liest das Skript auf Basis der Input-Nummer die erforderlichen Felder mit Hilfe der Awk-Funktion NR aus und zeigt das Ergebnis an.

Das Skript verzichtet weitgehend auf die Fehlerbehandlung -- es stellt lediglich fest, ob die eingegebene Zahl innerhalb des gültigen numerischen Bereichs liegt.

((1)) Das Skript aus Listing 5 baut dieses textbasierte FTP-Menü auf.

Fehlerbehandlung

Wenn Sie den Fehlerstatus am Ende des FTP-Scripts abfragen wollen, können Sie auf die FTP-Fehlernummern zurückgreifen. In der Tabelle "FTP-Rückgabewerte" finden Sie die standardisierten Rückgabe-Codes.

FTP-Rückgabewerte
CodeBedeutung
202Befehl nicht implementiert
421Dienst nicht verfügbar
426Transfer abgebrochen
450Datei nicht verfügbar
500Syntaxfehler
501Syntaxfehler in Argumenten
503Benutzer nicht angemeldet
550Datei nicht verfügbar
553Ungültiger Dateiname
666Datei oder Verzeichnis existiert nicht
777Unbekannter Host
999Ungültiger Befehl

Eine Möglichkeit, Fehlerbedingungen abzufangen, besteht darin, am Ende des Scripts egrep aufzurufen (siehe Listing 6). Als erstes müssen Sie die gesamte FTP-Ausgabe in eine Log-Datei umleiten:

ftp -i -v  >> ${log} 2>&1

FTP leitet die gesamte Ausgabe, einschließlich aller während der FTP-Session auftretenden Fehler, in das Logfile, dessen Name in der Variable log steht. Am Ende der FTP-Session durchsuchen Sie die Datei mithilfe von Egrep nach interessanten Codes oder Begriffen; dabei trennt jeweils eine Pipe (|) die Suchmuster. Setzen Sie Egrep innerhalb eines Skripts ein, dann macht es Sinn, die Ausgabe der Suchroutine auf /dev/null umzuleiten; damit halten Sie die Standardausgabe frei von unerwünschtem Output:

if egrep "202|421|426" $log > /dev/null 2>&1

Wenn Egrep für einen Treffer true meldet, terminiert das Skript aus Listing 6 mit dem Rückgabewert 1, gibt eine Meldung auf der Konsole aus und schreibt diese auch ins Logfile. Andernfalls gibt das Skript 0 zurück.

Falls Sie das Skript als Batch ausführen, statt interaktiv aus der Befehlszeile, sollten Sie die Ausgabe nur in die Log-Dateien schreiben, nicht aber über den Befehl tee auch auf die Standardausgabe. In diesem Fall ändern Sie die entsprechenden Zeilen aus Listing 6 in echo "Errors" >> ${log} im Fehlerfall und echo "OK" >> ${log} für eine Erfolgsmeldung.

Listing 6
...
for files in ${list}; do
  ftp -i -v  >> ${log} 2>&1 <<EOCMDS
  ...
  EOCMDS
done
if egrep "202|421|426|450|500|501|503|550|553|666|777|999" ${log} > /dev/null 2>&1; then
  echo "Errors" | tee -a ${log}
  exit 1
else
  echo "OK" | tee -a ${log}
  exit 0
fi

Fazit

Das Automatisieren von FTP bietet viele produktive Möglichkeiten für den Dateiaustausch zwischen Hosts. Experimentieren Sie ruhig mit unterschiedlichen FTP-Skripts, um verschiedene administrative Aufgaben zu erfüllen. Schreiben Sie dazu aber in jedem Fall die Benutzernamen und Passwörter in die nicht für jeden lesbare Datei .netrc, statt sie im Skript einzubetten. (ofr/jlu)

Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links" nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedruckten Fassung entsprechen.




Druckerfreundliche Version | Feedback zu dieser Seite | Datenschutz | © 2010 Linux New Media AG

[Linux-Magazin] [LinuxUser] [EasyLinux] [Linux-Community] [Ubuntu User] [Linux Technical Review] [Linux Magazine] [Linux Pro Magazine] [Ubuntu User]
[EasyLinux Poland] [Linux Magazine Poland] [Linux Magazine Brasil] [EasyLinux Brasil] [Linux Magazine Spain]