오류: "sh -c"만 사용하여 쉘 스크립트를 호출할 때 "예기치 않은 연산자" 발생

오류: "sh -c"만 사용하여 쉘 스크립트를 호출할 때 "예기치 않은 연산자" 발생

다음 스크립트가 있습니다.

installRequiredFiles=$1

install_with_pkg()
{
    arg1=$1
        echo $arg1
    echo "[+] Running update: $arg1 update."
}

if [ $installRequiredFiles = "true" ]; then
    if [ -x "$(command -v apt)" ]; then
          install_with_pkg "apt"
        elif [ -x "$(command -v yum)" ]; then
          install_with_pkg "yum"
        elif [ -x "$(command -v apk)" ]; then
          install_with_pkg "apk"
        else
          echo "[!] Can't install files."
    fi
fi

직접 실행하면 잘 작동합니다.

root@ubuntu:/# ./myscript.sh "true"
apt
[+] Running update: apt update.
Printing installRequiredFiles: true
Printing arg1: apt

하지만 사용하면 sh -c다음과 같은 오류가 발생합니다.

root@ubuntu:/# sh -c ./myscript.sh "true"
./c.sh: 11: [: =: unexpected operator
Printing installRequiredFiles:
Printing arg1:

올바르게 실행하고 싶고 sh -c현재 지원되는 기능을 지원하고 싶습니다 sh.bash

답변1

이것은 이 옵션의 목적이 아닙니다 -c. 일반적으로 파일을 제공하지 않고 쉘 명령을 제공합니다. 그 목적은 다음과 같은 작업을 수행하는 것입니다.

$ sh -c 'echo hello'
hello

이제 파일을 제공하고 파일을 읽고 그 안에 있는 명령을 실행하려고 시도하지만 매개변수는 스크립트( myscript.sh)에 전달되지 않고 매개변수는 sh명령 자체에만 전달됩니다. 매개변수:

$ cat script.sh
echo "ARGS: $@"

$ sh ./script.sh true
ARGS: true
$ sh -c ./script.sh true
ARGS: 

당신이 해야 할 일은 사용하지 않는 것 -c뿐이며 예상대로 작동합니다.

sh ./myscript.sh "true"

또는 어떤 이유로든 꼭 사용해야 하는 경우 -c스크립트를 전달하세요.그리고작은따옴표로 묶인 인수로 스크립트에 대한 매개변수 sh:

sh -c './myscript.sh "true"'

답변2

귀하가 받고 있는 오류는 쉘 dash(시스템에 구현된 쉘의 경우 /bin/sh)에서 발생합니다. 이 $installRequiredFiles때문 입니다

  1. 빈 문자열, 그리고
  2. 따옴표 없이 사용하세요.

변수가 비어 있으므로 따옴표 없이 변수를 사용하면 명령에서 변수가 완전히 제거됩니다.

if [ $installRequiredFiles = "true" ]; then

다음과 같이 해석될 것이다.

if [ = "true" ]; then

이것은 다시 명령 사용의 버그입니다 [. =예상되는 사람이 없을 때 연산자가 표시됩니다.

그렇다면 왜 $installRequiredFiles(및 $1)이 비어 있습니까?

주문하다

sh -c ./myscript.sh "true"

명령을 실행 ./myscript.sh하고 스크립트의 문자열로 설정합니다 $0. truein의 값은 $0일반적으로 스크립트나 셸의 이름이며 진단 메시지(예: 셸에서 생성된 오류 메시지)에 가장 일반적으로 사용됩니다.

혹시 사용해보신 분이라면

sh -c ./myscript.sh sh "true"

대신 $1예상대로 then 은 으로 설정되고 는 (인라인 스크립트에 대한 규칙입니다)로 설정됩니다. 두 경우 모두 스크립트는 -line 없이 스크립트를 실행하는 모든 쉘에 의해 실행됩니다. 스크립트를 실행하게 되는 쉘은 컴퓨터의 쉘에 따라 다를 수 있으며 동일하지 않을 수도 있습니다. 예를 들어 다음을 참조하세요.test$0shsh -c#!shshbashShebang 없이 스크립트를 실행하는 쉘 인터프리터는 무엇입니까?.

#!다음을 가리키는 스크립트에 줄을 추가 할 수 있습니다 /bin/sh.

#!/bin/sh

# ... rest of script here ...
# ... just remember to quote all expansions ...

이는 다음과 같이 스크립트를 실행할 수 있음을 의미합니다.

$ ./myscript.sh test

아니면동일한

$ sh -c './myscript.sh "test"'

또는,

$ sh -c './myscript.sh "$@"' sh test

sh -c마지막 두 경우에는 스크립트를 실행하는 쉘이 아니라 직접 실행하는 #!것과 마찬가지로 스크립트의 -line이 참조하는 쉘이 무엇이든 상관없습니다 . ./myscript.sh "test"-line을 추가하기 전과의 차이점은 이제 이것이 다른 #!쉘이 아니라 쉘인지 확인할 수 있다는 것입니다 ./bin/sh

/bin/sh스크립트는 POSIX 셸 구문만 사용합니다. 즉, /bin/sh특정 시스템에서 스크립트를 구현하는 데 사용되는 모든 셸에서 실행할 수 있습니다. /bin/sh그것이 쉘인지 아니면 bashkshdash이국적인 쉘인지는 중요하지 않습니다. 사용자는 스크립트를 실행하기 위해 올바른 인터프리터를 사용하는 것에 대해 걱정할 필요가 없습니다.

이 답변의 다양한 부분과 관련:

관련 정보