Por que esse comando gpg em um script se comporta de maneira diferente quando é colado em um shell?

2

Aqui está um script que criptografa / descriptografa simetricamente um arquivo com duas cifras simétricas diferentes em seqüência.

#!/bin/bash

if [ "$#" -ne 2 ]; then
    echo "Arguments: enc|dec filename"
    exit
fi

E="gpg -o - --symmetric --cipher-algo"
D="gpg -o - --decrypt"
ERR="2>/dev/null"

if [ "$1" = "enc" ]; then
    $E AES $2 | $E TWOFISH -
elif [ "$1" = "dec" ]; then
    $D $2 ${ERR} | $D - ${ERR}
else
    echo "Arguments: enc|dec filename"
    exit
fi

Quando executo ./doublecrypt dec /tmp/test.encrypted , obtenho os erros

usage: gpg [options] --decrypt [filename]
usage: gpg [options] --decrypt [filename]

Se eu mudar a linha

$D $2 ${ERR} | $D - ${ERR}

para

echo "$D $2 ${ERR} | $D - ${ERR}"

Imprime

gpg -o - --decrypt /tmp/xenc 2>/dev/null | gpg -o - --decrypt - 2>/dev/null

Se eu copiar e colar isso no bash, ele será executado corretamente.

Então, por que não funciona se eu remover o echo e deixar o script bash avaliá-lo diretamente, como na forma original?

Estou executando o Ubuntu Saucy e o bash é meu shell.

    
por spraff 25.07.2014 / 14:51

2 respostas

0

Resposta curta: veja BashFAQ # 50: Estou tentando colocar um comando em uma variável, mas os casos complexos sempre falham! .

Resposta longa: você está tendo problemas por causa da ordem em que o shell analisa vários elementos das linhas de comando; Especificamente, ele expande as referências de variáveis (como ${ERR} ) na metade do processo - depois de já ter lidado com coisas como cotações, escapes e redirecionamentos. No seu caso, é a parte de redirecionamentos que importa: no momento em que o shell expande ${ERR} para 2>/dev/null , ele já procurou redirecionamentos e não encontrou nenhum, então ele trata apenas 2>/dev/null como um argumento para o comando e então gpg rejeita isso como não fazendo sentido.

Basicamente, armazenar comandos (ou elementos de comando) em variáveis é a maneira errada de fazê-lo. Variáveis são para dados, não para código executável. Nesse caso, seria melhor usar as funções:

e() {
    gpg -o - --symmetric --cipher-algo "$@"
}
d() {
    gpg -o - --decrypt "$@" 2>/dev/null
}

if [ "$1" = "enc" ]; then
    e AES "$2" | e TWOFISH -
elif [ "$1" = "dec" ]; then
    d "$2" | d -
else
    echo "Arguments: enc|dec filename"
    exit
fi

Note que também coloquei $2 entre aspas duplas, para evitar que seu valor seja submetido à segunda metade do processo de análise do shell.

    
por 27.07.2014 / 17:31
0

Tente alterar $D $2 ${ERR} | $D - ${ERR} para:

$( $D $2 ${ERR} | $D - ${ERR} )

Além disso, use o caminho completo para o programa gpg , por exemplo:

/usr/local/bin/gpg
    
por 25.07.2014 / 15:26

Tags