teeを使用してGitHubのパイプライン出力を複製すると、出力が失われます。

teeを使用してGitHubのパイプライン出力を複製すると、出力が失われます。

GitHubリポジトリクローンの出力をファイルに書き込む必要があると思いました。走れば

git clone [email protected]:my_repo/my_repo.git | tee -a log

空のファイルが得られましlogたが、コマンドライン出力は次のとおりです。

Cloning into 'my_repo'...
remote: Enumerating objects: 284, done.
remote: Counting objects: 100% (228/228), done.
remote: Compressing objects: 100% (133/133), done.
remote: Total 284 (delta 122), reused 162 (delta 69), pack-reused 56
Receiving objects: 100% (284/284), 873.22 KiB | 2.71 MiB/s, done.
Resolving deltas: 100% (138/138), done.

これは私にとって少し謎になりました。私の考えでは、ファイルとファイルの両方をstderrパイピングする必要があるようです。stdout

git clone [email protected]:my_repo/my_repo.git 2>&1 | tee -a log

これでlogファイルとコマンドラインの両方

「my_repo」に複製...

私がここで何を見逃しているのでしょうか?このremote: ...行をファイルに入れることはできますかtee

答え1

コメントで述べたように、gitstdout / errorが端末であることを確認してください。その場合、プログラムはターミナル出力に追加の砂糖を追加して、進行状況といくつかの統計をテキスト形式で表示します。それ以外の場合は、標準ストリームへの出力を最小限に抑えます。

内部的にはisatty() たとえば、ここに記載されています。。これはコマンドラインプログラムの一般的な慣行です。最も重要なのは、ANSIの色を削除することです。通常、ファイルに色を入れたりパイプ処理を混乱させたりしたくないからです。たとえば、次のことを確認してください。

/bin/ls --color=auto -1 # ls print column in pipe
/bin/ls --color=auto | sed -n 'l'
/bin/ls --color=always | sed -n 'l'

常に抑制または常に印刷してgitそれを無視するオプションがあります。進行状況出力は印刷され(通常は)消費には使用されません。それにもかかわらず:-q--quiet--progressstderr

git clone --progress foo/bar.git 2>&1 | tee log

他のプログラムには同様のオプションがない可能性があり、データを取得するにはいくつかの手順が必要です。これは自動化スクリプトなどを最小限に抑えるために行われますが、それでも印刷されますが、stderrエラーメッセージに減ります。例えばgit:

$ git clone -q https://nonexistig-url.com/foo.git
fatal: https://nonexistig-url.com/foo.git/info/refs not valid: 
       is this a git repository?
$ echo $?
128

何の進行も行われませんが、通常、次の場合に発生するエラー メッセージが表示されます。後で想像する。複製プロセス自体の進行が抑制される。

場合によっては、後処理や他のコマンドや追加のコマンドの実行など、他の方法で情報を取得することもあります。たとえばgit count-objects -v


偽の端末

出力を本当に抑制したいプログラムにこのようなオプションがない場合git、一つのオプションは、プログラムが端末に書かなくても「考える」ようにすることです。これを達成するためのさまざまな方法の1つは、一時的なアイテムに使用する方法の1つは、何らかの理由でそのアイテムを交換することです。システムisatty()常に true を返します。

echo 'int isatty(int fd) { return 1; }' | \
gcc -O2 -fpic -shared -ldl -o faketty.so -xc -

strip faketty.so
chmod 400 faketty.so

次のラッパースクリプトと一緒に使用してくださいfaketty

#! /bin/sh -
LD_PRELOAD=/path/to/faketty.so "$@"

次のように使用されます。

faketty git clone foo

コードが示すように、実際にはファイル記述子のチェックなどを実行せず、単にハッキングです。


データ生成の問題

このgit cloneコマンドは出力に色を割り当てませんが、進行状況を表示します。これを行う方法は、端末で同じ行を繰り返し上書きすることです。通常は次のようになります。

Cloning into 'foo'...\n
remote: Enumerating objects: 236, done.        \n
\rReceiving objects:   0% (1/236)   
\rReceiving objects:   1% (3/236)   
\rReceiving objects:   2% (5/236)   
...
\rReceiving objects:  79% (187/236)   
\rremote: Total 236 (delta 0), reused 0 (delta 0), pack-reused 236        \n
...
\rReceiving objects:  99% (234/236)   
\rReceiving objects: 100% (236/236)   
\rReceiving objects: 100% (236/236), 79.45 MiB | 104.73 MiB/s, done.\n
...

ここでは、\rEnterと同様に、端末にカーソルを移動するように指示します。行の始まり改行/行末とは異なり、カーソルを\n行の先頭に移動します。次の行

結果は毎回記録されます書くremote: Total 236 …前の行から最後の行まで、\nプロセスが次の行から続く場合、結果はビューアに次のように表示されます。

Cloning into 'foo'...
remote: Total 236 (delta 0), reused 0 (delta 0), pack-reused 236        
Receiving objects: 100% (236/236), 79.45 MiB | 104.73 MiB/s, done.
...

各書き込みの視覚的な進行状況が含まれます。この場合、cat端末がキャリッジリターンを解釈すると、単純なログは大丈夫に見えますが、sed -n l log実際の内容は表示されます。オプションの類似sed 's/\r/\n/g' logディスプレイ「ワイヤー」

掃除する

についてはこの場合、そのまま単純なパイプまたはログスロットの後処理でsed十分です。

sed 's/.*\r//'
# Optionally to trim trailing white space, either of:
sed 's/.*\r//;s/ \+$//'
sed 's/.*\r\| \+$//g'

リリース、バージョンなどによって進行状況の出力が変わる可能性があるため、やや脆弱であるため、情報が同じであることは保証されません。出力に色がある場合は、これらのシーケンスをさらに削除する必要があります。

表示された進行状況(ライブカウント)が失われ、gitコマンドが実行される前にパイプに接続されたときにのみ最終結果が得られます。sedtee

関連情報