命令替换没有输出?

命令替换没有输出?

我已经编写了一些 shell 脚本,但从未见过这种行为,并且感到不知所措。我有以下在 bash shell 中运行的简单脚本:

LOGFILE="/var/log/constructor-events.txt"

SUBSYSTEM="$1"
DEVTYPE="$2"
DEVICE="$3"

VENDOR=$(lsusb -D "$DEVICE" | grep idVendor 2>&1)

REQUEST=$(cat <<EOF
{"data": {
    "action": "add",
    "port": {
        "type": "$SUBSYSTEM",
    },
    "drive": {
        "vendor_id": "$VENDOR",
    }
}}
EOF
)

printf "output: $VENDOR" >> $LOGFILE
printf "%s\n" "`date +%x\ %r\ %Z` $REQUEST"  >> $LOGFILE

这是从 udev 规则执行的。位置参数(来自 udev)具有我期望的值,并且将它们打印到日志文件中没有问题。但由于某种原因,该$VENDOR变量不包含lsusb命令的输出。

这是我完成的调试。

  • 添加了 stderr 重定向到 stdout 以捕获可能发生的任何错误。
  • 添加了将$VENDOR变量直接发送到日志的行,该日志为空。
  • 在 shell 中手动执行脚本并将$VENDOR变量打印到终端,它是空的。
  • 获取变量中包含的字符串$DEVICE并直接在 shell 中执行,得到以下结果。

    [root@host ~]# lsusb -D /dev/bus/usb/016/030 | grep idVendor
    Cannot open /dev/bus/usb/016/030
    

为什么$VENDOR输出到日志文件时变量为空?

编辑:

这是从命令替换中删除重定向后的更新。

  • 添加了一行以将$VENDOR变量打印到终端。
  • 静态分配值而不是使用$DEVICE变量。

打印$VENDOR到终端输出错误,但它仍然没有附加到日志文件!$DEVICE日志文件中 IS的值。我相信这与命令替换中的输出重定向有关。

答案1

在这里,如果lsusb丢弃错误,则不会重定向错误消息,仅重定向来自 的错误grep。错误lsusb仍然会发生在通常的情况下stderr,即终端(或stderr脚本启动时的任何地方)。

VENDOR=$(lsusb -D "$DEVICE" | grep idVendor 2>&1)

例如

$ blah=$(ls -l /nonexisting | grep foo 2>&1)
ls: cannot access '/nonexisting': No such file or directory
$ echo "blah: '$blah'"
blah: ''

您需要将它们的两个输出作为一个组进行重定向,以使命令替换也捕获错误:

$ blah=$( { ls -l /nonexisting | grep foo; } 2>&1)
$ echo "blah: '$blah'"
blah: 'ls: cannot access '/nonexisting': No such file or directory'

使用单独的重定向$( foo 2>&1 | grep 2>&1 )会将第一个命令的错误发送到管道,并进行grep过滤,在上面的示例中将再次产生空输出。

相关内容