単一のパイプライン項目でパイプライン全体を表示できますか?

単一のパイプライン項目でパイプライン全体を表示できますか?

func表形式の出力またはjson出力を生成できる関数があります。この問題を解決する従来の方法は、次のパラメータを使用することです。

$ func -j | jq .firstField
$ func -t | awk '{print $1}'

私は「事前に見て」パイプラインの次のステップに基づいて出力タイプを推測したいと思います。理想的な使い方は簡単です。

$ func | jq .firstField
$ func | awk '{print $1}'

func どこかで、パイプラインの次のステップの0番目のパラメータが含まれていることを確認すると想像してくださいj。その場合はjsonを作成し、そうでない場合はテーブルを作成します。

Bashはそのような魔法を許可しますか?それでは、どうすればいいですか?

答え1

/procプロセスツールを使用してプロセスツリー内または存在する場合は、タイプファイルシステムをマイニングして回収できる以外に、パイプラインに関連付けられた公式のメタデータやクエリAPIはありません。親シェルは(おそらく)メモリのどこかに完全なパイプを持ち、関連するさまざまなサブプロセスについて知っています。ただし、ランダムcat(例外を除いて意味なし)パイプが進行中のサブプロセスをcat | cat | cat | ...知ることができるAPIはありません。catパイプラインとその同僚が誰であるかを見てみましょう。

% cat | cat -b | cat -e | cat -n

一意のフラグを使用すると、pstree(1)他の端末に表示されているものがわかりやすくなります。

 |     \-+= 35276 jhqdoe -zsh (zsh)
 |       |--- 44661 jhqdoe cat -n
 |       |--- 03968 jhqdoe cat -b
 |       |--- 96165 jhqdoe cat -e
 |       \--= 26975 jhqdoe cat

cat -eしかし、これはパイプが何であるかを知らせずcat -n、猫のバッグがすべて親シェル35276のプロセスグループに属していることを伝えます。

% ps ao ppid,pid,command | grep '[ ]cat'
35276 44661 cat -n
35276 96165 cat -e
35276  3968 cat -b
35276 26975 cat

どのパイプまたは記述子が何に接続されているかを確認するpidまたはコマンドがあるシステムにある場合は、プロセスが属する/procプロセスグループから何がどのように接続されているかを判断できます。たとえば、Linuxでlsof同様のcatパイプラインを実行すると、パイプ14301040を共有するため、接続してコマンドを実行cat -eできます。cat -n

-bash-4.2$ lsof -p 23591 | grep pipe
cat     23591 jhqdoe    0r  FIFO    0,9       0t0 14301039 pipe
cat     23591 jhqdoe    1w  FIFO    0,9       0t0 14301040 pipe
-bash-4.2$ lsof -p 23592 | grep pipe
cat     23592 jhqdoe    0r  FIFO    0,9       0t0 14301040 pipe

したがって、情報が利用可能であっても情報を把握するには、非ポータブルツールを使用して多くの情報を掘り下げて再構成する必要があります。

親シェルは入力後にパイプを書き換える方法を提供できますが、ZSHフック機能は実行するpreexecコマンドを書き換える方法を提供しないようです。 (これらの機能は、LISPマクロを使用してプログラマーがコードを書き換えることを可能にする方法と似ている可能性があります。)親シェルは、子プロセスがパイプを調べるために使用できるAPIの種類を提供することができます。このタイプの追加はシェルに書き込む必要があります。 。

ただし、複雑なパイプラインを構築できます。

func | ( cd ... && ... | ( ... | awk ... ) )

この場合、誤ってfunc検索awkできない場合、またはプロセスパイプライン検索機能は、次のパイプライン要素のすべてのコマンドを再帰的に検索する必要があります。この場合、おそらくインスタントawkになります。funcまたは、この動作を設定したことを忘れてawk誤って修正され、バグを見つけるのが難しいかもしれません。

答え2

少なくともLinuxではこれを行うことができました。これを示すスクリプトは次のとおりです。https://gist.github.com/MatrixManAtYrService/790a4a058bc841b0ceb2eb0263fb5d88

使用例:

❯ cat -b | ./luigi | jq .
[
  {
    "pid": "20832",
    "name": "cat -b",
    "node": {
      "write": "5157339",
      "read": null
    }
  },
  {
    "pid": "20833",
    "name": "bash ./luigi",
    "node": {
      "write": "5157341",
      "read": "5157339"
    }
  },
  {
    "pid": "20834",
    "name": "jq .",
    "node": {
      "write": null,
      "read": "5157341"
    }
  }
]

関連情報