구문 오류: 파일 설명자 ≥10의 io 리디렉션에 예기치 않은 단어가 있습니다.

구문 오류: 파일 설명자 ≥10의 io 리디렉션에 예기치 않은 단어가 있습니다.

데비안 7에는 다음 쉘 스크립트가 있습니다.

#!/bin/sh


case "$IFACE" in
    lo)
        # The loopback interface does not count.
        # only run when some other interface comes up
        exit 0
        ;;
    *)
        ;;
esac

(
flock -e 200

FLAGFILE=/var/run/cyvo-auto-started

if [ -e $FLAGFILE ]; then
    exit 0
else
    touch $FLAGFILE
fi

# Launch CyVo without the lock and as cyvo user
flock -u 200
sudo -u cyvo /usr/local/bin/cyvo-launch.sh

) 200>/var/lock/cyvo-autostart-lock # word unexpected here? (line 29)

그것이 나에게주는 오류는 다음과 같습니다

./cyvo: 29: ./cyvo: Syntax error: word unexpected

이것은 제안된 구문이기 때문에 정말 혼란스럽습니다.그룹주문하다. /var/lock/cyvo-autostart-lock를 가리키는 파일 설명자 200을 전달합니다 ().

내가 뭘 잘못했나요?

답변1

쉘 스크립트에서 이식 가능하게 사용할 수 있는 유일한 파일 설명자 번호는 0부터 9까지(즉, 단일 숫자)입니다. 인용하다POSIX:

열린 파일은 0부터 시작하는 십진수로 표시됩니다. 가능한 최대 값은 구현에 따라 정의됩니다. 그러나 모든 구현은 애플리케이션 사용을 위해 최소 0~9(포함)를 지원해야 합니다. 이 숫자를 "파일 설명자"라고 합니다. (…) 파일 설명자 번호를 지정하기 위해 리디렉션 연산자 앞에 하나 이상의 숫자(<공백> 문자는 허용되지 않음)가 올 수 있습니다.

이것문법분명히 리디렉션 연산자 앞에 여러 개의 숫자가 있을 수 있습니다. 그러나 대부분의 쉘은 연산자 앞의 숫자가 단일 숫자로 구성된 경우 파일 설명자로만 구문 분석합니다. 예를 들어 POSIX 사양에 따르면 echo 10>a파일 디스크립터 10을 리다이렉션하여 a빈 파일을 생성해야 하며, 그렇지 않으면 쉘이 파일 디스크립터 번호로 10을 지원하지 않기 때문에 오류가 발생한다. 이 오류는 프로세스에서 열린 파일 수 제한을 초과하는 파일 설명자 수로 인해 발생할 수도 있습니다.

그러나 실제로 대부분의 쉘은 이를 echo 10 >awrite 10in 으로 구문 분석합니다 a. ATT ksh93 및 posh도 dash, mksh 및 zsh와 마찬가지로 규격을 준수하지 않습니다.

$ ksh -c 'echo 10>a; wc -c a'
3 a
$ posh -c 'echo 10>a; wc -c a'
3 a

Linux에서는 POSIX 호환 bash, yash 및 BusyBox의 ash만 찾을 수 있었습니다.

$ bash -c 'echo 10>a; wc -c a' 

0 a

마찬가지로 (…) 200>somefile리디렉션으로 구문 분석해야 하며 쉘이 이러한 높은 파일 설명자를 지원하는지 여부에 따라 작동할 수도 있고 작동하지 않을 수도 있습니다. 그러나 대부분의 쉘은 200이 부분을 파일 설명자 번호가 아닌 일반 토큰으로 구문 분석하기 때문에 구문 오류를 보고합니다 .

관련 참고 사항에서 echo 01>&1빈 줄은 01파일 설명자 번호로 구문 분석되어야 하기 때문에 인쇄되어야 하지만 다시 bash 및 BusyBox ash만 이를 수행할 수 있습니다.

따라서 실제로는한 자리 숫자의 파일 설명자만 사용할 수 있습니다.쉘 스크립트에서. 설명자 0, 1, 2는 표준 의미를 가지며 설명자 3-9는 자유롭게 사용할 수 있습니다. 쉘은 내부 목적으로 fd 3–9를 사용하지 않습니다. 어떤 파일 설명자를 선택하든 쉘이 시작될 때 파일 설명자가 이미 열려 있을 수 있지만 이는 중요하지 않습니다. 스크립트 내의 모든 파일 설명자 재할당은 스크립트 내에 유지되며 스크립트의 상위 프로세스에 영향을 주지 않습니다.

답변2

다시 생각해 보면 내 원래 답변(원래 허용된 답변이었기 때문에 아래에 복사함)보다 더 간단한 접근 방식은 파일 설명자를 200< 9에서 변경하는 것일 수 있습니다. 예를 들어 5. 따라서 200스크립트의 세 인스턴스를 모두 다음으로 변경합니다 5.

#!/bin/sh
case "$IFACE" in
    lo)
        # The loopback interface does not count.
        # only run when some other interface comes up
        exit 0
        ;;
    *)
        ;;
esac

(
flock -e 5

FLAGFILE=/var/run/cyvo-auto-started

if [ -e $FLAGFILE ]; then
    exit 0
else
    touch $FLAGFILE
fi

# Launch CyVo without the lock and as cyvo user
flock -u 5
sudo -u cyvo /usr/local/bin/cyvo-launch.sh

) 5>/var/lock/cyvo-autostart-lock

원래 답변:

@GlennJackman이 제안한 대로 sh파일 설명자 >9를 처리할 수 없거나 스크립트가 작동하지 않는 다른 특징이 있기 때문입니다 sh( dash데비안 기반 배포판). 사용해 봤는데 bash효과가 좋았으니 그냥 사용해 보세요 bash. 첫 번째 줄을 다음으로 변경하십시오.

#!/bin/sh

도착하다

#!/bin/bash

그러면 스크립트가 예상대로 작동해야 합니다.

관련 정보