(この質問がStackOverflowにあるのか、ここにあるのかわかりませんが、実際の質問は一般rsync
的にLinuxの問題だと思います。管理者が同意しない場合は必ず移行してください。)
私はrsync
別のプログラム(この場合はRubyで書かれていますが、他の言語でも簡単に書くことができます)で実行して出力を1行ずつキャプチャしようとしています。
(Rubyでは、以下を介して行われます。Open3#popen3
そしてIO.select
着信電話。 Pythonでは、人々がasyncio.create_subprocess_shell
。 )
しかし - 私が出会った他のほとんどすべての端末コマンドとは異なり -rsync
絶対に拒否するこのように実行すると(つまり、実際のttyを持つ端末で実行されていない場合)、出力は1行ずつ書き込まれます。代わりに出力を「バッファリング」し、最後にのみ出力します(またはおそらくバッファがいっぱいになったとき)。おそらくflush
パイプではないですか?理由が何であれ、これは深刻な問題です。これは、私のスクリプトがユーザーに進行状況メッセージ(パーセントなど)を表示できないことを意味します。代わりに、最大1時間(または手術にかかる時間)、完全なワイヤレスサイレントを見ることができます。
--outbuf=L
まさにこの状況に対してこのパラメータが存在することを読んでいます。しかしそれは動作しません。少なくとも私のrsyncバージョン3.2.7ではそうです。
インターネットの誰かがこのパラメータを--msgs2stderr
提案しましたが、それも役に立ちませんでした。
修正されたバージョンを使用して、これがRubyの問題ではないことを確認するためにPythonで簡単なテストを作成しました。このサンプルコード。結果は同じで、rsyncに問題がある可能性があります。
だから私の質問は簡単です。どうすればいいですか?力rsyncは「保存」して最後に1つの大きなダンプとして印刷するのではなく、1行ずつ進行メッセージを出力しますか?
追加のガイドライン
ローカルで実行していますrsync
。以下は、私が使用する正確なコマンドの例です。
rsync --verbose --msgs2stderr --progress --relative --links
--hard-links --perms --owner --group --times --sparse
--one-file-system --human-readable --delete --delete-excluded
--recursive --prune-empty-dirs --outbuf=L --from0
'/mnt/data' '/mnt/backup'
--exclude-from=/tmp/rsbackupexclusionlist20230816-2064241-6nghn7
apt-get
私のRubyコードが、またはなどの他のプログラムで正しく機能していることを確認できますgit
。 (私も知らず、テストしたこともありません。)make
debootstrap
yes
また、私の研究では、rsync
接続されたPTYが検出されないと、STDOUTまたはSTDERR出力が正しくフラッシュされません。
それ以来、私はPTYを生成し、コマンドの出力チャネルをここに接続するrsync
Rubyの正しく文書化されていないディレクティブを介して実行に成功しました。PTY.spawn
しかし、それは理想的ではありません。一方では、STDOUTとSTDERRを単一のストリームに結合します。
他の多くのソフトウェアが「ただ動作する」場合、なぜうまくrsync
動作しないのでしょうか?を使用せずに動作させる方法はありますかPTY.spawn
?
なぜ--outbuf=L
何もしないのですか?
答え1
私はこれを複製できません。
私はrsync 3.2.7を使用しており、stderrをキャッチするPythonスクリプトで実行しています。最後まで待たずにすぐに出力を表示します。
まったく同じrsyncオプションを使用していませんが(例外リストを処理しません)、関連オプションはすべて使用されているようです。 (含めるかどうかは関係ありません)--outbuf=L
。
このプログラムでそれを複製できることを確認してください。
import subprocess
import sys
s = subprocess.Popen(["rsync", "-av", "--msgs2stderr", "--outbuf=L", "--progress", "lots_o_files/", "lots2/", ], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while (True):
nextline = s.stderr.readline()
if nextline == b'' and s.poll() is not None:
break
sys.stdout.write(nextline.decode())
sys.stdout.flush()
出力:
sending incremental file list
8m28V3/qG81EA/TViGDb/
8m28V3/qG81EA/TViGDb/XOarqQ.txt
755 100% 0.00kB/s 0:00:00 (xfr#1, ir-chk=1008/15161)
8m28V3/qG81EA/TViGDb/Zhe0F6.txt
742 100% 724.61kB/s 0:00:00 (xfr#2, ir-chk=1007/15161)
8m28V3/qG81EA/TViGDb/a1B3ha.txt
847 100% 827.15kB/s 0:00:00 (xfr#3, ir-chk=1006/15161)
...
出力がすぐに印刷される場合、rsyncはTTYなしで即座に出力を生成する必要があります。これが最後まで待っていた場合、私たちのシステムは少し異なります(または私がコピーしていないrsyncオプションが関連しています)。