donsm00chy
Goto Top

Kopieren eines Ordners auf bestimmte Rechner - Namen der Rechner aus Datei auslesen

Im Rahmen eines Projektes zur Sicherung bestimmter Server mittels NTBackup galt es auch, auf einfache Art und Weise das letztendlich auszuführende Backup-Script auf diese Server zu kopieren.


back-to-topProblemstellung


Folgendes Problem galt es zu lösen: Der Ordner sollte auf bestimmte Rechner kopiert werden. Ebenso auf eine jeweils definierte Partition. Da für mich der händische Aufwand zu hoch gewesen wäre, sollte es über ein Script realisiert werden.

Zudem musste auf den Servern noch eine bestimmte Ordner-Struktur erzeugt werden, die für das eigentliche Backup-Script benötigt wird. Erschwerend kommt hinzu, dass Server mit englischem und deutschem Betriebssystem verwendet werden, sich also die Pfade unterscheiden (Dokumente und Einstellungen -> Documents and Settings). Dieser Teil gehört eigentlich nicht unbedingt mit dazu, ich lass ihn aber trotzdem als kleinen Denkanstoß drinne, falls jemand mal vor so einem Problem steht.


back-to-topVoraussetzungen


Grundlage zum Kopieren ist Robocopy. Dieses, normalerweise im Microsoft® Windows® Server 2003 Resource Kit enthaltene Tool übertrifft das schon bekannte copy bzw. xcopy im Funktionsumfang um Welten. Damit nicht das komplette Paket heruntergeladen und installiert werden muss, habe ich das Tool nochmal hier inklusive der Dokumentation hochgeladen.


back-to-topDreh- und Angelpunkt: Die Hosts.txt


Dreh- und Angelpunkt des Ganzen ist die Host.txt. In dieser müssen folgende Angaben gemacht werden:

  1. Hostname des Rechners, auf den der Ordner kopiert werden soll
  2. Partition, auf die der Ordner kopiert werden soll
  3. Sprache des Betriebssystems

Die Spalten werden mit einem beliebigen Trennzeichen versehen, in meinem Fall dem Semikolon (#). Ausschauen tut das Ganze dann so:

:: ***********************************************
:: * Configfile fuer NTBackup-Script             *
:: * Aufbau:                                     *
:: * A#B#C                                       *
:: * A = Hostname                                *
:: * B = lokales Backuplaufwerk (OHNE ":" !!!)   *  
:: * C = Sprachversion des Betriebssystems       *
:: * Genaue Beschreibungen siehe Dokumentation!  *
:: ***********************************************
HOSTNAME1#D#DE
HOSTNAME2#T#EN
HOSTNAME3#G#EN

Natürlich lässt sich die Liste beliebig ergänzen. Dabei ist zu beachten, dass die Hostnamen konsequenterweise immer groß, oder klein geschrieben werden sollten. Der späteren Einfachheit halber.


back-to-topWas hinter den Kulissen passieren soll


Der Prozess, der ablaufen soll ist folgender:

  1. Es werden alle Hostnamen aus der Hosts.txt ausgelesen und in einem kleinen Menü dargestellt
  2. Aus diesem Menü kann der Benutzer auswählen, ob er den Ordner Backup
    • Auf alle Server kopieren will
    • Auf einen einzelnen Server kopieren will
    • Sich nur verklickt hat und lieber abbrechen will.
  3. Je nach Auswahl des Users werden verschiedene Unterroutinen aufgerufen bei denen
    • Der Ordner nur auf den einen Server kopiert wird
    • Der Ordner auf alle Hosts der Hosts.txt kopiert wird
    • Abgebrochen wird, weil der User einen in der Hosts.txt nicht vorhandenen Namen eingegeben bzw. sich für den Abbruch entschieden hat
  4. Danach wird mittels Robocopy versucht den Ordner Backup auf den entsprechenden Server und die entsprechende Partition zu kopieren
  5. Im Anschluss wird überprüft, ob der Ordner und die darin enthaltene Backup.cmd vorhanden sind
  6. Für die Auswahl des Users und den Status der folgenden Operationen wird eine Log-Datei angefertigt, die sich nach Abschluss öffnet und dem User anzeigt, auf welche Servern der Ordner erfolgreich kopiert wurde, und bei welchen es möglicherweise Probleme gab


back-to-topDas Script im Einzelnen


Ich werde erstmal jeden Code-Komplex einzeln durchgehen und erläutern, am Ende wird dann das Script im Ganzen stehen. Es sind zudem noch mal Erklärungen im Script selber untergebracht, die erstmal ausgelassen werden, aber im kompletten Script dann natürlich enthalten sind.


back-to-topDas Menü

Das Menü, in dem alle in der Hosts.txt eingetragenen Server aufgeschlüsselt werden, wird mittels einer einfachen For-Schleife realisiert, bei der nur die erste Spalte abgefragt wird. Die Auswahl des Users wird mittels set /p in der Variable Choice gespeichert und im folgenden Teil ausgewertet werden. Zudem wie bereits erwähnt wird die Log_Datei geschrieben.

@ECHO Auf welche Rechner soll das Script kopiert werden?
@ECHO.
@ECHO.
@ECHO [ALLE] - Auf alle untenstehende Server
@ECHO.
for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	ECHO [%%a] - Nur auf %%a
	)
