如何使用 Linux shell 中的环境上下文信息扩展 STDOUT 和 STDERR



我的情况是,我需要从执行的每个输出行添加额外的信息,这是一个 Linux shell 环境,我可以控制初始化,但我不能(不想)控制该上下文中脚本/命令的执行。

为了更好地解释这个问题,假设我有一个 Linux shell 环境,可用于执行 CI(持续集成)管道的步骤(作业)。

在管道步骤中执行的命令存储在由不同人员/团队管理的不同存储库中,并使用提供的 shell 环境执行,例如:

echo "command 1"
echo "command 2"

执行的输出如下所示:

command 1
command 2

上述命令的输出应具有模式<timestamp>:<project_id>:<pipeline_id>:<pipeline_step>:<message>,如下所示:

143437560909100:9876:123456789:UnitTests:command 1
143437560909110:9876:123456789:UnitTests:command 2

模式中的信息在外壳中可用如下:

  • <timestamp>:简单的date +%H%M%S%N外壳执行
  • <project_id>: 可作为环境变量PROJECT_ID
  • <pipeline_id>: 可作为环境变量PIPELINE_ID
  • <pipeline_step>: 可作为环境变量PIPELINE_STEP

来自生成/发布执行的日志将发送到中央日志记录服务,该服务允许我关联和分析管道的行为。

由于我在不同的机器上甚至在不同的 CI 服务器上从不同的管道(由其他管道触发的管道)执行了很多步骤,其中一些是并行的,我需要在每个日志条目中添加与执行的 CI 管道相关的额外信息。要添加的信息和格式必须在平台中可配置,并且无需进行任何更改即可应用于存储管道定义的源存储库。

执行 CI 管道步骤的基础设施信息可以由基础设施平台自动注入(例如,对于基于 Kubernetes K8S 的运行器信息,如主机名、pod 名称、STDOUT/STDERR),而 CI 流水线信息必须由 CI 平台添加。

来自男人 bash:

重定向

Before a command is executed, its input and output may be
redirected using a special notation interpreted by the shell.
...

这意味着重定向可用于将发送到stdout的输出转发到字符串处理器,该处理器可以操作信息并将其以修改后的格式发送回stdout

命令:

exec {STDOUT}>&1
exec {STDERR}>&2

将分配与当前描述符1(/dev/stdout) 和2(/dev/stderr) 重复的新文件描述符,并将这些新描述符的值分别存储在 shell 变量$STDOUT$STDERR中。

这将允许我们将初始文件描述符重定向到初始文件描述符1的不同位置,并2在 shell 环境中执行的命令所针对的位置。我们重定向日志消息的新位置可以是我们可以更改日志消息的新脚本。一旦日志消息被处理为新的预期格式,我们现在可以将其重定向到初始stdinstdout文件描述符,这些描述符分别由新的 shell 变量$STDOUT$STDERR所针对。

现在我们知道了我们必须做什么,我们需要确保重定向应用于在 shell 环境中完成的每个命令执行。

exec 命令将当前进程映像替换为新的进程映像,同时打开、关闭和/或复制作为命令一部分的任何重定向指定的文件描述符。

最终命令看起来像

exec {STDOUT}>&1 
{STDERR}>&2 
1> >(while IFS= read -r line; do echo "$(date +%H%M%S%N):${PROJECT_ID}:${PIPELINE_ID}:${PIPELINE_STEP}:$line" ; done >&${STDOUT}) 
2> >(while IFS= read -r line; do echo "$(date +%H%M%S%N):${PROJECT_ID}:${PIPELINE_ID}:${PIPELINE_STEP}:$line" ; done >&${STDERR})

P.S. 如果要更改 Gitlab CI 管道作业输出中的所有日志条目,只需为 Gitlab CI 运行器配置预构建脚本

即可
RUNNER_PRE_BUILD_SCRIPT='exec {STDIN}>&1 1> >(while IFS= read -r line; do echo "$(date +%H%M%S%N):${PROJECT_ID}:${PIPELINE_ID}:${PIPELINE_STEP}:$line" ; done >&${STDIN})'

相关内容

  • 没有找到相关文章

最新更新