我正在研究一个通过管道将数据从一台服务器发送到另一台服务器进行处理的过程。
虽然这不是确切的命令,但它可能看起来像这样:
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
答案1
做就是了:
#! /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
awk
socat
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 logfile
是 的缩写tail -n 10 -f logfile
。您实际上可能希望tail -n +1 -f logfile
处理整个日志文件,然后tail
继续f
处理该文件,或者tail -n 0 -f logfile
仅处理正在添加的行今后。