@ECHO.
@ECHO [KEINEN] - bricht den Vorgang ab
@ECHO.

set /p Choice=Bitte den "HOSTNAMEN", "ALLE" oder "KEINEN" eingeben (GROSSSCHREIBUNG beachten!):  

@ECHO Vom Benutzer getroffene Choice: %Choice% > Install_Log.txt
@ECHO. >> Install_Log.txt

d244daddb0b228582c57f7d9238e8dbe-menue

back-to-topDie Auswertung der Usereingabe

Als nächstes folgt die Auswertung der Eingabe des Users. Dabei wird die Variable InstalledSuccessfully auf den Initialwert 0 gesetzt.

set InstalledSuccessfully=0
IF %Choice% == ALLE (
   GOTO AllServers
) ELSE IF %Choice% == KEINEN (
   GOTO NoneServers
) ELSE (
       for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
                    IF %Choice% == %%a (
                        GOTO SingleServer
                    )       
		)
      	GOTO Error
)

Bis zum ELSE-Zweig dürfte es soweit keine Nachfragen geben. In dem Zweig allerdings passiert folgendes: Es findet ein Abgleich der Eingabe mit den vorhandenen Hostnamen in der Hosts.txt statt. Stimmt die Eingabe mit Einem überein, wird zur Sprungmarke SingleServer gesprungen. Stimmt die Eingabe mit keinem der Hostnamen überein wird die For-Schleife verlassen und zur Sprungmarke Error gesprungen.


back-to-topDer weitere Verlauf für einen einzelnen Server
back-to-topDas Kopieren auf den Server

Nun folgt das Kopieren des Ordners auf den einzelnen Server.

:SingleServer
for /f "tokens=1,2,4 delims=#" %%a in ('findstr %Choice% Hosts.txt') do (  
robocopy backup \%Choice%\%%b$ackup /E /R:0 /W:1

	IF %%c==de (
		md "\%Choice%c$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupData"  
		md "\%Choice%c$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupTemp"  
	) ELSE IF %%c==en (
		md "\%Choice%c$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupData"  
		md "\%Choice%c$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupTemp"  
	)
)
GOTO QuerySingleServer

