bash script autobeautifiying usando declare -f

3

Estou tentando "embelezar" scripts automaticamente usando declare -f function

Em poucas palavras: Dado um script bash foo , você pode aparentemente "automagicamente" recuar, fazendo, no bash:   MAGIC () { ...here you copy/paste the whole foo script... ; } ; declare -f MAGIC

Eu forneço um script de exemplo abaixo que faz isso para qualquer script que você der como entrada.

Minha pergunta é: quais são as principais ressalvas de usar uma função abrangente e, em seguida, declare -f it?

  • algum perigo especial?
  • limite no número de aninhamento de função? (Eu posso ter funções no script, elas são felizes também, mas quantos níveis posso usar?)
  • "não será capaz de fazer isso / interpretar isso / ..."? (parece que o awk script está bem, e são até indentados um pouco (o script principal está alinhado com o resto do script) ... mas que (outras) coisas podem causar problemas?
  • perderá algumas informações? Eu notei: ele remove linhas em branco e comentários ( # ... ), mas o que mais ele descarta / modifica?

Eu quero receber sua opinião antes que eu possa usar o meu script "indent" abaixo para reindentar um monte de scripts bash ...

Aqui está minha primeira tentativa, comentários (e respostas sobre as preocupações acima) bem-vindos:

#!/usr/bin/bash
 # parameters:  $@ = bash (only) scripts that need reindentations.

for script in "$@" ; do
  tmpfile="${script}.BEAUTIFY.tmp"
  finalfile="${script}.BEAUTIFY"
  # optionnal temporisation...
  echo "I am about to create ${script}.BEAUTIFY from the bash (I hope) script: ${script} . Press return if OK, ctrl-C if not"
  read temporisation
  # we output the following commands into a pipe to a subshell bash:
  { sleep 1
    echo "
      # declare surrounding function . The script has to be bash, but can contain also functions, etc.
      # Will lose # comments and blank lines, but maybe also other things... hence the Question on unix.se
      ODBEAUTIFIER () {
      $(cat "$script")
      }
      #  print if via declare -f, to pretiffy it
      declare -f ODBEAUTIFIER > \"${tmpfile}\"
      #  then get rid of the surrounding ODBEAUTIFIER function:
      tail -n +3 \"${tmpfile}\" | tac | tail -n +2 | tac | sed -e 's/    //' > \"${finalfile}\"
      #  and displays the resulting file
      ls -l \"${script}\" \"${finalfile}\"
      \rm \"${tmpfile}\" ; # that rm has a backslash to avoid aliases to rm -i
      "
   } | bash ; #  that sub- bash receives the input and interprets it
done

Note / edit : Existe uma solução (mas com muitas advertências e perigos) para evitar o "declare -f perderá comentários começando com #": mas parece que distrai (... pelo menos um usuário insistente, veja os comentários abaixo ^^) da questão principal (Mesmo difícil eu citei as muitas ressalvas da solução alternativa, eu prefiro remover sua menção acima, pois não era de todo o ponto da questão. Mentes curiosas pode se referir à edição antes de agora ^^)

    
por Olivier Dulac 07.04.2016 / 14:23

1 resposta

2

Existe um risco de segurança ao ler o script como uma função e depois canalizar para outro shell: Se o arquivo de entrada contiver um } sem correspondência, o que segue será executado (e omitido da saída).

Um } incomparável pode ocorrer acidental ou maliciosamente. Normalmente, o bash informaria um erro de sintaxe, mas um invasor poderia ocultar isso (do usuário que está executando o script de embelezamento) finalizando o arquivo com outra função inacabada:

}
echo "insert shellcode here" > ~/RCFILE
function end_func {
    true

Menos importante:

  • Você mencionou que ele perde comentários começando com # . Isso inclui a abertura #!/bin/... , portanto, pode impedir que os arquivos de saída sejam executados.

  • sed -e 's/ //' retira os primeiros 4 espaços em qualquer linha. Esses são geralmente os 4 espaços prefixados por declare . Mas declare não insere espaços antes das linhas de um documento aqui, portanto isso pode excluir outros espaços que eram parte do original.

  • Você pode usar head -n -1 em vez de tac | tail -n +2 | tac . Ou você pode remover os dois tail s e usar sed '1,2d;$d' .

por 08.05.2016 / 09:35