使用 exec 和管道在 shell 脚本中处理信号,以使用 grep 过滤输出

使用 exec 和管道在 shell 脚本中处理信号,以使用 grep 过滤输出

我正在部署一个容器化应用程序,该应用程序在启动时输出大量无用的消息(相同的消息大约一百万次,没有任何变化)。该消息无法通过应用程序的配置来抑制,并且应用程序的开发超出了我的控制范围。这会导致日志记录基础设施出现烦人且有问题的峰值。仅在查看日志时才能过滤日志记录基础设施中的消息,而不能在将日志从容器运行时转发到日志记录存储后端时进行过滤。

所以我的目的是在容器入口点内foo bar baz使用应用程序外部抑制此消息(在以下示例中)。grep到目前为止我尝试过的是:

#!/bin/bash
set -euxo pipefail

exec myapp --some parameter | grep --line-buffered -v "foo bar baz"

但这不会替换 PID 1 myapp --some parameter,从而导致信号SIGTERM无法转发到正确的进程:

$> docker exec -it ep-test ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.0  18384  3008 pts/0    Ss+  16:54   0:00 /bin/bash /entrypoint
root         7  0.0  0.0   4540   836 pts/0    S+   16:54   0:00 myapp --some parameter
root         8  0.0  0.0  11472   964 pts/0    S+   16:54   0:00 grep --line-buffered -v "foo bar baz"
root         9  0.0  0.0  34412  2668 pts/1    Rs+  16:54   0:00 ps aux

如果我将 减少到execexec myapp --some parameter则 PID 1 会被正确替换(但输出不会根据需要进行过滤):

$> docker exec -it ep-test ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.2  0.0   4540   768 pts/0    Ss+  16:55   0:00 myapp --some parameter
root         7  0.0  0.0  34412  2796 pts/1    Rs+  16:55   0:00 ps aux

为了彻底关闭应用程序,将SIGTERM(和其他已知信号)转发到非常重要myapp。据我所知,实现此目的的最简单方法是将 PID 1 替换为exec.

myapp所以我的问题是是否有一种简单的方法来过滤with的输出grep,同时确保发送到容器的信号被发送/转发到myapp

答案1

您可以尝试对 grep 使用 bash 命名管道(fifo),这样它就不会使用普通管道。该语法>(cmd)创建一个 fifo,将cmdfifo 作为标准输入运行,并在命令行中替换为 fifo 的名称,例如/dev/fd/63,因此您可以使用 将 app 命令的 stdout 定向到该 fifo >

exec myapp --some parameter > >(grep --line-buffered -v "foo bar baz")

注意 中的空格> >()

相关内容