Eu tenho um script esperado que se conecta a um site SFTP e carrega alguns arquivos. O ID e a senha estão contidos em arquivos de texto locais. O script expect lê esses arquivos como uma variável e os passa para o servidor SFTP.
O problema que estou enfrentando é que estamos recebendo senhas com complexidade que inclui caracteres especiais ($\,!) etc. Por exemplo, se a senha for pass$word, o $ passará como especial em vez de literal. Sendo isso está sendo passado por uma variável (vários sites e IDs)
Não consigo usar '$pw', pois ele passará literalmente $pw para o servidor e usar "$pw" enviará caracteres especiais. Preciso que passe a senha exatamente como está.
Eu tenho escapado deles manualmente até agora (por exemplo, senha\$palavra), mas isso é tedioso e eu gostaria de fazê-lo script-o-maticamente.
O script fica assim (nomes e lugares alterados para proteger os inocentes)
#!/bin/bash
home=/data/ftp/vf/drop/
un=`cat /home/vf/workflow/.udf/.u/.u$1`
pw=`cat /home/vf/workflow/.udf/.p/.p$1`
sl=`cd /home/vf/workflow/scheduler; grep $1 upload*|cut -d \: -f1`
/usr/bin/expect -c "
spawn /usr/bin/sftp -o KexDHMin=1024 $un@$sl.mysteriouslocation.com
set timeout -1
expect *Authentication
expect Password*
send \"$pw\r\"
expect sftp*
send \"mput /$home/$1/transfer/*\r\"
expect sftp*
send \"ls \r\"
expect sftp*
send \"bye\r\"
expect eof
exit
Como posso passar a senha para o script esperado para que ele envie os caracteres literais e não dê a eles um significado especial? Eu não acho que posso criar um script de "conserto" para o próprio arquivo de senha, o que significa entrar e toda vez que vir um caractere especial, escapá-lo via sed ou outros meios, pois o caractere de escape em si é especial e pode acabar em uma volta.
Sua ajuda é muito apreciada!
Passe os valores como variáveis de ambiente. Isso também evitará as vulnerabilidades de injeção de comando e mostrará a senha na
ps
saída!(bem, ainda pode ser uma vulnerabilidade de injeção de comando se a variável contiver texto que tornaria o
sftp
comando de execução como!reboot
).Você pode colocar o programa esperado em um script separado (vamos chamá-lo de
sftp.expect
) e passar o nome de usuário/senha como argumentos para ele.Isso tem o problema de os argumentos da linha de comando ficarem visíveis para outros usuários no sistema , portanto, essa não é a melhor maneira de lidar com senhas e você realmente não deseja fazer isso com senhas em um sistema compartilhado.
Em seguida, execute-o a partir do script de shell com
Ou se você quiser manter o script esperado dentro do mesmo script de shell, coloque-o em um documento aqui:
(Observe as aspas ao redor
EOF
de , não queremos que o shell interprete as variáveis no heredoc.)Um pequeno trecho Perl pode ser usado para escapar (barra invertida) todos os caracteres ASCII não correspondentes
/[A-Za-z_0-9]/
usando a função quotemeta . A linha de comando Perl é facilmente incorporada ao seu script de shell:produz: