Die Programmiersprache Ruby

Blog|

Forum|

Wiki  


Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]

Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
BeitragVerfasst: 14 Apr 2012, 17:03 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Hallo zusammen,

trotz gründlicher Recherche (ich mach damit schon 5-6 h rum) habe ich ein Problem mit Dir.Entries, das ich nicht lösen kann... Hoffe, es weiss jemand Rat...

Ich erstelle ein Backup-Skript und an einem gewissen Punkt möchte ich alle Ordner, die innerhalb meines Ordners "Backup" auf dem Server sind, abfragen. Hintergrund ist, dass immer nur eine bestimmte Anzahl von Backups auf dem Server bleibt, und die älteste Sicherung bei der Erstellung eines neuen Backups gelöscht wird.

Mein Vorgehen sieht wie folgt aus: Den kompletten Ordnerinhalt in ein Array packen. Danach die Einträge ".", ".." und "mails" aus dem Array löschen. Danach die Einträge nach Datum sortieren. Anschließend prüfen, ob Backup-Grenze erreicht ist, wenn ja, ältestes Backup löschen nachdem das neue Backup erstellt wurde.

Nun habe ich bereits am Anfang Probleme, den Ordnerinhalt ins Array zu packen. Mein Code sieht wie folgt aus...



1
2
3
4
sftp.dir.entries("/home/#{SSH_USER}/#{BACKUP_ROOT}").each do |filename|
backup_list.push(filename)
end
puts backup_list


Der Terminal meines Macs gibt mir aber nur folgendes aus:

#<Net::SFTP::Protocol::V01::Name:0x10a204530>
#<Net::SFTP::Protocol::V01::Name:0x10a203c70>
#<Net::SFTP::Protocol::V01::Name:0x10a2034f0>
#<Net::SFTP::Protocol::V01::Name:0x10a202d70>
#<Net::SFTP::Protocol::V01::Name:0x10a2025f0>

Das Array kann befüllt werden, es sind jedoch keine Ordnernamen drin, sondern nur ich denke mal die Adressen... Weiss jemand wie ich mein Problem lösen kann??

BTW: Hat jemand für mein Vorhaben eine elegantere Lösung? Kann ich vielleicht mehrere Schritte durch Ruby zusammenfassen?!

Fragen über Fragen eines Ruby-Neulings, der bisher mit Java und Objective-C das Vergnügen hatte...

Vielen Dank schon mal für Antworten und Vorschläge!!

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 14 Apr 2012, 18:21 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
Hi,

grundsätzlich ist das richtig. Die zeilenweise Ausgaben kommt daher, dass Arrays aus historischen Gründen zeilenweise in Strings verwandelt werden. Wenn du "backup_list.inspect" verwendest, kriegst du auch die Struktur angezeigt.

Du musst aufpassen: 'entries' gibt keine Strings zurück, sondern Objekte des Typs Name (http://net-ssh.github.com/sftp/v2/api/classes/Net/SFTP/Protocol/V01/Name.html) . Der Dateiname ist dann in #name zu finden und die Eigenschaften findest du in #attributes. (#irgendwas ist die in Ruby übliche Notation für eine Instanzmethode).

Das gesonderte "in ein array packen" kannst du dir allerdings sparen: entries ist bereits ein Array. Aber das Filtern kann ich dir zum Beispiel grob vorzeichnen:



1
2
3
filtered_entries = sftp.dir.entries("/home/#{SSH_USER}/#{BACKUP_ROOT}").reject do |file|
%w(. .. mails).include?(file.name)
end


Gruß,
Skade


Nach oben
 Profil  
 
BeitragVerfasst: 15 Apr 2012, 08:45 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Hallo und vielen Dank... Das hat mir sehr geholfen, habe mein Skript nun fast abschliessen können. Fehlt nur noch das Löschen eines Ordners, da nutze ich folgenden Code:


1
2
3
4
if existing_backups.size > NO_OF_BACKUPS         
sftp.rmdir("/home/#{SSH_USER}/#{BACKUP_ROOT}/" + existing_backups[0].name)
backup_deleted = true
existing_backups.pop

Ich habe ein sortiertes Array nach Datum. Ich nehme den ältesten Eintrag und setze ihn in sftp.rmdir ein. Danach wird ein Flag auf true gesetzt und die Größe des Arrays um eins gemindert. Leider wird der Ordner aber nicht gelöscht. Weiss jemand woran das liegt bzw. wie ich einen Ordner löschen kann??

BTW: Ich konnte die Gems Net-SSH und Net-SFTP auf meinem Macbook nicht in dem Standard-Ordner installieren, sodass ich sie in meinem Benutzerordner installieren musste. Bei jedem Start meines Skripts muss ich nun im Terminal:

export GEM_HOME=/Users/antonios/RubyGems
ruby -rubygems /Volumes/BUSINESS/Projekte/myBackupScript/myBackup.rb

eingeben. Bisher reichte immer nur

/Volumes/BUSINESS/Projekte/myBackupScript/myBackup.rb


Gibt es eine Möglichkeit, das wieder so zu haben?? Also nur /Volumes/BUSINESS/Projekte/myBackupScript/myBackup.rb in den Terminal einzugeben und das Skript zu starten?!? Habe zwar einige Anleitungen dazu bei Google gefunden, aber keine hat geholfen...

Vielen Dank schon mal im Voraus!

Grüße

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 05:32 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Habe einige Beispiele mit Fileutils gefunden, sie aber nicht zum Laufen bekommen. Damit muesste es theoretisch gehen, oder? Koennte mir bitte jemand aufzeigen, wie ich damit Ordner loeschen kann?? Die Namensuebergabe des Ordners durch das Array sollte richtig sein, oder??

Vielen Dank!!

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 11:04 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Vielen Dank Skade,

folgendermassen habe ich den Server eingebunden:


1
2
Net::SSH.start("#{SSH_SERVER}", "#{SSH_USER}") do |ssh|
ssh.sftp.connect do |sftp|


Also uber SFTP... Wie kann ich denn uber SFTP Verzeichnisse loschen?? Es muss doch irgendwie uber sftp.irgendwas gehen... Aber vor allem, wie gebe ich den Pfad auf dem Server, der geloscht werden soll, korrekt an (BTW: Ordner der geloscht werden soll, ist nicht leer)?!

BTW: Umlaute klappen leider nicht...

Vielen Dank!

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 11:22 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
Die SFTP-FAQ sagt dazu, dass du #rmdir verwenden sollst:

http://net-ssh.github.com/sftp/v1/faq.html#2202612

Du musst allerdings aufpassen, #rmdir verlangt, dass das Verzeichnis leer ist:

http://net-ssh.github.com/sftp/v2/api/classes/Net/SFTP/Session.html#M000145


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 11:30 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Hallo,

und vielen Dank. Das heisst ja dann, dass mein Code soweit passt, nehme ich an. Deshalb wohl auch keine Fehlermeldung im Terminal. Allerdings sind in dem Ordner ca 300 andere Ordner und alles verschachtelt. Gibt es eine Moglichkeit wie rm -r im terminal? Oder wie kann ich den Ordner sonst so geschickt wie moglich leeren? An dieser Ordner-Geschichte kann man glaube ich echt verzweifeln... :cry:

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 11:39 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
Das kann SFTP nicht :). Am einfachsten listest du dir alle Dateien unter dem Verzeichnis auf und löschst sie dann einzeln.

