/bin/sh 잘못된 동작

/bin/sh 잘못된 동작

몇 가지 간단한 플래그를 사용하여 실행 스크립트를 만들려고 합니다./bin/sh

#!/bin/sh

set -eux

if [ "$DEBUG" = "true" ]; then
    debug="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=$SUSPEND,address=$DEBUG_PORT"
else
    debug=''
fi

serv="--server.port=${SERVER_PORT}"
prop="--spring.profiles.active=${PROFILES}"

all="${serv:-} ${prop:-}"

java "${debug:-}"-jar /opt/someJar.jar "${all:-}"

이제 설명할 수 없고 왜 그런 일이 발생하는지 Google에서 찾을 수 없는 몇 가지 문제를 발견했습니다.

  1. "${debug:-}"-jar자리가 없으니 참고하세요 . 공백을 넣으면 "java가 메인 클래스를 찾거나 로드할 수 없습니다."라는 메시지와 함께 응용 프로그램이 중단됩니다. 공간을 제거하면 예상대로 작동합니다.
  2. 두 개의 변수 servprop. 이 두 가지를 java 명령 끝에 넣으면 "${serv:-}" "${prop:-}"이 두 매개변수가 애플리케이션에서 별도로 전달됩니다. 그러나 "${all:-}"Java의 예외에서 증가시키면 이 둘이 서로 연결되어 있는 것을 볼 수 있습니다.
Caused by: java.lang.NumberFormatException: For input string: "1234--spring.profiles.active=some-profile"

하지만 set -eux인쇄되기 때문에

+ java -jar /opt/someJar.jar --server.port=1234 --spring.profiles.active=some-profile

그것이 내가 정말로 원하는 것입니다.

어떤 이유로든 충분한 정보를 제공하지 못한 경우 추가 정보를 제공할 수 있습니다. 제가 달성하려는 것은 이것이 왜 이런 일을 하는지, 그리고 /bin/sh이와 같은 간단한 스크립트와 함께 그것을 사용하는 방법을 이해하는 것입니다.

답변1

Stéphane은 $@이를 일반 쉘에서 배열로 사용한다고 언급했습니다. 한 가지 방법은 다음과 같습니다.

#!/bin/sh

set -eux
set --      # clear cmdline params

if [ "$DEBUG" = "true" ]; then
    set -- "-Xdebug" "-Xrunjdwp:transport=dt_socket,server=y,suspend=$SUSPEND,address=$DEBUG_PORT"
fi

# specify the jar file
set -- "$@" -jar /opt/someJar.jar

# add the port and profile
set -- "$@" "--server.port=${SERVER_PORT}" 
set -- "$@" "--spring.profiles.active=${PROFILES}"

# and run it
java "$@"

답변2

sh배열이 없습니다( "$@"위치 매개변수 배열 제외).

존재하다:

java "${debug:-}"-jar /opt/someJar.jar "${all:-}"

java(자신 외에) 3개의 매개변수만 전달됩니다 java.

두 개의 매개변수를 전달하려는 경우 마지막 매개변수에는 --server.port=1234 --spring.profiles.active=some-profile공백과 같은 내용이 --server.port=1234포함 됩니다 --spring.profiles.active=some-profile.

스칼라(대대량으로) 변수는 $all와 마찬가지로 sh하나의 값만 포함할 수 있습니다.

대신 "$@"배열을 다음과 같이 사용할 수 있습니다.글렌이 보여줬어(나는 또한 혼합 $IFS하고 noglob매우 지저분한 것을 좋아합니다) 또는 쉘에 말할 수 있습니다나뉘다변수의 내용을 delimiter 로 설정하여 확장하고 $IFS매개변수 확장을 따옴표 없이 그대로 둡니다(와일드카드를 비활성화한 후 기본적으로 따옴표가 없는 매개변수 확장에서도 와일드카드가 수행되므로).

의 경우 $IFS매개변수에 나타날 수 없는 문자를 선택해야 하며, 매개변수를 비워두려면 해당 문자가 SPC, TAB, NL이 될 수 없습니다(3개 문자가 모두 기본값으로 되어 있음 $IFS).

그러나 귀하의 경우에는 빈 인스턴스가 null일 때 (빈 인수가 아닌) $serv해당 인수가 발생하지 않기를 원하는 것 같으 므로 공백이 더 나은 아이디어일 수 있습니다. NL은 귀하의 주장에서 발견될 가능성이 낮기 때문에 좋은 선택이 될 수 있습니다.$serv$IFS

serv="--server.port=${SERVER_PORT}"
prop="--spring.profiles.active=${PROFILES}"
IFS="
" # newline character only
all="${serv:-}${IFS}${prop:-}"
set -o noglob # disable glob

java ... /opt/someJar.jar $all

에 대해서도 비슷한 작업을 수행해야 합니다 $debug.

set -o noglob매개변수에 와일드카드, 중괄호 또는 백슬래시가 포함되어 있지 않다고 보장할 수 있는 경우 이 단계를 건너뛸 수 있습니다.

xtrace쉘의 출력은 약간 오해의 소지 가 있습니다. SPC 문자로 구분된 원시 출력을 통해 명령에 전달된 인수 목록을 나타냅니다. 이는 매개변수의 SPC 문자와 xtrace매개변수를 구분하는 데 사용되는 출력 문자를 구분할 수 없음을 의미합니다 .

일부 다른 쉘은 그러한 모호성이 존재할 때 인수 주위에 따옴표를 출력하기 때문에 더 유용합니다.

set -x; printf "<%s>\n" foo "bar baz"여러 다른 쉘 해석의 출력을 비교하십시오.

$ dash -c 'set -x; printf "<%s>\n" foo "bar baz"'
+ printf <%s>\n foo bar baz
<foo>
<bar baz>
$ bosh -c 'set -x; printf "<%s>\n" foo "bar baz"'
+ printf <%s>\n foo bar baz
<foo>
<bar baz>
$ bash -c 'set -x; printf "<%s>\n" foo "bar baz"'
+ printf '<%s>\n' foo 'bar baz'
<foo>
<bar baz>
$ ksh -c 'set -x; printf "<%s>\n" foo "bar baz"'
+ printf '<%s>\n' foo 'bar baz'
<foo>
<bar baz>

귀하의 항목은 / 카테고리 sh에 속하는 것 같습니다 . xtrace 출력이 어떻게 3개의 인수를 전달한다고 생각하게 만드는지 확인하세요 . 실제로 는 두 개의 인수인 및 를 전달하고 있습니다 .dashbosh+ printf <%s>\n foo bar bazprintffoobarbazfoobar baz

관련 정보