Использование && после heredoc в bash

У меня есть bash script, команды которого я соединяю цепочкой, используя &&, так как я хочу, чтобы script остановился, если отдельные шаги завершились с ошибкой.

Один из шагов создает файл конфигурации на основе heredoc:

some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
some_command &&
cat > ./my-conf.yml <<-EOF
host: myhost.example.com
... blah blah ...
EOF
... lots more commands ...

Как включить эту команду в цепочку &&? Я пробовал:

  • Размещение && сразу после EOF. Не работает, поскольку EOF должен быть на линии сам по себе.
  • Размещение && на отдельной строке после EOF. Не работает, потому что bash думает, что я пытаюсь использовать && в качестве команды.
  • Размещение && перед редиректором >. Не работает, поскольку редиректоры логически являются частью команды && -ed.

УТОЧНЕНИЕ:

Существует множество (многострочных) команд, следующих за командой, которая генерирует файл конфигурации из heredoc, поэтому в идеале я ищу решение, которое позволяет мне добавлять следующие команды после heredoc, что является естественным потоком script. То есть, я бы предпочел не использовать встроенные 20+ команд в одной строке.

Ответы

Ответ 1

Цепочные команды в одной строке

Вы можете поместить оператор управления && сразу после слова EOF в здесь, и вы можете подключить более одной команды:

cat > file <<-EOF && echo -n "hello " && echo world

Он будет ждать вашего документа здесь, а затем напечатает привет мир.

Пример

$ cat > file <<-EOF && echo -n "hello " && echo world
> a
> b
> EOF
hello world

$ cat file
a
b

Цепочные команды после разделитель heredoc

Теперь, если вы хотите поместить следующие команды после heredoc, вы можете group в фигурных скобках и продолжайте команды цепочки следующим образом:

echo -n "hello " && { cat > file <<-EOF
a
b
EOF
} && echo world

Пример

$ echo -n "hello " && { cat > file <<-EOF
> a
> b
> EOF
> } && echo world
hello world

$ cat file
a
b

Используя построенный набор

Если вы собираетесь использовать set [-+]e вместо цепочечных команд с &&, вы должны заметить, что окружающая кусок кода с set -e и set +e не является прямой альтернативой, и вы должны принять как описано ниже:

Команды, зависящие от окружения, с set [-+]e

echo first_command
false # it doesnt stop the execution of the script

# surrounded commands
set -e
echo successful_command_a
false # here stops the execution of the script
echo successful_command_b
set +e

# this command is never reached
echo last_command

Как вы можете видеть, если вам нужно продолжать выполнение команд после окруженных команд, это решение не работает.

Группировка команд для спасения

Вместо этого вы можете группировать окруженные команды для создания подоболочки следующим образом:

echo first_command
false # it doesnt stop the execution of the script

# surrounded commands executed in a subshell
(
set -e
echo successful_command_a
false # here stops the execution of the group
echo successful_command_b
set +e
)

# the script is alive here
false # it doesnt stop the execution of the script
echo last_command

Итак, если вам нужно выполнить что-то еще после ваших цепных команд, и вы хотите использовать set встроенный, рассмотрите приведенные выше примеры.

Также обратите внимание на подоболочки:

Подстановка команд, команды, сгруппированные в круглые скобки, и асинхронные команды вызываются в среде подсетей, которая является дубликатом среды оболочки, за исключением того, что ловушки, пойманные оболочкой, reset соответствуют значениям, которые оболочка унаследовала от родительского при вызове. Встроенные команды, которые вызывается как часть конвейера, также выполняются в среде подсетей. Изменения, внесенные в среду подсетей, не могут повлиять на среду выполнения оболочек.

Ответ 2

Если вы используете && оператор просто для остановки в команде, которая терпит неудачу и не будет продолжена, вы можете захотеть окружить кусок кода с помощью set -e и закрыть с помощью set + e. таким образом вы можете удалить && и ваш код, скорее всего, будет выглядеть более чистым.