假设我有一个像下面这样的脚本:

useless.sh

echo "This Is Error" 1>&2
echo "This Is Output" 

我有另一个shell脚本:

alsoUseless.sh

./useless.sh | sed 's/Output/Useless/'

我想捕捉“这是错误”,或任何其他stderr从无用的。sh,到一个变量。 我们称它为ERROR。

注意,我使用了stdout。我想继续使用stdout,所以在这种情况下,将stderr重定向到stdout没有帮助。

所以,基本上,我想做

./useless.sh 2> $ERROR | ...

但这显然行不通。

我也知道我能做到

./useless.sh 2> /tmp/Error
ERROR=`cat /tmp/Error`

但这是丑陋和不必要的。

不幸的是,如果这里没有答案,这就是我要做的。

我希望还有别的办法。

有人有更好的主意吗?


当前回答

$ b=$( ( a=$( (echo stdout;echo stderr >&2) ) ) 2>&1 )
$ echo "a=>$a b=>$b"
a=>stdout b=>stderr

其他回答

我将使用find命令

find / -maxdepth 2 -iname 'tmp' -type d

作为非超级用户的演示。当访问/ dir时,它应该抱怨“权限被拒绝”。

#!/bin/bash

echo "terminal:"
{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&- | tee /dev/stderr)"; } 3>&1 | tee /dev/fd/4 2>&1; out=$(cat /dev/fd/4)
echo "stdout:" && echo "$out"
echo "stderr:" && echo "$err"

给出输出:

terminal:
find: ‘/root’: Permission denied
/tmp
/var/tmp
find: ‘/lost+found’: Permission denied
stdout:
/tmp
/var/tmp
stderr:
find: ‘/root’: Permission denied
find: ‘/lost+found’: Permission denied

终端输出也包含/dev/stderr内容,就像不带任何脚本地运行find命令一样。$out有/dev/stdout, $err有/dev/stderr内容。

use:

#!/bin/bash

echo "terminal:"
{ err="$(find / -maxdepth 2 -iname 'tmp' -type d 2>&1 1>&3 3>&-)"; } 3>&1 | tee /dev/fd/4; out=$(cat /dev/fd/4)
echo "stdout:" && echo "$out"
echo "stderr:" && echo "$err"

如果您不想在终端输出中看到/dev/stderr。

terminal:
/tmp
/var/tmp
stdout:
/tmp
/var/tmp
stderr:
find: ‘/root’: Permission denied
find: ‘/lost+found’: Permission denied
# command receives its input from stdin.
# command sends its output to stdout.
exec 3>&1
stderr="$(command </dev/stdin 2>&1 1>&3)"
exitcode="${?}"
echo "STDERR: $stderr"
exit ${exitcode}

重定向stderr到stdout, stdout到/dev/null,然后使用反勾号或$()捕获重定向的stderr:

ERROR=$(./useless.sh 2>&1 >/dev/null)

在zsh:

{ . ./useless.sh > /dev/tty } 2>&1 | read ERROR
$ echo $ERROR
( your message )

为了防止你的命令出错:

execute [INVOKING-FUNCTION] [COMMAND]

execute () {
    function="${1}"
    command="${2}"
    error=$(eval "${command}" 2>&1 >"/dev/null")

    if [ ${?} -ne 0 ]; then
        echo "${function}: ${error}"
        exit 1
    fi
}

精益生产的启示:

故意让错误变得不可能 让步骤最小 逐个完成项目 让每个人都清楚