Chamando script do bash tem problema com argumentos

4

Eu tenho um script que gera um arquivo xml e, em seguida, executa um script perl, passando uma série de argumentos para ele. Aqui está o código chave:

CMD="./dnscurl.pl --keyname $KEYNAME  -- -X POST -H \"Content-Type: text/xml; charset=UTF-8\" --upload-file /tmp/file.xml https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset"
echo "Executing..."
echo $CMD
RESULT='$CMD'

Quando isso é executado, o resultado indica que algo está acontecendo com os argumentos incorporados após o parâmetro -H enviado para o script dnscurl.pl:

curl: (6) Couldn't resolve host 'text'

No entanto, posso pegar o comando exato que eu echo e executá-lo a partir do prompt do shell, e o script funciona corretamente. Parece que quando eu corro com backtic usando RESULT = $CMD os parâmetros não estão sendo passados com as aspas duplas em torno do "Content-Type: etc ...".

O comando que estou executando é este (somente os parâmetros keyname e hostid foram alterados)

./dnscurl.pl --keyname mykey -- -X POST -H "Content-Type: text/xml; charset=UTF-8" --upload-file /tmp/file.xml https://route53.amazonaws.com/2010-10-01/hostedzone/ZZZZZZZ/rrset

Uma coisa que eu estou curioso sobre o uso do '-' eles estão passando. Eu percebo que é específico para o manuseio do script dnscurl.pl, mas não estou claro sobre o porquê isso está sendo passado. Isso é devido ao tratamento de argumentos posicionais? O script foi escrito para lidar com 3 casos de uso diferentes. Não acho que seja relevante, mas apenas por ser completo, esse script está sendo usado para fazer chamadas para a API de descanso da rota 53 da AWS.

    
por gview 28.01.2012 / 23:37

1 resposta

3

Sua citação está errada. Quando você escreve $CMD sem aspas, o valor de $CMD é dividido em “palavras” em cada seqüência de espaço em branco¹ (as palavras podem conter qualquer caractere que não seja espaço em branco incluindo pontuação) e cada palavra passa por globbing expansão). Observe que as citações no valor de CMD , em particular, não são alteradas: as aspas têm um significado na sintaxe dos scripts de shell, mas não na substituição de variáveis. Depois disso, a primeira palavra se torna o nome do comando a ser executado e as palavras subsequentes são os argumentos do comando.

No seu exemplo, assumindo que $KEYNAME é somekeyname e $HZID é somehzid , então o comando e argumentos são:

./dnscurl.pl
--keyname
$KEYNAME
--
-X
POST
-H
"Content-Type:
text/xml;
charset=UTF-8"
--upload-file
/tmp/file.xml
https://route53.amazonaws.com/2010-10-01/hostedzone/somehzid/rrset

Observe que text/xml; aparece como o primeiro argumento não opcional; Claramente, o script Perl passa esse argumento para curl . O -- na lista de argumentos não está relacionado ao seu problema.

Não há como inserir uma linha de comando em uma variável. Uma variável (simples) é a ferramenta errada para isso: ela contém uma string, mas uma linha de comando é uma lista de strings (o comando e seus argumentos). Você pode inserir um nome de comando e seu argumento em uma variável de matriz:

CMD=(./dnscurl.pl --keyname "$KEYNAME"  --
     -X POST -H "Content-Type: text/xml; charset=UTF-8"
     --upload-file /tmp/file.xml
     "https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset")
RESULT=$("${CMD[@]}")

A sintaxe de aparência estranha "${CMD[@]}" expande a variável de array CMD para a lista de palavras na matriz. As aspas duplas impedem a expansão de palavras dentro da matriz, e [@] é necessário por razões históricas para informar ao shell que você deseja expandir uma matriz.

Outra maneira de lembrar uma linha de comando, ou um trecho de shell arbitrário, para uso posterior, é uma função.

cmd () {
    ./dnscurl.pl --keyname "$KEYNAME"  -- \
                 -X POST -H "Content-Type: text/xml; charset=UTF-8" \
                 --upload-file /tmp/file.xml \
                 "https://route53.amazonaws.com/2010-10-01/hostedzone/$HZID/rrset"
}
RESULT=$(cmd)

¹ Mais precisamente, de acordo com o valor de IFS .

    
por 29.01.2012 / 00:36

Tags