在捕获返回退出代码(是任何环境变量)并将其“沿着链”传递回时,对每个输出进行处理

在捕获返回退出代码(是任何环境变量)并将其“沿着链”传递回时,对每个输出进行处理

我一直在努力并阅读了很多相关内容,显然 bash 可能不是最好的工具,但由于我已经在这个洞里挖了这么深(太多的代码已经存在),我在最不想知道是否存在解决方案,它会是什么样子。

我的目标:一个名为“my_run”的函数,它包装了一个命令行调用,该调用可以是任何内容 - 内置命令、函数或其他脚本,并执行以下操作:

  1. 调用命令行。
  2. 将 stderr 发送到文件 (file_e),为每一行添加时间戳
  3. 将 stdout 发送到单独的文件 (file_s),为每一行添加时间戳
  4. 在控制台上呈现输出(因此是上面的 T 恤)
  5. 返回命令的退出返回码。

我有 1-4 个工作,实际上我也有 5 个工作,但我想知道是否有不同/更好的方法来实现相同的目标。

目前,这是通过将值保存在文件中并将其读入变量来实现的。正如我所说 - 它有效。

我的要求

有没有一种方法可以将值分配给变量“内部”(下面第 18 行)并使其在外部可用而不使用中间文件?

我知道管道创建子 shell,并且环境不会从该子 shell 传回,并且shopt -s lastpipe(在交互式 shell 中禁用作业管理set +m)应该有所帮助,但因为我没有在“最后一个管道”中分配',这对我来说从来没有用过。

有人做过这样的事吗?

我关注的代码是这样的:

01  EXIT_CODE_TMP=$(mktemp)
02  unset MY_RUN_EXIT_CODE
03  MY_RUN_EXIT_CODE=0
04  
05  # This is my failed attempt to try and capture the return code.
06  #shopt -s lastpipe
07  
08  # This is where all the work is done:
09  # * Redirect stderr(2>) into stdout(&1), stdout(1>) in to
10  #   stream:3(&3)
11  # * grabs the code and dumps into a temp file
13  # * Tees while adding a timestamp into the *.2err log file
14  # * Redirects stream:3(3>) into stdin(&1), and stdin(1>) into
15  #   stderr(&2), basically reverting back
16  # * Tees while adding a timestamp into the *.1std log file
17  { {
18      2>&1 1>&3 "${1}" "${@:2}" || echo $? > $EXIT_CODE_TMP
19  } | tee >(_ts "E" > "/tmp/log.${MY_RUN_NAME}.2err")
20  } 3>&1 1>&2 \
21  | tee >(_ts > "/tmp/log.${MY_RUN_NAME}.1std")
22
23  # Reads the exit code form the temp file (and deletes the file)
24  MY_RUN_EXIT_CODE=$(( 0 + 0$(cat $EXIT_CODE_TMP; rm $EXIT_CODE_TMP) ))

如果您想测试代码,我已在我的个人文件夹中放置了完整的功能副本哈斯特宾

更新:范围澄清

这个问题是bash具体的,我知道其他地方有解决方案,但这需要在可能无法选择安装不同外壳的环境中运行。

答案1

使用 更容易zsh。从 bash 切换到 zsh 可能会消除更多令人头疼的问题。

{
  the-command(s)-you-want-to-redirect
} > >(ts "%FT%T%z OUT:" >&1 > file_s) 2> >(ts "%FT%T%z ERR:" >&2 > file_e)

这里使用 moreutilts来做时间戳。

相关内容