/bin/sh неадекватное поведение

Хорошо, после пяти комментариев я дошел до того, что должен просто опубликовать ответ:-)

(Предыдущие комментарии удалены)

Мне кажется, что dstdir1и dstdir2могут быть пустыми, так что ваша командаrsync-синхронизируется с /.

Чтобы предотвратить такие ошибки, измените заголовок вашего файла (завершающий пробел, необходимый после-):

#!/bin/bash - 
set -o nounset   # exit on unset variables.
set -o errexit   # exit on any error.

Может оказаться полезным установить shellcheckна вашу коробку.

Я проверил его на вашем скрипте, и он жалуется на некавычки vars в строках 7, 10, 11, 13, 41 и 49. onlyonce=0кажется неиспользуемым.

Псевдоним brcне используется, и я бы не советовал использовать псевдонимы в сценариях оболочки. Вместо этого вы должны использовать функции.

0
27.07.2020, 19:21
2 ответа

Стефан упомянул об использовании $@в качестве массива в простой оболочке. Вот один из способов сделать это:

#!/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
18.03.2021, 23:16

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очень беспорядочно ), или вместо этого вы можете указать оболочке разделить содержимое переменной при расширении, установив переменную $IFSв разделитель, и оставить расширение параметра без кавычек (после отключения подстановки, поскольку подстановка также выполняется по умолчанию для параметра без кавычек расширения ).

Для $IFSвы хотите выбрать символ, который не может встречаться в аргументах, и если вы хотите сохранить пустые аргументы, этот символ не может быть SPC, TAB или NL (все 3 оказались в значении по умолчанию$IFS).

Однако в вашем случае похоже, что вы хотите, чтобы пустой $serv, например, приводил к отсутствию соответствующего аргумента, когда $servпуст (, в отличие от одного пустого аргумента ), поэтому пробел $IFS, вероятно, лучшая идея. NL, вероятно, хороший выбор, так как вряд ли он будет найден в ваших аргументах здесь:

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относится к категории dash/ bosh. Посмотрите, как их вывод + printf <%s>\n foo bar bazxtrace заставляет вас думать, что printfпередается 3 foo, bar, bazаргумента, хотя на самом деле ему передаются два аргумента:fooи bar baz.

2
18.03.2021, 23:16

Теги

Похожие вопросы