2009-10-31 17 views
6

私は毎晩cronjobで実行する予定のバックアップスクリプトを作成しています。Pythonの出力ファイルのリダイレクト

スクリプトはsys.stdoutとsys.stderrを出力ファイルに設定し、発生したログを記録します。私は、サブプロセスの呼び出しの前と後にprint文を追加し、次のコード

cmd = 'rsync -av --del --stats --filter "- .thumbnails/" ' + \ 
    '--filter "- *~" --filter "- *.iso" --filter "- lost+found/" ' + \ 
    '--filter "- .cache/" --filter "- tmp/" --filter "- *.mp3" ' + \ 
    '--filter "- *.log" ' + srcDir + ' ' + dstDir 

print "Executing '"+cmd+"' ..." 
try: 
    sys.stdout.flush() 
    sys.stderr.flush() 
    retcode = subprocess.call(cmd, stdin = sys.stdin, stdout = sys.stdout, 
     stderr=sys.stderr, shell=False) 
    if retcode < 0: 
     print >>sys.stderr, "Command was terminated by signal", -retcode 
    elif retcode > 0: 
     print >>sys.stderr, "Command returned code ", retcode 
except OSError, e: 
    print >>sys.stderr, "Execution failed:", e 

を使用するバックアップを行うには

。 問題は、呼び出し前に印刷指示の出力の前にサブプロセス呼び出しの出力を取得することです。私はflush()呼び出しを追加しましたが、効果はありません。

なぜこのようなことが起こりますか、どうやってこの動作を変更できますか?

+1

どのようにsys.stdoutとsys.stderrを設定していますか? – Ned

+1

これは正しいようで、そのように動作してはいけません(試しても動作しません)。環境(OS、シェルを起動するシェル)を記述できますか? – RedGlyph

+0

'rsnapshot'(' rsync'も使用しています)のような既存のツールを使わないのはなぜですか? – jfs

答えて

3

私はちょうどStackoverflowの答えで解決策を見つけましたhere

sys.stderr = sys.stdout = logFile = open(tmpLogFileName, 'a', 0) 

これは、ファイルに任意の出力バッファを割り当てないためにのpythonを伝えて

sys.stderr = sys.stdout = logFile = open(tmpLogFileName, 'a') 

を交換してください。

+2

しかし、これはあまりにもすぐにあきらめている! :-)なぜflush()が動作していないのかを理解するのを手助けしたい。バッファリングをオフにしただけでは、実際の問題は何であれ固定されません。 :-) –

+0

:]それは解決策です。私はあきらめていませんよ。私は本当の問題は内部が平らだと思う。これを調べて解決することは、私の能力と必要性を超えています。 – chmike

+0

それは面白い落とし穴でした。うれしいことにあなたはそれを打ち倒しました:-) – RedGlyph

0

tryブロックの外側にフラッシュ呼び出しを入れてみましたか?

+2

いいえ、これは出力の動作に影響しないはずです。フラッシュは実際にはフラッシュされていないように見えます。 print "Executing"命令に>> sys.stdoutを追加しても、動作は変更されません。 – chmike

0

なぜあなたはstderrに印刷していますか? stderrに書き込んでいるときにサブプロセスがstdoutに書き込んでいる場合、それは奇数のインターリーブを説明することができます。

+2

呼び出されたコマンドが終了するまで、呼び出しブロックを仮定します。それ以外の場合、私はリターンコードを取得することができません。 – chmike

+0

あなたが言っているように、呼び出しはブロックされますので、戻りコードを取得できます。しかし、それはあなたが標準エラー出力に印刷する理由を説明していません。サブコマンドと同じファイルを使用すると、おそらく出力が適切にインターリーブされます。 –

+1

プログラムの先頭に 'sys.stdout = sys.stderr = logFile = open( "/tmp/backup.log"、 "a")という命令があるので、同じファイルを使用しています。 stdout = sys.stdoutなどを指定すると、ログファイルが呼び出されたコマンドのstdoutファイルとして設定されます。できます。flush()が実際にバッファされたデータをディスクに書き込んでいないことだけです。 – chmike

関連する問題