Como recuar um heredoc dentro de um heredoc do jeito certo?

3

A seguinte codepiece é um script usado para instalar o Apache. Eu executo este script no local ao executá-lo a partir do bloco heredoc que o envolve (APACHE).

Note que dentro deste heredoc APACHE, eu tenho um heredoc interno (MOD_REWRITE), ao qual eu posso me referir como um heredoc "secundário" ou "interno".

Por favor note também que todo o código dentro do APACHE é recuado (tabulado), além do código do heredoc interno.

bash /dev/fd/10 10<<'APACHE'

    # Setup basics:

    apt-get update -y && apt-get upgrade -y
    apt-get install tree zip unzip
    a2enmod mcrypt && a2enmod mbstring

    # Setup LAMP environment with enabled mod rewrite:

    echo -e "" && echo -e "7" # Insert password.
    apt-get install lamp-server^ -y
    a2enmod rewrite

cat <<MOD_REWRITE >> /etc/apache2/apache2.conf

<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
MOD_REWRITE

    systemctl restart apache2.service

    # Setup maldet:

    cd /usr/local/src
    wget http://www.rfxn.com/downloads/maldetect-current.tar.gz && tar -xzf maldetect-current.tar.gz
    cd maldetect-* && bash ./install.sh

APACHE

Se eu recuar com comandos com espaços em vez de tabulações, posso executar o script muito bem (contanto que não tenha o MOD_REWRITE dentro dele). Se eu adicionar o MOD_REWRITE, o script travará quando executado; O mesmo acontece se eu remover todos os recuos de espaço e substituí-los totalmente por tabulações, mas o AFAIK, a última vez que tentei executar o script com tabulações, também quebrou (mesmo quando adicionei um hífen entre bash /dev/fd/10 10<< e 'APACHE' .

Minha pergunta:

Qual é o caminho certo para recuar o heredoc MOD_REWRITE dentro do heredoc APACHE, então o script seria mais unificado e seria executado sem quebra?

Notas:

  • O motivo pelo qual eu quero recuar heredocs internos, assim como eu faria com qualquer outro comando, é por razões estéticas --- Isso facilita a leitura e organização dos meus scripts.

  • Esta questão não é a mesma que " Can ' t indent heredoc para coincidir com o recuo do aninhamento "porque ele pergunta sobre a maneira correta de recuar heredocs internos dentro de heredocs externos, e não sobre recuar os heredocs externos.

por JohnDoea 22.03.2017 / 14:18

2 respostas

7

Um documento aqui é um redirecionamento do formulário:

<<[-]DELIMITER
    ....
    ....
    ....
DELIMITER

O opcional - (dentro dos parênteses acima) muda a maneira como o delimitador é correspondido e permite recuar cada linha dentro do conteúdo heredoc, com tabulações (sem espaços permitidos).

  • "Corresponde" significa que o delimitador é correspondido ao abridor (como quando DELIMITER corresponde a <<DELIMITER ou <<-DELIMITER , por exemplo).

  • Observe que você pode usar um ou mais espaços entre << ou <<- e a palavra a seguir).

Então, para resumir as leis básicas para correspondência dentro de um singlar heredoc:

  1. O abridor deve ser colocado no início da linha em uma sintaxe aplicável.
  2. O delimitador deve ser a única palavra de sua linha.
  3. Todo o conteúdo sob o abridor (incluindo o delimitador) pode ser recuado com qualquer número de tabulações , com a sintaxe <<-DELIMITER .

Já que com a sintaxe anterior, nenhum espaço em branco pode preceder o opener heredoc, se você quiser recuá-lo, sua única escolha é usar a seguinte sintaxe e você deve usar exclusivamente tabulações no início de cada linha dentro do conteúdo do heredoc.

Agora você tem duas opções com a sintaxe <<- .

Primeira opção

Use a sintaxe <<- para o heredoc interno.

bash << APACHE
    ... 
    ... 
    cat <<- MOD_REWRITE
⇨       ...     
⇨       ....    
⇨       MOD_REWRITE
    ... 
    ... 
APACHE

(indentação é de 4 espaços, tabulações são simbolizadas com )

O código visto por bash será exatamente o que está escrito na sua tela (por exemplo, bash verá o recuo de cada linha como você a vê agora). Quando o heredoc interno é atendido, devido à sintaxe <<- , bash removerá os caracteres de tabulação que levam cada linha até o delimitador MOD_REWRITE.

Segunda opção

Use a sintaxe <<- para o heredoc externo.

bash <<- APACHE
⇨       ...
⇨       ...
⇨       cat << MOD_REWRITE
⇨       ⇨       ...
⇨       ⇨       ....
⇨       MOD_REWRITE
⇨       ...
⇨       ...
APACHE

Desta vez, o código visto por bash será diferente do que você vê: ele não conterá nenhuma tabulação principal. É por isso que não é um problema usar a sintaxe << para o heredoc interno: o delimitador MOD_REWRITE estará no início da linha.

Em ambos os casos, o delimitador MOD_REWRITE é reconhecido e seu arquivo de configuração do Apache /etc/apache2/apache2.conf não é recuado. Se você quiser recuar partes dela, sua única opção é usar espaços (após as tabulações iniciais que serão removidas).

Naturalmente, há uma terceira opção: usar a sintaxe <<- para ambos os heredocs, mas isso não alterará nada da opção 2, pois todas as tabulações principais serão removidas quando o código for enviado para bash .

    
por 24.03.2017 / 22:29
4

Primeiro de tudo, indentando a linha cat e as linhas subsequentes (exceto a linha com o NGINX terminator) deve funcionar. A liderança indentação dentro do documento será preservada na saída, o que pode ou não ser um problema no seu caso (se a saída for realmente HTML, há uma chance de que não importa se o espaço em branco extra é introduzido).

Além disso, a documentação do Bash diz isso:

The format of here-documents is:

       <<[-]word
               here-document
       delimiter

[...]

If the redirection operator is <<-, then all leading tab characters are
stripped from input lines and  the  line  containing  delimiter.   This
allows  here-documents within shell scripts to be indented in a natural
fashion.

Você pode usar <<-'PHP_FPM' e recuar cada uma das linhas que seguem com guias, o que seria removido pelo redirecionamento.

    
por 22.03.2017 / 14:31