Questão Bash scripting: execute um comando shell dentro de um script com variável dentro de citações


Eu preciso carregar um banco de dados em um servidor mysql e o seguinte comando funciona a partir do shell:
De casca

mysql -h "172.17.0.2" -u "root"  -p"mypasswd" -Bse "create database mydb;"

Mas não do script, em que o ip e a senha são variáveis ​​passadas como argumentos:

O roteiro:

#!/bin/bash

set -e
sqlname=$1
sqlpass=$2
sqlip=$3
...  
set -x
echo "Creating the database..."
mysql -h $sqlip -u "root" -p$sqlpass -Bse "create database mydb;"

O resultado do script: 

./myscript.sh mysql1 mypasswd 172.17.0.2

Criando o banco de dados ...
  + mysql -h 172.17.0.2 -u root -pmypasswd -Bse 'criar banco de dados mydb;'
   ERRO 2003 (HY000): Não é possível conectar-se ao servidor MySQL em   «172.17.0.2» (111)

- comece a editar
Mesmo resultado para as variáveis ​​dentro de aspas duplas:

#!/bin/bash  
...  
mysql -h "$sqlip" -u root -p"$sqlpass" -Bse "create database mydb;"

+ echo 'Criando o banco de dados ...' Criando o banco de dados ...
  + mysql -h 172.17.0.2 -u root -pmypasswd -Bse 'criar banco de dados mydb;' ERRO 2003 (HY000): Não é possível conectar-se ao servidor MySQL em   «172.17.0.2» (111)

- end edit

Aspas duplas e citações de singles com variáveis ​​dentro do script me confundem.

Eu estou faltando algo óbvio aqui sobre o uso de variáveis ​​dentro e com aspas.

Alguma dica?


0


origem


Feito. Eu estou usando uma senha muito simples para testes, tão simples quanto "mypasswd" - AJN


Respostas:


O uso de aspas é para impedir que o shell interprete certos caracteres de pontuação, como espaço (separador de parâmetro), > (redirecionamento de saída), * (wild card na máscara de arquivo), etc.

Aspas simples param todas as interpretações do texto citado, enquanto as aspas duplas permitem $ expansão (e alguns outros). O comando dentro de um script não é diferente daquele digitado para um prompt interativo.

O endereço IP não possui caracteres específicos do shell, nem root, então eles não precisam ser citados. Se a sua senha tiver caracteres específicos do shell, como um espaço, ela precisará ser citada e porque requer $ expansão eles precisam ser aspas duplas. o -Bse parâmetro tem espaço e ;, então ele precisa de citação, mas também serve, já que não há $ expansão.

As variáveis ​​que você está expandindo $sqlip e $sqlpass precisam ser definidos dentro do subshell que executa o script, então eles precisam ser definidos no subshell ou definidos como export no shell de chamada.


1



Oi @afh. No script eu uso o shebang que irá rodar o script em uma subshell (editei a questão). É isso que você quis dizer? - AJN
@AJN - Não. Scripts sempre executado em um subshell, a menos que invocado com o source / . comando. - AFH
Onde é 172.17.0.2? É a mesma máquina em que você está correndo? Está na sua intranet? - AFH
É um contêiner e não há problemas de conectividade. Eu testei o comando (mencionado no início da pergunta) no console do host e ele funciona. - AJN
Procurando por "sql error 2003 HY000 111" dá um monte de soluções, incluindo este e a seguinte resposta. Mas seus comandos de linha de comando e script parecem ser os mesmos, então não vejo como isso pode variar no script, a menos que você não tenha publicado variáveis ​​de configuração, tal como MYSQL_TCP_PORT. - AFH


É possível que haja alguns caracteres na variável de senha que são tratados especialmente pelo shell.

Como regra geral, a melhor prática é cite sempre as variáveis ​​do shell para evitar efeitos colaterais indesejados, como divisão de token e expansão de curingas. Vejo Quando é necessário cotar duas vezes? do Unix e do Linux Stack Exchange.

mysql -h "$sqlip" -u root -p"$sqlpass" -Bse "create database mydb;"

1



Dentro do script, coloquei as variáveis ​​entre aspas duplas, mas dá o mesmo resultado (veja a pergunta editada). - AJN