パイプラインの概念を複数の並列パイプラインに一般化するシェルはありますか?これをサポートするには、オペレーティングシステムのカーネルを変更する必要がありますか?

パイプラインの概念を複数の並列パイプラインに一般化するシェルはありますか?これをサポートするには、オペレーティングシステムのカーネルを変更する必要がありますか?

コマンドラインを使用して作業するときは、いくつかの入力ストリーム仕様のさまざまなインスタンスに対して同じ操作を指定し、特定の方法でその出力を再結合したい場合がよくあります。

昨日の2つのユースケース:

  1. 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
    

  2. 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
    

明らかにこれは必要です

  1. 特定のシェルサポート。たぶん、独自の「マルチパイプライン」シンボルが必要な場合があります。
  2. パイプラインの分割とマージのための新しいツール(csplit-teeおよび)on-eachmerge
  3. シェルが並列パイプとして処理するようにツール内で入力および出力ファイル記述子を必要な数だけ指定する方法の規則が修正されました。

これが完了しましたか?それとも私のユースケースに適用できるものと同等ですか?

特定のカーネルサポートなしでこれは可能ですか?カーネルには通常、開いているファイル記述子の最大数が固定されていることがわかりますが、実装では盲目的にすべてのファイル記述子を一度に開こうとしないことでこの問題を解決できます。

知ってみれば可能だろうか?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簡単です。

関連情報