나는 몇 가지 쉘 스크립트를 작성했지만 이런 동작을 본 적이 없으며 압도감을 느낍니다. Bash 쉘에서 실행되는 다음과 같은 간단한 스크립트가 있습니다.
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
제가 수행한 디버깅은 다음과 같습니다.
- 발생할 수 있는 오류를 포착하기 위해 stdout에 stderr 리디렉션을 추가했습니다.
$VENDOR
비어 있는 로그에 직접 변수를 보내는 행을 추가했습니다 .- 셸에서 스크립트를 수동으로 실행하고
$VENDOR
변수를 터미널에 인쇄하면 비어 있습니다. 변수에 포함된 문자열을 가져
$DEVICE
와서 셸에서 직접 실행하면 다음과 같은 결과가 나타납니다.[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
필터링되고 위의 예에서는 다시 빈 출력이 생성됩니다.