Da wir dabei noch den ausgesuchte Partition und Sprache des Betriebssystems abfragen müssen, geschieht die ganze Operation wieder mit einer For-Schleife. Dazu suchen wir uns mittels findstr %Choice% Hosts.txt zuerst die gebrauchte Zeile aus der Hosts.txt. Anschließend wird versucht den Ordner Backup auf den Server zu kopieren. Was die Slash-Befehle im Einzelnen bedeuten lässt sich in der Doku nachlesen (Link siehe #toc1 Voraussetzungen).
Zudem wird in der Hosts.txt die Sprachversion abgefragt und je nach Sprache die entsprechenden Ordnerstrukturen erzeugt.


back-to-topAbfrage, ob das Kopieren erfolgreich war

Man kann nicht immer davon ausgehen, dass das Kopieren erfolgreich war, deshalb muss eine kleine Abfrage stattfinden. Dies geschieht damit, dass man einfach nachschaut, ob die Backup.cmd auf dem Server vorhanden ist:

:QuerySingleServer
for /f "tokens=1,2 delims=# skip=12" %%a in (Hosts.txt) do (  
	IF EXIST \%Choice%\%%b$BackupBackup.cmd (
		SET InstalledSuccessfully=1
	) 
)
GOTO EchoStatus

Ist dies der Fall, wird die Variable InstalledSuccessfully auf 1 gesetzt. Als nächstes wird der Wert der Variable überprüft:

:EchoStatus
IF %InstalledSuccessfully% == 1 (
	@ECHO Backupscript erfolgreich auf %Choice% kopiert >> Install_Log.txt
	@ECHO Backupscript erfolgreich auf %Choice% kopiert.
	) ELSE (
	@ECHO Backupscript konnte nicht erfolgreich auf %Choice% kopiert werden! >> Install_Log.txt
	@ECHO Backupscript konnte nicht erfolgreich auf %Choice% kopiert werden!
)
GOTO EndOfFile

Sollte das Kopieren erfolgreich verlaufen und somit die Variable auf 1 gesetzt sein, wird dies als Meldung zurückgegeben, ansonsten wird eine Meldung ausgegeben, dass das Kopieren nicht erfolgreich war. (Aufbauend darauf, dass am Anfang des Scripts der Wert für die Variable auf 0 gesetzt wurde).
Damit ist der Durchgang für das Kopieren auf einen einzelnen Server beendet. Es wird noch die Log-Datei geöffnet, damit der User nachschauen kann, wie die Installation verlief. Nach dem Schließen dieser wird das Script beendet.


back-to-topDer weitere Verlauf falls alle Server ausgewählt worden
back-to-topDas Kopieren auf die Server

Der Kopiervorgang unterscheidet sich nur minimal von dem beim einzelnen Server, es werden einfach alle Hosts abgeklappert und versucht auf diese den Ordner zu kopieren.

:AllServers
for /f "tokens=1,2,4 delims=# skip=12" %%a in (Hosts.txt) do (  
	robocopy backup \%%a\%%b$ackup /E /W:5 /R:0 > Install_Log_%%a.txt

	IF %%c==de (
		md "\%%ac$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupData"  
		md "\%%ac$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupTemp"  
	) ELSE IF %%c==en (
		md "\%%ac$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupData"  
		md "\%%ac$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupTemp"  
	)	
)
GOTO CheckForSuccessAll

Ebenso wird wieder die Ordnerstruktur angelegt, falls diese noch nicht vorhanden sein sollte.
In einem Punkt unterscheidet sich die Installation: Es wird für jeden Rechner eine einzelne, temporäre Log-Datei angelegt, in die Robocopy den Status – ob erfolgreich oder nicht – vermerkt. Bei einem nicht erfolgreichen Kopieren steht in diesen Logs eine markante Zeichenkette, die im nächsten Schritt abgefragt wird:

:CheckForSuccessAll
for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	for /f %%b in ('findstr /C:"Accessing Destination Directory" Install_Log_%%a.txt') do (  
		@ECHO Backupscript konnte nicht erfolgreich auf %%a kopiert werden! >> Install_Log.txt
		@ECHO Backupscript konnte nicht erfolgreich auf %%a kopiert werden!
		del Install_Log_%%a.txt /Q
	)
)

Sollte diese vorhanden sein, wird ausgegeben, dass das Kopieren Schiefgelaufen ist, gleichzeitig wird die temporäre Log für diesen Server gelöscht. Dies geht nun solange, bis in keiner temporären Log mehr diese Zeichenkette zu finden ist. Danach werden die restlichen temporären Logs abgeklappert und die Meldung, dass das Kopieren erfolgreich verlief ausgegeben:

for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	IF EXIST Install_Log_%%a.txt (
		@ECHO Backupscript erfolgreich auf %%a kopiert >> Install_Log.txt
		@ECHO Backupscript erfolgreich auf %%a kopiert.
	del Install_Log_%%a.txt /Q
	)
)
goto EndOfFile

Durch diese Prozedur wird sichergestellt, dass es nicht heißt "Kopieren bei allen Servern erfolgreich bzw. bei allen fehlgeschlagen", sondern für jeden Server individuell das Ganze geprüft wird.
Abschließend wird wieder die "richtige" Log-Datei geöffnet, die zum Beispiel dann so aussehen kann:

Vom Benutzer getroffene Auswahl: ALLE 
 
Backupscript konnte nicht erfolgreich auf HOSTNAME1 kopiert werden!
Backupscript konnte nicht erfolgreich auf HOSTNAME2 kopiert werden!
Backupscript erfolgreich auf HOSTNAME3 kopiert

Damit wäre der Vorgang abgeschlossen, wenn alles geklappt hat, hat man nun mit 1 Mausklick und 5 Buchstaben einen Ordner auf x verschiedene Rechner kopiert. Natürlich kann man das Script noch ausweiten.


back-to-topDas Script im Ganzen


Zum Abschluss nun noch mal das Script hintereinanderweg:

@echo off
cls
@title Installscript fuer NTBackup-Script © Andre F.
::**********************************************
::* Installscript fuer NTBackup-Script (v 4.0) *
::*                  Andre F.                  *
::**********************************************


:: ***********************************
:: ******          GUI          ******
:: ***********************************
:: *---------------------------------*
:: ***********************************
:: * Erklaerung:                     *
:: * Auflistung der in der Hosts.txt *
:: * eingetragenen Rechner und die   *
:: * Benutzerabfrage                 *
:: ***********************************

@ECHO Auf welche Rechner soll das Script kopiert werden?
@ECHO.
@ECHO.
@ECHO [ALLE] - Auf alle untenstehende Server
@ECHO.
for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	ECHO [%%a] - Nur auf %%a
	)
@ECHO.
@ECHO [KEINEN] - bricht den Vorgang ab
@ECHO.

set /p Choice=Bitte den "HOSTNAMEN", "ALLE" oder "KEINEN" eingeben (GROSSSCHREIBUNG beachten!):  

@ECHO Vom Benutzer getroffene Auswahl: %Choice% > Install_Log.txt
@ECHO. >> Install_Log.txt


:: *****************************************
:: ******           Auswahl           ******
:: *****************************************
:: *---------------------------------------*
:: *****************************************
:: * Erklaerung:                           *
:: * Anhand der Eingabe des Users wird     *
:: * entschieden, welche Abarbeitung folgt *
:: *****************************************

set InstalledSuccessfully=0
IF %Choice% == ALLE (
   GOTO AllServers
) ELSE IF %Choice% == KEINEN (
   GOTO NoneServers
) ELSE (
       for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
                    IF %Choice% == %%a (
                        GOTO SingleServer
                    )       
		)
      	GOTO Error
)


:: ******************************************
:: ******      Einzelner Server        ******
:: ******************************************
:: *----------------------------------------*
:: ******************************************
:: * Erklaerung:                            *
:: * Bei der Eingabe eines einzelnen        *
:: * Hostnamen wird dieser Teil ausgefuehrt *
:: ******************************************

:SingleServer
for /f "tokens=1,2,4 delims=#" %%a in ('findstr %Choice% Hosts.txt') do (  
robocopy backup \%Choice%\%%b$ackup /E /R:0 /W:1 > Install_Log_%Choice%.txt

	IF %%c==de (
		md "\%Choice%c$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupData"  
		md "\%Choice%c$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupTemp"  
	) ELSE IF %%c==en (
		md "\%Choice%c$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupData"  
		md "\%Choice%c$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupTemp"  
	)
)
GOTO QuerySingleServer


:: ********************************
:: ******    Alle Server     ******
:: ********************************
:: *------------------------------*
:: ********************************
:: * Erklaerung:                  *
:: * Bei der Eingabe von ALLE     *
:: * wird dieser Teil ausgefuehrt *
:: ********************************

:AllServers
for /f "tokens=1,2,4 delims=# skip=12" %%a in (Hosts.txt) do (  
	robocopy backup \%%a\%%b$ackup /E /W:5 /R:0 > Install_Log_%%a.txt

	IF %%c==de (
		md "\%%ac$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupData"  
		md "\%%ac$Dokumente und EinstellungenAdministratorLokale EinstellungenAnwendungsdatenMicrosoftWindows NTNTBackupTemp"  
	) ELSE IF %%c==en (
		md "\%%ac$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupData"  
		md "\%%ac$Documents and SettingsAdministratorLocal SettingsApplication DataMicrosoftWindows NTNTBackupTemp"  
	)	
)
GOTO CheckForSuccessAll


:: ***********************************
:: ******    Statusabfragen     ******
:: ***********************************
:: *---------------------------------*
:: ***********************************
:: * Erklaerung:                     *
:: * Hier erfolgt die Abfrage, ob    *
:: * ein das Kopieren erfolgreich    *
:: * war oder nicht.                 *
:: ***********************************

:QuerySingleServer
for /f "tokens=1,2 delims=# skip=12" %%a in (Hosts.txt) do (  
	IF EXIST \%Choice%\%%b$BackupBackup.cmd (
		SET InstalledSuccessfully=1
	) 
)
GOTO EchoStatus


:EchoStatus
IF %InstalledSuccessfully% == 1 (
	@ECHO Backupscript erfolgreich auf %Choice% kopiert >> Install_Log.txt
	@ECHO Backupscript erfolgreich auf %Choice% kopiert.
	) ELSE (
	@ECHO Backupscript konnte nicht erfolgreich auf %Choice% kopiert werden! >> Install_Log.txt
	@ECHO Backupscript konnte nicht erfolgreich auf %Choice% kopiert werden!
)
del Install_Log_%Choice%.txt /Q
GOTO EndOfFile


:CheckForSuccessAll
for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	for /f %%b in ('findstr /C:"Accessing Destination Directory" Install_Log_%%a.txt') do (  
		@ECHO Backupscript konnte nicht erfolgreich auf %%a kopiert werden! >> Install_Log.txt
		@ECHO Backupscript konnte nicht erfolgreich auf %%a kopiert werden!
::		del Install_Log_%%a.txt /Q
	)
)
for /f "tokens=1 delims=# skip=12" %%a in (Hosts.txt) do (  
	IF EXIST Install_Log_%%a.txt (
		@ECHO Backupscript erfolgreich auf %%a kopiert >> Install_Log.txt
		@ECHO Backupscript erfolgreich auf %%a kopiert.
::	del Install_Log_%%a.txt /Q
	)
)
goto EndOfFile


:: ********************************
:: ******    Kein Server     ******
:: ********************************
:: *------------------------------*
:: ********************************
:: * Erklaerung:                  *
:: * Bei der Eingabe von KEINEN   *
:: * wird dieser Teil ausgefuehrt *
:: ********************************

:NoneServers
@ECHO Script wurde auf keinen Rechner kopiert.
@ECHO Script auf keinen Rechner kopiert >> Install_Log.txt
GOTO EndOfFile


:: *********************************
:: ******  Falsche Eingabe   *******
:: *********************************
:: *-------------------------------*
:: *********************************
:: * Erklaerung:                   *
:: * Bei der fehlerhaften Eingabe  *
:: * eines Namens wird dieser Teil * 
:: * ausgefuehrt                   *
:: *********************************

:Error
@ECHO Eingegebener Name ist kein gueltiger Hostname!
@ECHO Eingegebener Name ist kein gueltiger Hostname >> Install_Log.txt
goto EndOfFile

:EndOfFile
call Install_Log.txt
@title %ComSpec%

back-to-topAbschluss


Ich hoffe, ich konnte einigen mit dieser Anleitung weiterhelfen. Sollten dennoch Fragen offen sein, immer raus damit.

Mit freundlichen Grüßen, smoo

Content-Key: 54159

Url: https://administrator.de/contentid/54159

Ausgedruckt am: 28.03.2024 um 09:03 Uhr

Mitglied: DonSm00chY
DonSm00chY 15.03.2007 um 15:58:54 Uhr
Goto Top
Hab das Problem selber lösen können. Fehler steckte mal wieder im Detail, bzw. im benutzen von Copy & Paste.

:rechner
@ECHO 123
for /f "tokens=1,2,4 delims=# skip=17" %%a in ('findstr %auswahl% hosts.txt') do (  
@ECHO 234
robocopy backup \\%%a\%%b$\backup /E

   IF %%c==de (
      md "\\%auswahl%\c$\Dokumente und Einstellungen\Administrator\Lokale Einstellungen\Anwendungsdaten\Microsoft\Windows NT\NTBackup\Data"  
      md "\\%auswahl%\c$\Dokumente und Einstellungen\Administrator\Lokale Einstellungen\Anwendungsdaten\Microsoft\Windows NT\NTBackup\Temp"  
   ) ELSE IF %%c==en (
      md "\\%auswahl%\c$\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\Data"  
      md "\\%auswahl%\c$\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\Temp"  
      )
)
@ECHO 456
GOTO eof

Im skip=17 lag der Fehler. Wenn ich nur 1 Zeile als Rückmeldung bekomme, kann ich natürlich nicht die ersten 17 überspringen...


Manchmal sieht man den Wald vor lauter Bäumen nicht...

Grüße, André
Mitglied: DonSm00chY
DonSm00chY 29.03.2007, aktualisiert am 18.10.2012 um 18:31:47 Uhr
Goto Top
So, hab aus der Frage mal eine Antwort gemacht - in Form eines kleinen Tutorials. Demnächst werde ich noch meinen Beitrag zur schtasks.exe überarbeiten.
Mitglied: Biber
Biber 29.03.2007 um 13:43:19 Uhr
Goto Top
Moin, DonSm00chY,

vielen Dank für dieses schöne Tutorial und Deine damit verbundene Arbeit.
Find ich klasse.

Habe es hochgestuft zum Tutorial.
Solche Aktionen wie Deine entschädigen mich (und einige andere Stammuser hier) für viele andere Postings.

Danke
Biber
Mitglied: micneu
micneu 13.05.2009 um 14:05:47 Uhr
Goto Top
Super geschrieben.....

Viel spaß noch