• Apfeltalk ändert einen Teil seiner Allgemeinen Geschäftsbedingungen (AGB), das Löschen von Useraccounts betreffend.
    Näheres könnt Ihr hier nachlesen: AGB-Änderung
  • Was gibt es Schöneres als den Mai draußen in der Natur mit allen Sinnen zu genießen? Lasst uns teilhaben an Euren Erlebnissen und macht mit beim Thema des Monats Da blüht uns was! ---> Klick

Variablen in eine Schleife packen

Whoution21

Pferdeapfel
Registriert
08.08.06
Beiträge
79
Hallo, ich habe folgendes AppleScript (sinnvoller Auszug):

Code:
tell application "Finder"
    activate
    try
        mount volume servervol_1
    on error
        display dialog "Die Verbindung konnte nicht hergestellt werden!"
    end try
end tell

do shell script "rsync -avz " & path_1 & " " & target
Das möchte ich insgesamt sechs mal ausführen, für die gegebenen Variablen servervol_1 bis servervol_5 sowie path_1 bis path_5. Kann ich das mit einer Schleife vereinfachen? Ich habe bisher folgendes probiert:

Code:
repeat with counter from 1 to 5
[...]
    mount volume "servervol_" & counter & " "
[...]
    do shell script "rsync -avz " & path_" & counter & " " " & target
In der letzten Zeile komme ich einfach nicht weiter, hier bekomme ich immer den Fehler "Es wurde „Zeilenende, etc.“ erwartet, aber ein „„"““ wurde gefunden."

Ich bin über jegliche Hilfe dankbar, kenne ich mich aber noch nicht so gut mit der Materie AppleScript aus. Ich bitte das, bei einer Antwort zu beachten :)
 
Zuletzt bearbeitet von einem Moderator:

hillepille

Melrose
Registriert
19.07.09
Beiträge
2.508
Versuch mal das mittlere von den drei " in der letzten zeile mit \" zu maskieren

Und ich glaube die " sitzen an den falschen stellen zum teil

do shell script "rsync -avz " & path_ & counter & " " " & target

da frage ich mich wozu das dritte " hinter counter & da ist :)
 

Whoution21

Pferdeapfel
Registriert
08.08.06
Beiträge
79
Was bedeutet maskieren? Bedeutet das, dass ich einfach ein Backslash davor schreibe?

Wenn ja, dann klappt das nicht. Ich bekomme den selben Fehler, nach wie vor mit einer Markierung auf dem ersten Anführungszeichen nach path_.


Das mit den falschen Stellen kann auch sein. Ich habe da etwas den Überblick verloren. Ich habe, wie gesagt, nicht viel Ahnung von der Materie. Ich suche mir nur aus Codeschnippseln die benötigten Teile raus und versuche sie zu kombinieren. Aber es wird immer komplizierter und unübersichtlicher irgendwie.
 

fyysh

Schweizer Glockenapfel
Registriert
25.01.10
Beiträge
1.386
Ich glaube du versuchst sowas:
Code:
property myMap : {¬
	{server:"server1", protocol:"afp", share_name:"share1", rsync_src:"/quelle/für/rsync", rsync_tgt:"ziel/ordner/für/rsync/", rsync_opt:"-avz"}, ¬
	{server:"server2", protocol:"smb", share_name:"share2", rsync_src:"/quelle/für/rsync", rsync_tgt:"ziel/ordner/für/rsync/", rsync_opt:"-avz"}, ¬
	{server:"server3", protocol:"afp", share_name:"share3", rsync_src:"/quelle/für/rsync", rsync_tgt:"ziel/ordner/für/rsync/", rsync_opt:"-avz"} ¬
		}



tell application "Finder"
	repeat with aSrv in myMap
		try
			--ich empfehle dir einen ping check auf verfügbarkeit des servers einzufügen - checkt schneller als der finder
			do shell script "ping -c 1 " & (server of aSrv) --gibt error wenn ping fehlschlägt
			
			set mountpoint to mount volume ((protocol of aSrv) & "://" & (server of aSrv) & "/" & (share_name of aSrv)) --generiert sowas wie afp://server1/share
			
			try
				do shell script "rsync " & (rsync_opt of aSrv) & space & quoted form of (rsync_src of aSrv) & space & quoted form of ((POSIX path of mountpoint) & (rsync_tgt of aSrv))
				--wird sowas wie "rsync -avz '/quelle/für/rsync' '/Volumes/share1//ziel/ordner/für/rsync/'" ausgeben
			on error e
				display alert "rsync von " & return & quoted form of (rsync_src of aSrv) & return & "nach" & return & ((POSIX path of mountpoint) & (rsync_tgt of aSrv)) & return & "fehlgeschlagen." message e buttons {"Abbrechen", "Weiter"} cancel button 1
			end try
			
			
		on error e
			display alert "Die Verbindung zu " & (server of aSrv) & " konnte nicht hergestellt werden!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
		end try
		
	end repeat
end tell

Wenn du die Möglichkeit hast, auf die Server per SSH zuzugreifen, könntest du dir das Mounten der Shares schenken.
In diesem Fall konfigurierst du dir einfach key authentication für ssh auf den Servern und verwendest rsync über ssh.
Das ginge so (bsp):
rsync -ahv /was/gesynct/werden/soll user@server:/wohin/gesynct/werden/soll (=> nach server syncen)
oder
rsync -ahv user@server:/was/gesynct/werden/soll /wohin/gesynct/werden/soll (=> von server syncen)

Wie du key auth einrichtest hab ich mal hier erklärt: http://www.apfeltalk.de/forum/denkfehler-t317936-2.html#post3037034
Musst natürlich erst ssh access aktivieren.
 

Whoution21

Pferdeapfel
Registriert
08.08.06
Beiträge
79
Danke für das AppleScript. Ich werde es mir morgen mal genauer ansehen und testen, und vorher noch versuchen, es nachzuvollziehen.

fyysh; schrieb:
Wenn du die Möglichkeit hast, auf die Server per SSH zuzugreifen, könntest du dir das Mounten der Shares schenken.

Diese Möglichkeit habe ich nicht. Vielleicht etwas zum Hintergrund meines Vorgehens: Ich möchte vom FH-Server aus 5 verschiedenen Ordnern die Skripte der Professoren auf mein MacBook laden. Das möchte ich automatisiert, und am besten noch mit einer kleinen Statusmeldung, falls sich etwas ändert. So ein AppleScript habe ich im Netz gefunden. Das versuchte ich jetzt, anzupassen. Das sind meine ersten Schritte in AppleScript, daher möchte ich etwas weiterlernen und das AppleScript noch verbessern, z.B. durch die Variablen und durch eine Schleife. Aber da hängts, da ich quasi in einer Variable eine Variable habe.
 

fyysh

Schweizer Glockenapfel
Registriert
25.01.10
Beiträge
1.386
Ah, IC.

Dann vielleicht eher so:
Code:
property protocol : "smb" --wahrscheinlich sind das samba-shares bei dem Server. Falls nicht, anpassen.
property server : "der-th-server" --name oder ip des servers
property common_target : "/Users/muesteff/Documents/Skripte" --der allgemeine pfad, wo deine skripte hin sollen der ordner sollte existieren

set shares to {{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof1")}, ¬
	{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof2")}, ¬
	{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof3")}}

(*
rsync_source ist der share. du kannst ganze pfade angeben.
bsp: 
-der share heißt "prof_xy"
-deine skripte befinden sich unter smb://der-th-server/prof_xy/bla/ble/bli
=> du gibtst ein rsync_source:"prof_xy/bla/ble/bli"

rsync_target ist wo es bei dir lokal hinsoll
bsp:
unter Dokumente => Skripte => prof_xy
Du setzt oben common_target auf "/Users/muesteff/Documents/Skripte" (benutzernamen anpassen!)
und rsync_target auf rsync_target:(common_target & "/prof_xy") => "/Users/muesteff/Documents/Skripte/prof_xy"
Du könntest komplett andere Pfade nehmen. Um z.B. den dritten Share auf dein Desktop zu syncen, schreib:
rsync_target:"/Users/muesteff/Desktop/Prof3"
*)


try
	do shell script "ping -c 1 " & server --gibt error wenn ping fehlschlägt
on error e
	display alert "Die Verbindung zu " & server & " konnte nicht hergestellt werden!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	return 1
end try

set sharecount to count of shares
set successcount to 0
repeat with aShare in shares
	
	try
		set mountpoint to mount volume (protocol & "://" & server & "/" & (rsync_source of aShare)) --generiert sowas wie afp://server1/share
		try
			--das hier ist zum testen. mach aus "-Pahvn" ein "-Pahv" wenn's funktioniert. das "n" macht einen sog. dry-run, zeigt also nur an, was gemacht werden würde, überträgt aber nix.
			set rsyncresult to do shell script "rsync -Pahvn" & space & quoted form of (POSIX path of mountpoint) & space & quoted form of (rsync_target of aShare) & ">" & quoted form of ((rsync_target of aShare) & ".rsync.log")
			set successcount to successcount + 1
		on error e
			display alert "rsync von " & return & (POSIX path of mountpoint) & return & "nach" & return & rsync_target & return & "fehlgeschlagen." message e buttons {"Abbrechen", "Weiter"} cancel button 1
		end try
		set detachresult to do shell script "diskutil umount force " & (POSIX path of mountpoint) --share "auswerfen"
	on error e
		display alert "mounten von " & return & protocol & "://" & server & "/" & (rsync_source of aShare) & return & "fehlgeschlagen." & return & return & "überprüfe den sharenamen!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	end try
	
end repeat
display dialog "gesynct: " & successcount & "/" & sharecount


Der Witz hierbei ist eigentlich diese Record-Liste, hier shares genannt.

An sich könntest du "shares" aus so definieren:
Code:
property common_target : "/Users/muesteff/Documents/Skripte"

set shares to {{"sharename_auf_dem_server/ggf_unterordner1", (common_target & "/Prof1")}, ¬
	{"sharename_auf_dem_server2/ggf_unterordner", (common_target & "/Prof2")}, ¬
	{"sharename_auf_dem_server3/ggf_unterordner", (common_target & "/Prof3")}}

repeat with aitem in shares
	display dialog (item 1 of aitem) & return & return & (item 2 of aitem)
end repeat

Dann hättest du eine Liste, die 3 Listen enthält.

so ist es einfach eleganter (finde ich):
Code:
property common_target : "/Users/muesteff/Documents/Skripte"

set shares to {{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof1")}, ¬
	{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof2")}, ¬
	{rsync_source:"sharename_auf_dem_server/ggf_unterordner", rsync_target:(common_target & "/Prof3")}}

repeat with aitem in shares
	display dialog (rsync_source of aitem) & return & return & (rsync_target of aitem)
end repeat

Schlussendlich läuft dann alles darauf hinaus, dass du durch variabeln loopen willst. Und dafür nimmst du in deinem Fall am besten ne Liste (repeat with [variable] in [liste]), wo du gleich für rsync definierst, wo die Daten herkommen und wo sie hinsollen.

Wenn alles in den selben ordner sollte (was ich nicht denke - du musst es selber wissen), dann könnte man den rsync_target anteil komplett weglassen, eine Liste mit nur den Shares machen und als target für rsync einfach bspw. den common_target ordner nehmen.

Quasi so:
Code:
property protocol : "smb"
property server : "der-th-server" --name oder ip des servers
property common_target : "/Users/muesteff/Documents/Skripte" --der allgemeine pfad, wo deine skripte hin sollen der ordner sollte existieren

set shares to {"sharename_auf_dem_server1/ggf_unterordner", "sharename_auf_dem_server2/ggf_unterordner", "sharename_auf_dem_server3/ggf_unterordner"}


try
	do shell script "ping -c 1 " & server --gibt error wenn ping fehlschlägt
on error e
	display alert "Die Verbindung zu " & server & " konnte nicht hergestellt werden!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	return 1
end try

set sharecount to count of shares
set successcount to 0
repeat with aShare in shares
	
	try
		set mountpoint to mount volume (protocol & "://" & server & "/" & aShare) --generiert sowas wie afp://server1/share
		try
			--das hier ist zum testen. mach aus "-Pahvn" ein "-Pahv" wenn's funktioniert. das "n" macht einen sog. dry-run, zeigt also nur an, was gemacht werden würde, überträgt aber nix.
			set rsyncresult to do shell script "rsync -Pahvn" & space & quoted form of (POSIX path of mountpoint) & space & quoted form of common_target
			set successcount to successcount + 1
		on error e
			display alert "rsync von " & return & (POSIX path of mountpoint) & return & "nach" & return & rsync_target & return & "fehlgeschlagen." message e buttons {"Abbrechen", "Weiter"} cancel button 1
		end try
		set detachresult to do shell script "diskutil umount force " & (POSIX path of mountpoint) --mount auswerfen
	on error e
		display alert "mounten von " & return & protocol & "://" & server & "/" & aShare & return & "fehlgeschlagen." & return & return & "überprüfe den sharenamen!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	end try
	
end repeat
display dialog "gesynct: " & successcount & "/" & sharecount

Dann würde halt immer alles in /Users/muesteff/Documents/Skripte landen...
 

Whoution21

Pferdeapfel
Registriert
08.08.06
Beiträge
79
Danke für die Antwort!

Jedoch hängts bei mir schon an den ersten beiden Zeilen im Skript. Ich weiß nicht was ich für property protocol und property server eingeben muss. Ich habe schon einige Kombinationen durchprobiert, bekomme aber immer die Meldung, dass der Server nicht angepingt werden kann.

Der Zugriff über den Browser ist über "https://ftp.h-ab.de/info" möglich. Ich habe also als Server "https://meinbenutzername:[email protected]/info" angegeben. Diese Adresse kann ich in den Browser eingeben und ich komme auf den Server. Ist das soweit richtig? Oder habe ich schon hier einen Fehler gemacht? (Hier noch ein Link der FH, vielleicht hilft das ja: Externer Zugriff auf Laufwerke)
 

fyysh

Schweizer Glockenapfel
Registriert
25.01.10
Beiträge
1.386
Dude, vielleicht informierst du dich zunächst einmal was smb, afp, ftp und http(s) ist... und v.a. worin die Unterschiede liegen... ^^

Vorausgesetzt der FTP server lässt dich auf den root, klappt's so:
Code:
property protocol : "ftp"
property server : "ftp.h-ab.de" --name oder ip des servers
property common_target : "/Users/muesteff/Documents/Skripte" --der allgemeine pfad, wo deine skripte hin sollen der ordner sollte existieren

set shares to {"info/pfad/zum/ersten/ordner", "info/pfad/zum/zweiten/ordner", "info/pfad/zum/dritten/ordner"}


try
	do shell script "ping -c 1 " & server --gibt error wenn ping fehlschlägt
on error e
	display alert "Die Verbindung zu " & server & " konnte nicht hergestellt werden!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	return 1
end try

set sharecount to count of shares
set successcount to 0

try
	set mountpoint to mount volume (protocol & "://" & server) --generiert sowas wie ftp://server
on error e
	display alert "mounten von " & return & protocol & "://" & server & return & "fehlgeschlagen." & return & return & "überprüfe den sharenamen!" message e buttons {"Abbrechen", "Weiter"} cancel button 1
	return 1
end try

repeat with aShare in shares
	try
		set rsynclogname to do shell script "share_name=\"" & aShare & "\";echo ${share_name/\\//_}.rsync.log" --generiert aus "ein/ordner" => "ein_ordner.rsync.log"
		--das hier ist zum testen. mach aus "-Pahvn" ein "-Pahv" wenn's funktioniert. das "n" macht einen sog. dry-run, zeigt also nur an, was gemacht werden würde, überträgt aber nix.
		set rsyncresult to do shell script "rsync -Pahvn" & space & quoted form of ((POSIX path of mountpoint) & aShare) & space & quoted form of common_target & ">>" & quoted form of (common_target & "/" & rsynclogname)
		set successcount to successcount + 1
	on error e
		try
			display alert "rsync von " & return & (POSIX path of mountpoint) & return & "nach" & return & common_target & return & "fehlgeschlagen." message e buttons {"Abbrechen", "Weiter"} cancel button 1
		on error
			set detachresult to do shell script "diskutil umount force " & (POSIX path of mountpoint) --mount auswerfen
			return detachresult
		end try
	end try
end repeat

set detachresult to do shell script "diskutil umount force " & (POSIX path of mountpoint) --mount auswerfen

display dialog "gesynct: " & successcount & "/" & sharecount
return detachresult

Lässt er dich nicht auf den root, dann wirst du irgend nen apfelskriptbaren FTP-Client nehmen müssen. Cyberduck oder so...
So kannst du's testen (im Browser): ftp://meinbenutzername:[email protected]
Wenn das funktioniert, funktioniert das Skript oben auch (vorausgesetzt du setzt alle Pfade richtig).
 

Whoution21

Pferdeapfel
Registriert
08.08.06
Beiträge
79
Dude, vielleicht informierst du dich zunächst einmal was smb, afp, ftp und http(s) ist... und v.a. worin die Unterschiede liegen... ^^

Vorausgesetzt der FTP server lässt dich auf den root, klappt's so:
Code:
property protocol : "ftp"
property server : "ftp.h-ab.de"

Lässt er dich nicht auf den root, dann wirst du irgend nen apfelskriptbaren FTP-Client nehmen müssen. Cyberduck oder so...
So kannst du's testen (im Browser): ftp://meinbenutzername:[email protected]
Wenn das funktioniert, funktioniert das Skript oben auch (vorausgesetzt du setzt alle Pfade richtig).

Wie ich oben geschrieben habe, habe ich einige Kombinationen ausprobiert. Damit meinte ich Kombinationen aus URL und Protokoll. Jetzt, wo du das mit root geschrieben hast, wird mir aber klar warum es nicht klappt. Denn ich muss auf "ftp.h-ab.de/info/". Auf "ftp.h-ab.de" habe ich keinen Zugriff.

Mit meinem obigen Skript hat das ja auch unabhängig von einem FTP-Client funktioniert. Ich werde es wohl doch verwenden und die Variablen einfach raus lassen. Funktioniert trotzdem :)

Vielen Dank trotzdem für die Bemühungen! Ich habe wieder etwas gelernt :)