Shell-Script

如何通過 shell 腳本將標題行注入管道?

  • August 1, 2022

我正在研究通過管道將數據從一台伺服器發送到另一台伺服器進行處理的過程。

雖然這不是確切的命令,但它可能看起來像這樣:

tail -f logfile | grep "abc" | grep "def" | grep -v "ghi" | netcat -q 0 n.n.n.n 7777

我想將所有這些 grep 包裝到一個腳本中,更重要的是在管道前面加上netcat一個標識符,所以命令看起來像這樣:

tail -f logfile | myscript.sh {id}

在另一端監聽的腳本應該收到:

{id}
[Line 1 of the logfile]
[Line 2 of the logfile]
...

將其包裝在腳本中很容易:

#!/bin/sh
id=$1
grep "abc" | grep "def" | grep -v "ghi" | netcat -q 0 n.n.n.n 7777

但我不知道如何$id在一開始注入。

接收端正在使用

socat -u tcp-l:7777,fork system:/dev/receivePipe

因此,如果有不同的方式我可以獲取 id(例如以某種方式作為參數/dev/receivePipe),或者通過環境變數,那也可以。

編輯:最終答案在已接受答案的評論中得出:

#!/bin/sh
{
 printf '%s\n' $1
 grep "abc" | grep "def" | grep -v "ghi" 
} | netcat -q 0 192.168.56.105 7777

做就是了:

#! /bin/sh -
{
 printf '%s\n' "${1-default-id}"
 awk '/abc/ && /def/ && ! /ghi/'
} | socat - tcp:n.n.n.n:7777

${1-default-id}如果指定或以其他方式擴展至第一個位置參數default-id。如果未傳遞任何參數,則替換為${1?}以錯誤退出(或${1?The error message}指定錯誤消息而不是預設值)。

我們將執行printf以輸出 ID 和過濾命令grep的命令組的輸出重定向awksocat/ netcat

或者僅在讀取並匹配一行時列印 ID:

#! /bin/sh -
ID=${1-default-id} awk '
 /abc/ && /def/ && ! /ghi/ {
   if (!already_printed++) print ENVIRON["ID"]
   print
 }' | socat - tcp:n.n.n.n:7777

或者將 ID(和空格字元)添加到每一行:

#! /bin/sh -
ID=${1-default-id} awk '
 /abc/ && /def/ && ! /ghi/ {
   print ENVIRON["ID"], $0
 }' | socat - tcp:n.n.n.n:7777

當心,當輸出到管道(到 tty 設備以外的任何設備)時awk,like會緩衝它們的輸出。使用(aka )grep的 GNU 實現,您可以在每個之後添加一個呼叫來強制刷新該緩衝區。另見的。在大多數實現中,執行 a也會強制刷新。的 GNU 實現可以選擇在每行輸出後強制刷新。awk``gawk``fflush()``print``-Winteractive``mawk``awk``system("")``grep``--line-buffered

另請注意,它tail -f logfiletail -n 10 -f logfile. 您實際上可能希望tail -n +1 -f logfile處理整個日誌文件,然後繼續處理該文件,或者只處理從現在tail開始添加的行。f``tail -n 0 -f logfile

引用自:https://unix.stackexchange.com/questions/711992