13

bashとzenityを使用したgit://リンクのグラフィカルURIハンドラーを作成し、zenityの「text-info」ダイアログを使用して、実行中にgitのクローン出力をFIFO配管を使用して表示しています。スクリプトの長さは約90行なので、ここに投稿する必要はありませんが、最も重要な行は次のとおりです。

git clone "$1" "$target" 2>&1 | cat >> /tmp/githandler-fifo &
cat /tmp/githandler-fifo | zenity --text-info --text='Cloning git repository' &

直接パイプの代わりにFIFOを使用して、非同期で実行できるようにし、zenityウィンドウが閉じている場合にgitを強制終了できるようにします。

問題は、gitの出力から表示される唯一の行が最初の行であるということです。

Initialized empty Git repository in /home/delan/a/.git/

カウントオブジェクトなどを含む他の行は、端末に表示されないか、表示されます。

現在の理由

これが機能しない理由に関する現在のコンセンサスは、catブロッキングがなく、最初の行の後で終了し、残りの行ではなく、zenityに渡すだけであるようです。私の目的は、読み取りを強制的にブロックし、zenityのテキスト情報ダイアログにすべての出力を段階的に表示させることです。

gitstderrに進行状況メッセージ(「初期化」メッセージ以外)を出力しますが、stderrをファイルにパイプするか、stdoutとマージしようとすると、メッセージが消えます。

修正の試み1

私は次のように、Cでcatの関数の2つのブロッキングバージョンであるbreadとbwriteを書き込もうとしました。

#include <stdio.h>
main(int argc, char **argv) {
    int c;
    for (;;) {
        freopen(argv[1], "r", stdin);
        while ((c = getchar()) != EOF)
            putchar(c);
    }
}

#include <stdio.h>
main(int argc, char **argv) {
    int c;
    for (;;) {
        freopen(argv[1], "w", stdout);
        while ((c = getchar()) != EOF)
            putchar(c), fputs("writing", stderr);
    }
}

EOFをブロックして終了しないため、うまく機能しますが、まだ問題は完全には解決されていません。現時点では、一方、他方、または両方を使用することは理論的には機能しますが、実際には、zenityは現在何も示していません。

修正の試み2

@mvdsは、通常のファイルをtail -fではなくと組み合わせて使用​​するとcat、これが可能になることを示唆しています。そのような単純な解決策に驚いた(ありがとう!)私はそれを試しましたが、残念ながら、最初の行だけが天頂に現れ、他には何もありませんでした。

修正の試み3

いくつかのstrace'ingを実行し、gitのソースコードを調べた後、gitがすべての進行状況情報(「Initialized」メッセージを超えるもの)をstderrに出力すること、およびこれが最初の行であるという事実と、それが猫のせいであるという私の仮定に気付きました。 EOFの早い段階で終了することは、偶然/誤った仮定でした(gitはプログラムが終了するまでEOFを実行しません)。

(質問の最初の)元のコードから何も変更する必要がなく、機能するはずなので、状況ははるかに単純になっているように見えました。しかし、不思議なことに、リダイレクトされるとstderrの出力は「消える」-これはgitで発生することだけです。

テストケース?これを試して、ファイルに何かが表示されるかどうかを確認してください(表示されません)。

git clone git://anongit.freedesktop.org/xorg/proto/dri2proto 2> hurr

これは、stderrとリダイレクトについて私が知っているすべてに反します。stderrとstdoutに出力する小さなCプログラムを作成して、リダイレクトがgitでは機能しないことを自分自身に証明しました。

修正の試み4

JakubNarębskiの答えに沿って、そして私がgitメーリングリストに送信した電子メールへの返信--progressは、私が必要とするオプションです。このオプションはコマンドの後でのみ機能し、の前では機能しないことに注意してくださいclone

成功!

本当にありがとうございました。これは固定電話です:

git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 &

4

3 に答える 3

19

出力がターミナル(tty)でない場合、進捗レポートの少なくとも一部が無音になると思います。それがあなたのケースに当てはまるかどうかはわかりませんが、--progressオプションを「git clone」に渡してみてください(つまり、use git clone --progress <repository>)。

それがあなたが欲しかったものかどうかはわかりませんが。

于 2010-10-31T15:13:19.087 に答える
6

一つには、出力リダイレクトは右から左に解析されるので、

git clone "$1" "$target" 2>&1 > /tmp/githandler-fifo &

と等しくない

git clone "$1" "$target" > /tmp/githandler-fifo 2>&1 &

後者は、stderrをstdoutにリダイレクトし、次にstdout(stderrを含む)をファイルにリダイレクトします。前者はstdoutをファイルにリダイレクトし、stdoutにstderrを表示します。

zenity(私にはわかりませんが)への配管に関しては、名前付きパイプで物事を過度に複雑にしているのではないかと思います。を使用straceすると、起動しているプロセスの内部動作に光を当てることができます。経験の浅い人にとっては、名前付きパイプは通常のパイプに比べて事態を悪化させます。

于 2010-10-31T12:10:36.933 に答える
1

'a'と呼ばれるFIFOを使った実験を考えると、問題はzenityが入力を処理する方法にあると思います。キーボードからzenityと入力するとどうなりますか?(疑わしい:EOFを読み取って、希望どおりに動作します。)ただし、zenityは通常のブロッキングI / Oを使用して端末入力(tty入力)を処理しますが、他のすべてのデバイスタイプには非ブロッキングI/Oを使用する可能性があります。ノンブロッキングI/Oは、ファイルからの入力に適しています。パイプやFIFOなどからの入力にはあまり望ましくありません。ノンブロッキングI/Oを使用した場合、zenityは出力の最初の行を取得し、2回目の読み取り試行で次のことを示すため、実行されたと考えてループを終了します。すぐに利用できるものは他にありませんでした。

これが起こっている(または起こっていない)ことを示すのは難しいでしょう。zenityが何をしているかを追跡するために、「truss」または「strace」または他のシステムコールモニターを探しています。

回避策については...仮説が正しければ、FIFOではなく端末から読み取っていることをzenityに説得する必要があるため、おそらく疑似tty(またはpty)を装備する必要があります。最初のプロセスはptyのマスター側に書き込み、Zenityがptyのスレーブ側から読み取るように調整します。それでもFIFOを使用する可能性がありますが、コマンドのチェーンが長くなります。

于 2010-10-31T18:12:31.283 に答える