2015-11-02 30 views
0

閱讀我想創建一個運行的每個第一個接收管道線路上的其它腳本的腳本。 像這樣:從無休止的管慶典

journalctl -f | myScript1.sh 

myScript1.sh將運行一個又一個這樣的:

./myScript2.sh $line_in_pipe 

的問題,我發現每天我測試的代碼只是運行良好,在有限的管道(直到EOF)。 但是,當我管道tail -f或其他程序,它只是不會執行。我認爲它只是等待EOF執行循環。

編輯: 無盡的管道是這樣的:

tail -f /var/log/apache2/access.log | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | script_ip_check.sh 

等script_ip_check.sh的想法是做這樣的事情:

#!/bin/bash 

for line in $(cat); do 
     echo "process:$line" 
     nmap -sV -p1234 --open -T4 $line | grep 'open' -B3 | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' >> list_of_ip_mapped & 
done 

的每一行,這種情況下IP,我會產生一個nmap的線程來掃描該主機上的特殊內容。 我將使用它來掃描試圖連接服務器上某個「隱藏」端口的IP。 所以我的腳本必須一直運行,直到我取消它或它收到一個EOF。

EDIT2: 我剛剛發現grep刷新其緩衝區所以這就是爲什麼它不工作。 我使用--line-buffered強制grep輸出每一行,因爲它正在處理。

+3

不可能,它根本不運行。更有可能在做任何事之前等待一個完整的緩衝區。 –

+0

另請參閱BashFAQ#9:http://mywiki.wooledge.org/BashFAQ/009 –

+0

...但是,要確定地說話而不是「可能」和「不太可能」,我們​​需要一個完整的重現器。 –

回答

3

我們不可能不知道什麼是在你的腳本肯定地說。

舉例來說,如果你這樣做:

# DON'T DO THIS: Violates http://mywiki.wooledge.org/DontReadLinesWithFor 
for line in $(cat); do 
    : ...do something with "$line"... 
done 

...這要等到所有的標準輸入可用,導致掛你描述。


但是,如果你遵循最佳實踐(每BashFAQ #1),您的代碼將操作起來更是這樣的:

while IFS= read -r line; do 
    : ...do something with "$line" 
done 

...這實際上會循規蹈矩,受由作家執行的任何緩衝。有關控制緩衝的提示,請參閱BashFAQ #9


最後,從DontReadLinesWithFor報價:

最後一個問題與讀取線,for是效率低下。 A while read循環從輸入流一次讀取一行; $(<afile)將整個文件一次全部寫入內存。對於小文件,這不是問題,但如果您正在閱讀大文件,內存要求將非常高。 (Bash將不得不分配一個字符串來保存文件,而另一組字符串來保存分詞結果......實質上,分配的內存將是輸入文件大小的兩倍。)

顯然,如果內容是不確定的,則內存需求和完成時間也是如此。