2015-11-02 50 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将不得不分配一个字符串来保存文件,而另一组字符串来保存分词结果......实质上,分配的内存将是输入文件大小的两倍。)

显然,如果内容是不确定的,则内存需求和完成时间也是如此。