我一直在努力并阅读了很多相关内容,显然 bash 可能不是最好的工具,但由于我已经在这个洞里挖了这么深(太多的代码已经存在),我在最不想知道是否存在解决方案,它会是什么样子。
我的目标:一个名为“my_run”的函数,它包装了一个命令行调用,该调用可以是任何内容 - 内置命令、函数或其他脚本,并执行以下操作:
- 调用命令行。
- 将 stderr 发送到文件 (file_e),为每一行添加时间戳
- 将 stdout 发送到单独的文件 (file_s),为每一行添加时间戳
- 在控制台上呈现输出(因此是上面的 T 恤)
- 返回命令的退出返回码。
我有 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
来做时间戳。