是否有 shell 將管道的概念概括為多個平行管道?支援它需要更改作業系統內核嗎?

是否有 shell 將管道的概念概括為多個平行管道?支援它需要更改作業系統內核嗎?

很多時候,在使用命令列時,我發現自己在某些輸入流指定的一堆不同實例上指定相同的操作,然後想要以某種特定的方式重新組合它們的輸出。

昨天的兩個用例:

  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-teeon-each和)。merge
  3. 關於如何在工具內指定任意多個輸入和輸出檔案描述符的固定約定,以便該 shell 將它們視為平行管道。

這已經做到了嗎?或者我可以應用於我的用例的等效內容?

沒有特定內核支援是否可行?我知道內核通常有一個固定的最大數量的打開文件描述符,但是一個實現可以通過不盲目地嘗試一次打開它們來解決這個問題。

知道的話可行嗎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以處理多個流並修改cat以提供這些多個流要容易得多。

相關內容