I've written a few shell scripts, but have never seen this behavior and am at a loss. I've got the following simple script which runs in a 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
This is executed from a udev rule. The positional parameters (coming from udev) have the values I expect, and I have no problem printing them to the log file. But for some reason, the $VENDOR
variable contains no output from the lsusb
command.
Here is the debugging I've done.
$VENDOR
variable directly to the log, which is empty.$VENDOR
variable to the terminal and it's empty.Took the string that is contained in the $DEVICE
variable and executed it directly in the shell, with this result.
[root@host ~]# lsusb -D /dev/bus/usb/016/030 | grep idVendor
Cannot open /dev/bus/usb/016/030
Why is the $VENDOR
variable empty when outputting to the log file?
EDIT:
Here is an update after removing the redirection from the command substitution.
$VENDOR
variable to the terminal.$DEVICE
variable.Printing $VENDOR
to the terminal output the error, but it still did not append to the log file! The value of $DEVICE
IS in the log file. I believe it has something to do with the output redirection inside the command substitution.
Here, if lsusb
drops an error, the error message is not redirected, only errors from grep
. Errors from lsusb
still go the the usual stderr
, i.e. the terminal (or whatever stderr
was when the script started.
VENDOR=$(lsusb -D "$DEVICE" | grep idVendor 2>&1)
E.g.
$ blah=$(ls -l /nonexisting | grep foo 2>&1)
ls: cannot access '/nonexisting': No such file or directory
$ echo "blah: '$blah'"
blah: ''
You'll need to redirect both of their outputs as a group to have the command substitution capture the error, too:
$ blah=$( { ls -l /nonexisting | grep foo; } 2>&1)
$ echo "blah: '$blah'"
blah: 'ls: cannot access '/nonexisting': No such file or directory'
Using separate redirections like $( foo 2>&1 | grep 2>&1 )
would send the errors of the first command to the pipe, and for grep
to filter, which in the above example would again produce an empty output.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments