2009-03-23 14 views
2

Ich möchte alle Fortschrittsmeldungen erfassen, die von einem rsync-Prozess von einem Perl-Skript ausgegeben werden. Unter bestimmten Umständen funktioniert das nicht.Wie kann ich Rsync-Fortschrittsnachrichten in Perl erfassen?

Hier ist eine typische rsync Befehlszeile Ich verwende:

Building file list ... 
1600 files... 
1700 files... 
and so on 

Wenn ich versuche, den gleichen Befehl:

rsync -aL --verbose --progress --bwlimit=100 \ 
    --include-from=/tmp/78hJ2eDCs1 \ 
    --include '*/' --exclude '*' \ 
    /srcdir/* \ 
    hostname:/target/ 2>&1 

Wenn ich dies in einer Bash-Shell laufen, ich etwas sehen werde Innerhalb von Perl bekomme ich die Ausgabe der "Dateiliste erstellen" OK, aber nicht die Statusaktualisierungen. Hier ist, wie ich die Capture-Test

my $pid = open(OUTPUT, "$cmd |") or die "Couldn't fork: $!\n"; 

my $ch; 
while(read(OUTPUT, $ch, 1)==1) 
{ 
    print $ch; 
} 
close(OUTPUT); 

Meine Vermutung ist, dass entweder rsync den Ausgang Griff spürt ist keine typische Konsole oder ausgegeben in einige ungewöhnliche Art und Weise zu sein, dass ich nicht zu erfassen. Was es jedoch noch seltsamer macht, ist, dass ich, wenn ich die Filter --include und --exclude weglasse, die Statusnachrichten gut erfassen kann.

Wer irgendwelche Hinweise, was vor sich geht?

+0

Nachdem die zwei Antworten bereits zur Verfügung gestellt wurden, vermute ich, dass es etwas ist, das rsync tut, um die Ausgabe zu puffern. Erhalten Sie die gesamte Ausgabe am Ende? –

Antwort

3

Stellt sich heraus, die Lösung war einfach - ich musste nur die IO in meinem Skript unbuffer mit $| = 1;

ich immer noch verwirrt bin, wie ich das Problem mit einigen rsync Optionen beobachtet und andere nicht. Danke Paul Tomblin und dsm, dass sie mir Ideen gegeben haben.

+0

Lustig, dachte ich $ | und -> autoflush waren gleichwertig, deshalb habe ich es vorgeschlagen. –

+0

Ich vermute, dass Autoflush auf den OUTPUT-Handle wirkte, während $ | handelte auf den Skripten STDOUT? d. h. irgendwie habe ich einfach nicht die Ausgabe gespült bekommen? –

4

Puffert Perl die Ausgabe von Rohren? Wenn dies der Fall ist, können Sie das Problem möglicherweise beheben, wenn Sie nach dem Öffnen des OUTPUT-Handles die Pufferung mit OUTPUT-> autoflush (1) ausschalten;

+0

Ich habe versucht, ohne Erfolg - die seltsame Sache ist, dass ich * kann * die gesamte Ausgabe erfassen, wenn ich nicht die --include/exclude-Optionen verwenden. –

4

können Sie Expect.pm verwenden, die ein PTY nachahmt, das Ihnen die Ausgabe geben kann, nach der Sie suchen.

Andernfalls können Sie die Optionen --stats oder --progress versuchen.

+0

Ich bin mir nicht sicher, ob ich iterativ nur die Ausgabe mit Expect essen kann, aber die Idee, eine Pseudo-TTY nachzuahmen, könnte sich als fruchtbar erweisen ... wird das untersuchen. –

+0

Nein, ich habe versucht mit IO :: Pty :: Easy und ich sah das gleiche Verhalten –

0

Sie könnten auch IPC :: Run und Callbacks für Daten auf stdout/stderr verwenden.

0

Suffering from Buffering? ist die beste Erklärung über Pufferwirkung, die ich bisher gefunden habe. Es lohnt sich die Zeit zu lesen und zu verstehen.

Vergessen Sie nicht, dass die Pufferung aus einem bestimmten Grund da ist, also blenden Sie es nicht für jedes mögliche Problem ab.

Verwandte Themen