Aber da du ssh-Zugriff hast, kannst du auch den schnellen Weg nehmen und rm -rf per SSH ausführen.



1
2
3
4
Net::SSH.start('host', 'user', :password => "password") do |ssh|
# capture all stderr and stdout output from a remote process
output = ssh.exec!("rm -rf #{folder}") #aufpassen! erstmal mit was bravem wie ls testen
end


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 15:10 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Hallo,

und vielen Dank. Nachdem ich Probleme hatte, alle Files aufzulisten und einzeln zu löschen, habe ich mich an den vereinfachten Vorschlag gemacht, und siehe da, es läuft. Falls es jemanden interessiert, wie das komplette Skript aussieht, oder er Verbesserungsvorschläge hat, es ist in github unter https://github.com/as5/Backup/blob/master/myBackup.rb zu erreichen.

Nochmals danke für die Hilfe!

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 15:24 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
Das sieht sogar recht sauber aus. Einen nitpick habe ich: in Ruby ist 2-spaces und snake_case standard, statt 4 spaces und lowerSnakeCase. Das kann natürlich am Ende jeder machen, wie er will :).


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 15:28 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Danke, progge etliche Jahre in Java und Obj-C, von daher ist mir sauberes Coden geläufig und wichtig ;-) du meinst 2 Leertasten beim einrücken? ich habe momentan 3, aber an Standards halte ich mich gern. Und diese Benennung mit den Unterstrichen, bezieht sich das auf alles, oder nur Methoden oder nur Variablen, etc.?

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 16 Apr 2012, 16:01 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
as5 hat geschrieben:
Danke, progge etliche Jahre in Java und Obj-C, von daher ist mir sauberes Coden geläufig und wichtig ;-) du meinst 2 Leertasten beim einrücken? ich habe momentan 3, aber an Standards halte ich mich gern. Und diese Benennung mit den Unterstrichen, bezieht sich das auf alles, oder nur Methoden oder nur Variablen, etc.?


Methoden und Variablen. Konstanten für Klassen und Module werden in SnakeCase geschrieben, sonstige Konstanten in SCREAMING_SNAKE_CASE (Ruby erkennt übrigens am führenden Großbuchstaben, dass es eine Konstante ist).

Github hat einen sehr guten Ruby-Styleguide, der eigentlich fast alles abdeckt: https://github.com/styleguide/ruby


Nach oben
 Profil  
 
BeitragVerfasst: 17 Apr 2012, 05:04 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Vielen Dank, sollte ich in den naechsten Tagen Zeit finden, werde ich den Code ueberarbeiten, damit er den Coding Conventions entspricht.

Mal aber eine andere Frage in die Runde: Wenn das Backup kurz dauert, also wenig Daten, laeuft es problemlos. Wenn das Backup allerdings gross ist, wie gestern herausgefunden, dann wird das Backup zwar erstellt, allerdings werden die Statistiken nicht mehr ausgegeben, sondern eine Fehlermeldung wegen unterbrochenener Verbindung zum Server angezeigt. Gibt es eine Moeglichkeit, die Session so lange zu erzwingen, bis ich sie manuell beende?

Ansonsten nochmals danke, Ordner loeschen klappt wunderbar...

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
BeitragVerfasst: 17 Apr 2012, 10:11 
Offline
Interpreter
Benutzeravatar

Registriert: 03 Jul 2006, 14:53
Beiträge: 4847
Wohnort: RLP
Hast du mal mit den Alive-Intervals gespielt?

http://fredericiana.com/2009/10/21/keeping-ssh-from-disconnecting-automatically/


Nach oben
 Profil  
 
BeitragVerfasst: 17 Apr 2012, 10:16 
Offline
Novize

Registriert: 14 Apr 2012, 16:48
Beiträge: 15
Wohnort: Kuala Lumpur, Malaysia
Vielen Dank, das scheint genau das zu sein, was ich brauche. Werde ich nach der Arbeit gleich mal testen... Noch 1 Stunde... :(

_________________
If Not Program.IsWorking Then Code.Debug Else Code.DoNotTouch


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite 1, 2  Nächste

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 0 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach: