コマンドラインを使用して作業するときは、いくつかの入力ストリーム仕様のさまざまなインスタンスに対して同じ操作を指定し、特定の方法でその出力を再結合したい場合がよくあります。
昨日の2つのユースケース:
PEMファイルにバンドルされているSSL証明書の束のタイトルを見たいです。
cat mypemfile.crt | (openssl x509 -noout -text | fgrep Subject:)
最初の項目のみが表示されます。証明書を分割し、各証明書に対して同じコマンドを実行して、結果をリンクする必要があります。
csplit
分割できますが、ファイルにのみ分割できます。これは面倒なことです。なぜ言うことができないのですか
cat mypemfile.crt | csplit-tee '/BEGIN/ .. /END/' | on-each ( openssl x509 -noout -text | fgrep Subject: ) | merge --cat
?
JupyterHubインスタンスを実行し、ノートブックサーバーをDockerコンテナに分割します。タイムスタンプが表示されたログを見たいです。コンテナの場合、これは簡単です。
sudo docker logs -t -f $container_id
(
-t
タイムスタンプを追加して-f
パイプを開けてくださいtail -f
。)タイムスタンプでソートすることで、すべてのコンテナのログを簡単に一覧表示できます。
sudo docker ps | awk '{print $1}' | while read container_id do sudo docker logs -t $container_id done | sort
または
sudo docker ps | awk '{print $1}' | xargs -n1 sudo docker logs -t | sort
または
sudo docker ps | awk '{print $1}' | parallel sudo docker logs -t {} | sort
-f
ただし、これらのいずれもログを表示するためにそのオプションを使用することはできません。なぜ使用できないのですか?
sudo docker ps | awk '{print $1}' | csplit-tee /./ | on-each (xargs echo | sudo docker logs -t -f) | merge --line-by-line --lexicographically
または
sudo docker ps | awk '{print $1}' | parallel --multipipe sudo docker logs -t -f {} | merge --line-by-line --lexicographically
?
明らかにこれは必要です
- 特定のシェルサポート。たぶん、独自の「マルチパイプライン」シンボルが必要な場合があります。
- パイプラインの分割とマージのための新しいツール(
csplit-tee
および)on-each
。merge
- シェルが並列パイプとして処理するようにツール内で入力および出力ファイル記述子を必要な数だけ指定する方法の規則が修正されました。
これが完了しましたか?それとも私のユースケースに適用できるものと同等ですか?
特定のカーネルサポートなしでこれは可能ですか?カーネルには通常、開いているファイル記述子の最大数が固定されていることがわかりますが、実装では盲目的にすべてのファイル記述子を一度に開こうとしないことでこの問題を解決できます。
知ってみれば可能だろうか?GNUパラレル可能ですか?
答え1
GNU並列処理を使用する:
cat mypemfile.crt |
parallel --pipe -N1 --recstart '-----BEGIN' 'openssl x509 -noout -text | fgrep Subject:'
テストされていません:
sudo docker ps | awk '{print $1}' |
sudo parallel -j0 --lb docker logs -t -f {}
sudo docker ps | awk '{print $1}' |
sudo parallel -j0 --tag --lb docker logs -t -f {}
答え2
いいえ、シェルはそうすることはできません。パイプは通常、他のプロセスからソースからターゲットへの単純なストリームです。
最初の例を見てみましょう。
cat mypemfile.crt |
(openssl x509 -noout -text | fgrep Subject:)
BEGINとENDを含む行に沿って入力ファイルを分割したいのですが、cat
内容は気にせず、パイプにはレコード区切り文字の範囲外のマークはありません。
パイプラインソースとターゲットの特定のルールを使用してこれを達成できますが、これにより、作成者が意図しない操作を実行するためにプログラムをビルディングブロックに結合する機能であるパイプラインの主な利点が排除されます。
openssl
この特定の例では、openssl
複数のストリームを処理するように変更し、その複数のストリームを提供するように変更するよりも、1つのストリームで複数の証明書を処理するように変更する方がはるかにcat
簡単です。