Сначала нужно процитировать любую часть EOF
сразу после <<
. Самый естественный способ есть <<"EOF"
, но <<E"OF"
или даже <<""EOF
подойдет. Без этого envsubst
получится строка с $
уже развернутым. Так как envsubst
оперирует строками с литералом $foo
или $
подстрокой, их предварительное расширение означает, envsubst
что ничего не нужно делать. Кроме того, в вашем случае оболочка, скорее всего, расширится $
до пустой строки, потому что определение переменной в вашем коде влияет только envsubst
на саму оболочку; если переменная с тем же именем (случайно?) не установлена в оболочке заранее.
Теперь мы переходим к вашему явному вопросу. Вы можете передать результат любой команде, которую пожелаете, но вам все равно нужно держать окончательный EOF в отдельной строке. Один из способов сделать это так:
passphrase=$(<passphrase) envsubst <<"EOF" | oc create -f - apiVersion: v1 kind: Secret metadata: name: openshift-passphrase stringData: passphrase: $ EOF
Или вы можете запустить код, который у вас есть в подоболочке:
( passphrase=$(<passphrase) envsubst <<"EOF" apiVersion: v1 kind: Secret metadata: name: openshift-passphrase stringData: passphrase: $ EOF ) | oc create -f -
Примечание Bash Справочное руководство говорит
Каждая команда в конвейере выполняется в своей собственной оболочке
так что даже в первом решении, когда нам удалось построить нашу трубу без ( )
нее, ее первая часть (до |
) все равно работает в подоболочке. Второе решение делает эту подоболочку явной. После того, как мы используем явное (
, оболочка ожидает явного )
. Это позволяет нам размещать что-то после окончания EOF
.
Удивительно, но даже с первым решением вы можете использовать более одного документа ( <<
) в одной составной команде. Такие перенаправления не имеют большого смысла в трубе, но они могут быть полезны с &&
и ||
.
command1 <<EOF && command2 <<EOF || command3 <<EOF content1 EOF content2 EOF content3 EOF
То же переставил, с явными подоболочками:
( command1 <<EOF content1 EOF ) && ( command2 <<EOF content2 EOF ) || command3 <<EOF content3 EOF
В зависимости от ситуации вы можете предпочесть одну запись другим.
Вернемся к вашему конкретному примеру. С подоболочкой вам даже не нужно envsubst
:
( passphrase=$(<passphrase); oc create -f - <<EOF apiVersion: v1 kind: Secret metadata: name: openshift-passphrase stringData: passphrase: $ EOF )
Есть интересные различия между этим способом и первыми двумя:
- На этот раз сама оболочка должна расширяться
$
, следовательно<<EOF
, нет<<"EOF"
. - Чтобы это работало, переменная должна быть известна подоболочке, а не только
oc
; это означает… passphrase=$(<passphrase) oc create -f - <<…
(обратите внимание на отсутствие точки с запятой) не будет работать. - Технически тот же код не в подоболочке (т.е. без
( )
) также будет работать, но тогда переменная останется в основной оболочке. Запуск кода в подоболочке заставляет переменную умереть вместе с ней. В вашем исходном коде переменная не установлена для основной оболочки, поэтому я думаю, это то, что вы хотите.