Ansible процитировал heredoc в ожидаемом / командном блоке, не находя разделитель / многострочную команду в ожидаемой команде

#bash #ansible #escaping #heredoc

#bash #ansible #экранирование #heredoc

Вопрос:

Я пытаюсь сгенерировать скрипт для копирования в ansible ожидаемый / ответный блок с ssh на удаленный хост. Я бы хотел избежать записи промежуточных файлов.

У меня две проблемы:

  1. Ansible, похоже, выполняет некоторую обработку, command которая портит многострочные bash сценарии, но я могу обойти это с помощью /bin/bash -c 'my multi line command' (на фактических нескольких строках)
  2. Кажется, я не могу правильно указать метку EOF для heredoc в bash вызове (см. Ниже)
   - name: Generate script on the fly
    expect: 
      command: |
        /bin/bash -c 'ssh -o PubkeyAuthentication=no -p {{ ansible_ssh_port }} {{ ansible_user }}@{{ ansible_host }} "cat - > {{ tgtdir }}/myscript.sh" <<-'EOF' 
          #! /bin/env sh
          a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; THIS=$(cd "$a"; pwd)
          echo "Script dir == ${THIS}"
          echo "{{ someansiblevar }}"
          EOF
        '
      responses:
        (.*)password: "{{ ansible_ssh_pass }}"
    delegate_to: localhost
  

(Обратите внимание, что в этом примере мне, по-видимому, сходит с рук использование одинарных кавычек внутри одинарных кавычек, но все другие варианты также терпят неудачу.)

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

 "stdout_lines": ["/bin/bash: line 10: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')", "", "admin@192.168.1.111's password: "]
  

И содержимое myscript.sh либо неправильно оставлено в покое (т. Е. Все $... развернуто), либо содержит последнее EOF (поскольку оно не распознается как разделитель и просто считывается до конца командного блока, отсюда и предупреждение.

Каков правильный способ справиться с этим?

(Обратите внимание, что я делегирую localhost , потому что я не хочу полагаться python на целевой хост, это минимальные системы только с ssh ).

Комментарии:

1. Убедитесь, что отступ в EOF строке состоит только из символов ТАБУЛЯЦИИ, а не пробелов.

2. Это было быстро 😉 К сожалению, это дает: Syntax Error while loading YAML. found a tab character where an indentation space is expected

3. Если YAML не разрешает табуляции, вы не можете использовать маркер с отступом EOF .

Ответ №1:

Переместите закрывающий EOF влево на два пробела. На данный момент он не запускается в начале своей строки, поэтому bash не увидит его в качестве разделителя.

Со страницы руководства bash:

Здесь документы

Этот тип перенаправления предписывает оболочке считывать входные данные из текущего источника до тех пор, пока не будет видна строка, содержащая только разделитель (без конечных пробелов). Все строки, прочитанные до этого момента, затем используются в качестве стандартного ввода для команды. Формат here-documents является:

 <<[-]word
        here-document 
delimiter 
  

Не выполняется расширение параметров, подстановка команд, арифметическое расширение или расширение имени пути
включено word . Если какие-либо символы в word заключены в кавычки, delimiter является
результат удаления кавычек на word и строки в here-document
не развернуты. Если word не заключено в кавычки, все строки здесь-документа
подвергаются расширению параметров, замене команд и
арифметическое расширение. В последнем случае последовательность символов
<новая строка> игнорируется и должна использоваться для кавычек символов ,
$, и `. Если оператор перенаправления <<- , то все ведущие вкладки
символы удаляются из строк ввода и строки, содержащей
delimiter . Это позволяет here-документам в сценариях оболочки быть
отступ естественным образом.

Таким образом, вам нужно либо удалить отступ из EOF строки, либо сделать отступ во всем с помощью табуляции вместо пробелов. Я полагаю, что первый вариант проще.

Комментарии:

1. «Два пробела превзойдены» в сочетании с двойными кавычками (т. Е. <<-"EOF" ) сделали свое дело! (Одиночные кавычки распознаются как разделитель, но heredoc был непреднамеренно проанализирован.) Спасибо!

2. Пока мы на этом: есть ли способ выполнить многострочный ввод command: | без необходимости дополнительного bash вызова?

3. Я подозреваю, что использование одинарных кавычек могло быть потеряно, потому что вся ваша строка была в одинарных кавычках, но я не могу сказать наверняка.

4. Вы могли бы написать свой сценарий оболочки в одной строке (разделяя команды с ; ), хотя это, вероятно, просто означало бы, что вы отбросили bash в начале команды и вставили ее в качестве аргумента ssh .