Как я могу использовать здесь документ в середине трубы?

559
simbo1905

Я хочу создать контент:

passphrase=$(<passphrase) envsubst <<EOF apiVersion: v1 kind: Secret metadata: name: openshift-passphrase stringData: passphrase: $ EOF 

и трубка это oc create -f -.

Если я добавлю трубу после EOF, она не будет работать.

Как передать многострочную команду чему-то, что ее потребляет?

0
Не работает после первого EOF? Paulo 5 лет назад 0
@paulo: либо `EOF |` не закрывает несколько строк, либо `EOF`, затем newline заканчивает работу и следующий | находится в начале новой команды simbo1905 5 лет назад 0

1 ответ на вопрос

1
Kamil Maciorowski

Сначала нужно процитировать любую часть 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 - <<…(обратите внимание на отсутствие точки с запятой) не будет работать.
  • Технически тот же код не в подоболочке (т.е. без ( )) также будет работать, но тогда переменная останется в основной оболочке. Запуск кода в подоболочке заставляет переменную умереть вместе с ней. В вашем исходном коде переменная не установлена ​​для основной оболочки, поэтому я думаю, это то, что вы хотите.
Спасибо за очень полный ответ. Хотел бы я проголосовать за него один раз за каждую часть. simbo1905 5 лет назад 0

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