Quando eu corro:
ssh [email protected] bash -c "/home/devops_staging/deployJob.sh example"
Eu encontro o seguinte erro:
/home/devops_staging/deployJob.sh: line 4: $1: unbound variable
Se eu executá-lo sem a bash -c
peça, funcionará conforme o esperado.
ssh [email protected] /home/devops_staging/deployJob.sh example
deploy success
Por que isso acontece?
Isso é bastante inesperado, pois me lembro de sempre usar essa sintaxe ssh ... bash -c "commands param1 param2"
sem nenhum problema.
O script em questão é super simples, tudo o que estou fazendo na linha 4 é atribuir uma variável from $1
(que deve ser o primeiro parâmetro):
#!/usr/bin/env bash
set -euo pipefail
CI_PROJECT_NAME="$1"
...
Depurando com o, bash -x -c ...
vejo essas seguintes linhas suspeitas:
+ '[' -z '' ']'
+ return
+ case $- in
+ return
+ /home/devops_staging/deployJob.sh
/home/devops_staging/deployJob.sh: line 4: $1: unbound variable
Acho que é uma duplicata da seguinte pergunta: comando ssh com aspas . Já havia sido anotado, mas o autor aqui declarou:
portanto, esta resposta tenta explicar o problema especificamente no contexto do código usado na pergunta atual.
As informações mais importantes desta boa resposta para a pergunta vinculada são:
Se você executar localmente
então os argumentos
ssh
reconhecem como código a ser passado para o lado remoto Será:/home/devops_staging/deployJob.sh
,example
. A string da concatenação dos argumentos seráe este será o código shell a ser executado no lado remoto. Acontece que é a string que você quer.
Mas se você executar localmente
então os argumentos serão:
bash
,-c
,/home/devops_staging/deployJob.sh example
e a string para o shell remoto será(como se os argumentos fossem:
bash
,-c
,/home/devops_staging/deployJob.sh
,example
) e este não é o código shell que você deseja executar no lado remoto. Aquiexample
não pertencerá à opção-argumento-c
(será como o segundosh
nesta outra pergunta ).Se você quiser exatamente esta string como código remoto:
então o método mais fácil é passar a string para um local
ssh
como um único argumento:O argumento entre aspas simples contém todo o código shell que você deseja passar para um shell iniciado pelo servidor SSH no lado remoto.
Observe que você pode até fazer isso localmente:
onde aspas duplas (para o shell remoto) pertencem a dois argumentos locais separados, a string resultante para um shell remoto será a mesma.
Observe quantas ferramentas interpretam e digerem o comando até que o código em seu (remoto)
deployJob.sh
seja executado:O shell local faz divisão de palavras, remoção de citações (e, em geral, algumas outras coisas). No resultado
ssh
pode obter um ou mais argumentos que interpreta como código a ser passado para o lado remoto.ssh
concatena esses argumentos com espaços entre eles, então uma única string é passada para um shell remoto.O shell remoto executa divisão de palavras, remoção de citações (e, em geral, algumas outras coisas) por conta própria. Ele executa alguns comandos.
Se o comando for,
bash -c …
outro shell (remoto) analisará o código sendo o argumento de opção para-c
. A divisão de palavras, a remoção de citações e outras coisas também serão executadas por este shell.E se
deployJob.sh
contiver um shebang são ( ou nenhum ), haverá outro shell (remoto) que, por sua vez, interpretará o arquivo.Em geral, você precisa prever e planejar qual ferramenta obtém quais argumentos depois que todas as ferramentas anteriores digeriram seus argumentos; e quais argumentos passará para a próxima ferramenta. Você precisa projetar seu comando local, para que a ferramenta definitiva obtenha exatamente o que você deseja.