如何在变量中重定向 stderr 但在控制台中保留 stdout

Dou*_*dou 5 bash terminal stdout stderr variable

我的目标是调用一个命令,在一个变量中获取 stderr,但在屏幕上保留 stdout(并且只有 stdout)。是的,这与大多数人所做的相反:)

目前,我拥有的最好的是:

#!/bin/bash
pull=$(sudo ./pull "${TAG}" 2>&1)
pull_code=$?

if [[ ! "${pull_code}" -eq 0 ]]; then
  error "[${pull_code}] ${pull}"
  exit "${E_PULL_FAILED}"
fi

echo "${pull}"
Run Code Online (Sandbox Code Playgroud)

但这只能在成功的情况下显示标准输出,并且在命令完成后。我想直播标准输出,这可能吗?

编辑

感谢@sebasth,并在没有临时文件的情况将 STDERR 和 STDOUT 重定向到不同变量的帮助下,我写了这个:

#!/bin/bash
{
  sudo ./pull "${TAG}" 2> /dev/fd/3
  pull_code=$?
  if [[ ! "${pull_code}" -eq 0 ]]; then
    echo "[${pull_code}] $(cat<&3)"
    exit "${E_PULL_FAILED}"
  fi
} 3<<EOF
EOF
Run Code Online (Sandbox Code Playgroud)

我承认这不是真正的“美丽”,看起来很棘手,而且我真的不明白为什么需要heredoc ......

这是实现这一目标的更好方法吗?

Sté*_*las 7

只需使用:

{ err=$(cmd 2>&1 >&3 3>&-); } 3>&1
Run Code Online (Sandbox Code Playgroud)

cmd在保持标准输出不变的情况下获得标准错误(这里使用 fd 3原始标准输出(复制3>&1带入命令替换中(>&3在我们将 fd 2 重定向到命令替换创建的管道后恢复2>&1)) .


seb*_*sth 5

您可以使用St\xc3\xa9phane Chazelas提供的答案进行少量修改:仅重定向 stderr 并且不使用命令替换来运行命令。

\n\n
{\n  command 2> /dev/fd/3\n  res=$?\n  err=$(cat<&3)\n} 3<<EOF\nEOF\n\nprintf \'stderr: %s\\n\' "$err"\n
Run Code Online (Sandbox Code Playgroud)\n\n

的输出command通常在 stdout 中,而 stderr 在err变量中。

\n