Variáveis não são passadas de um script chamando outro com Bash heredoc

1

Eu tenho um shell script mantido no meu usuário local chamado ( executeAdM.sh ), e quando eu executo este script eu estou mudando para um usuário sudo, tomando comandos de um arquivo de instrução. Mas quando eu executo este script eu também estou passando parâmetros, que é na verdade algum caminho de diretório do usuário sudo. Veja o script abaixo.

Script para usuário local ( executeADM.sh ):

#!/bin/bash
echo password | sudo -S -l
sudo /usr/bin/su - user  <<\EOF
#ls -lrt
pwd
for entry in $(ls -r)
  do
  if [ "$entry" = "testingADM.sh" ];then
    ./"$entry" "$1"
  fi
done
EOF

Estou executando o acima como:

./executeADM.sh "/global/u70/globe/ADM"

Quando o script acima é executado, ele alterna com sucesso para o outro usuário e, com o usuário sudo, eu executo um loop for que procura outro script chamado testingADM.sh .

Quando o script for encontrado, eu executo esse script com o parâmetro passado pelo usuário local, e testingADM.sh deve definir o caminho para mim.

Isso não está funcionando - não está lendo o parâmetro passado pelo usuário local.

O script do usuário sudo ( testingADM.sh ):

#!/bin/bash
changepath=$1
cd "$changepath"
pwd

Quando codifico a variável path no script, tudo funciona bem. Mas eu não quero isso:

 #!/bin/bash
 changepath=somepath
 cd "$changepath"
 pwd

O problema é que, em vez de ir para "/global/u70/globe/ADM" , o caminho é assumido como "/global/u70/globe/" , que é o caminho depois de sudo . Não é apenas passar a variável.

Com as sugestões abaixo, acabei ficando assim:

#!/bin/bash
echo password | sudo -S -l
sudo /usr/bin/su - user  <<EOF
#ls -lrt
#pwd
echo "$1"
./testingADM.sh "$1"
EOF

O comando echo não imprime nada; um espaço em branco é mostrado. Funcionou quando mudei \EOF para EOF .

Alguém pode explicar a diferença entre:

\EOF , "EOF" , 'EOF' , EOF

ou os três primeiros têm o mesmo significado? Então qual é a diferença entre eles?

    
por Tushar Sharma 04.08.2017 / 08:05

2 respostas

1

Não cite nem escape sua sequência de limite heredoc (ou seja, use EOF em vez de \EOF ou "EOF" ), caso contrário, variáveis especiais como $ não serão interpretadas. Consulte aqui para mais informações e exemplos (por exemplo, Exemplo 19-7).

Aqui está um script mínimo que funciona:

$ cat test.sh
#!/bin/bash
sudo su - $(whoami) <<EOF
./test2.sh "$1"
EOF

$ cat test2.sh
#!/bin/bash
foo=$1
echo "$foo"

$ ./test1.sh "/path/to/file"
"/path/to/file"

Observe que:

  • Não há necessidade do heredoc. Basta ligar ./test2.sh diretamente após sudo : sudo -u $(whoami) test2.sh "$1"
  • Você não deve repetir a saída de ls .
  • Não há necessidade de fazer um loop for para pesquisar um único arquivo. Basta ligar para o script diretamente com o nome dele.

Você também deve citar suas variáveis, ou seja:

  • Execute seu script com ./executeADM.sh "/path/with white/space"
  • Chame ./"$entry" "$1" no seu script
  • Em seu outro script, use cd "$path"

Em geral:

  • Sempre duplique as variáveis. (Não faça uma citação simples - eles não se expandirão.)
  • Não use uma variável chamada path . (Por mais que você não usasse variáveis chamadas user , home , etc.)
por 04.08.2017 / 10:19
1

Editar
Da minha cabeça. Seu caminho contém espaços?

Se sim, você precisa executá-lo como ./executeADM.sh 'somePath' .

É sempre melhor salvar o $1 em uma variável quando você está passando adiante, o que facilita a leitura. Eu adicionaria path=$1 , em seguida, no arquivo de lote, você teria ./$entry "$path"

    
por 04.08.2017 / 10:02