명령 대체 결과가 출력되지 않습니까?

명령 대체 결과가 출력되지 않습니까?

나는 몇 가지 쉘 스크립트를 작성했지만 이런 동작을 본 적이 없으며 압도감을 ​​느낍니다. 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일반적인 컨텍스트에서 오류가 계속 발생합니다.stderrstderr

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필터링되고 위의 예에서는 다시 빈 출력이 생성됩니다.

관련 정보