如何使用 grep 表达式将 tcpdump 输出到 stdout / 文件?

Rda*_*ang 2 grep system-administration tcpdump

我正在尝试将以下 tcpdump grep 表达式输出到文件中:

tcpdump -vvvs 1024 -l -A TCP 端口 80 | grep -E 'X-Forwarded-For:' --line-buffered | grep -E 'X-Forwarded-For:' --line-buffered | awk '{打印$2}

我知道它与行缓冲选项有关,该选项将输出发送到标准输入。但是,如果我不使用 --line-buffered,我根本不会从 tcpdump 中获得任何输出。

在这种情况下,如何使用 grep 以便将我的输出直接发送到 stdout/文件?

小智 7

我正在尝试将以下 tcpdump grep 表达式输出到文件中

然后将管道中最后一个命令的输出重定向到文件:

tcpdump -vvvs 1024 -l -A tcp port 80 | grep -E 'X-Forwarded-For:' --line-buffered | awk '{print $2}' >file
Run Code Online (Sandbox Code Playgroud)

我知道它与行缓冲选项有关,该选项将输出发送到标准输入。

不,那不是--line-buffered

$ man grep

    ...

     --line-buffered
             Force output to be line buffered.  By default, output is line
             buffered when standard output is a terminal and block buffered
             otherwise.
Run Code Online (Sandbox Code Playgroud)

因此它不会改变输出的位置,只是在数据实际写入输出描述符(如果它不是终端)时发生变化。在这种情况下,它不是终端 - 它是一个管道 - 因此,默认情况下,它是块缓冲的,因此如果 grep 写入 4 行输出,并且这小于完整的缓冲区块(在这种情况下,缓冲区块通常为 4K 字节)在大多数现代 UN*Xes 和 Windows 上,因此这 4 行很可能不会填充缓冲区),这些行不会立即由 grep 写入管道,因此它们不会立即显示。

--line-buffered更改该行为,以便每一行在生成时都写入管道,并且 awk 可以更快地看到它。

您正在使用-ltcpdump,它具有相同的效果,至少在 UN*X 上:

$ man tcpdump

    ...

       -l     Make stdout line buffered.  Useful if you want to see  the  data
              while capturing it.  E.g.,

                     tcpdump -l | tee dat

              or

                     tcpdump -l > dat & tail -f dat

              Note  that on Windows,``line buffered'' means ``unbuffered'', so
              that WinDump will write each character  individually  if  -l  is
              specified.

              -U is similar to -l in its behavior, but it will cause output to
              be ``packet-buffered'', so that the output is written to  stdout
              at  the  end of each packet rather than at the end of each line;
              this is buffered on all platforms, including Windows.
Run Code Online (Sandbox Code Playgroud)

因此,正如您所编写的,管道将导致 grep 在 tcpdump 打印后立即查看 tcpdump 打印的每一行,并导致 awk 立即查看包含“X-Forwarded-For:”的每一行grep 看到它并匹配它。

但是,如果我不使用 --line-buffered,我根本不会从 tcpdump 中获得任何输出。

只要 grep 产生一个缓冲区的输出,您最终就会看到它;然而,这可能需要很长时间。 --line-buffered导致 grep 在生成时写出每一行,因此 grep 生成它时就会显示它,而不是缓冲区已满。

在这种情况下,如何使用 grep 以便将我的输出直接发送到 stdout/文件?

grep 正在将其(标准)输出发送到 awk,这可能就是您想要的;您从 grep 的输出中提取第二个字段并仅打印该字段。

因此,您不希望grep将(标准)输出直接发送到终端或文件,您希望它将其输出发送到 awk 并让awk将其(标准)输出发送到那里。如果您希望将输出打印在终端上,那么您的命令就是在做正确的事情;如果您希望将其发送到文件,请将 awk 的标准输出重定向到该文件。

  • 不幸的是,在这种情况下 awk *也*会缓冲其输出。尝试 `tcpdump -vvvs 1024 -l -A tcp 端口 80 | grep -E 'X-Forwarded-For:' --line-buffered | grep -E 'X-Forwarded-For:' --line-buffered | awk '{打印$2}; fflush(stdout)' > file`,让它刷新每行的*其*输出。 (2认同)