我想创建一个脚本,为第一行接收管道的每一行运行另一个脚本。像这样:
journalctl -f | myScript1.sh
这myScript1.sh将运行另一个这样的:
myScript1.sh
./myScript2.sh $line_in_pipe
我发现的问题是,我测试的每个代码都只能在有限的管道中正常运行(直到EOF)。但是,当我通过管道传送类似tail -f或的程序时,它将无法执行。我认为它只是等待EOF执行循环。
EOF
tail -f
编辑:无尽的管道是这样的:
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刷新了它的缓冲区,所以这就是它不起作用的原因。II用于--line- buffered强制grep输出正在处理的每行。
grep
--line- buffered
不知道您的脚本中的内容,我们无法确定地说。
例如,如果您要这样做:
# 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
…并且实际上会正常运行,并 受writer进行的任何缓冲的影响 。有关控制缓冲的提示,请参见BashFAQ#9。
最后,引用DontReadLinesWithFor:
阅读线的最后一个问题for是效率低下。甲while read循环读取在从输入流中一次一行; $(<afile)一次将整个文件提取到内存中。对于小文件,这不是问题,但是如果您正在读取大文件,则内存需求将非常巨大。(Bash必须分配一个字符串来保存文件,而另一组字符串来保存单词拆分结果…本质上,分配的内存将是输入文件大小的两倍。)
for
while read
$(<afile)
显然,如果内容不确定,则存储要求和完成时间也将相同。