Ir para o conteúdo principal
No meu último post, falei sobre a automatização de transferências de arquivos usando FTP. Existem três problemas associados ao uso do FTP. Primeiro, sua senha é enviada pela rede em texto simples, tornando-a acessível a qualquer pessoa que utilize um analisador de protocolo. Segundo, seus dados também são enviados em texto simples. Terceiro, você precisa registrar sua senha em algum lugar no módulo, seja na macro ou no arquivo .netrc. Devido a esses problemas, muitos sites já determinaram ou estão pensando em determinar que o SFTP, o subsistema FTP seguro do SSH, seja usado em vez do FTP. No entanto, não basta simplesmente substituir o ftp pelo sftp na sua macro de comando (figura 1) e esperar que funcione (figura 2).

 

&attach_input
sftp 172.16.1.116
nd
MYPASSWORD
put foo
&if (command_status) ^= 226 &then &goto ERROR1
get bar
&if (command_status) ^= 226 &then &goto ERROR2
quit
&
&label ERROR1
..display_line Could not put file
quit
&return
&
&label ERROR2
..display_line Could not get file
quit
&return

Figura 1 – sftp1.cm – substituindo o comando ftp por sftp em uma macro de comando

 

sftp1
Connecting to 172.16.1.116...
dup2: Bad file number.
Error on line 3 of sftp1.
command_processor: Object not found. nd. In command macro
%phx_vos#m15_mas>SysAdmin>Noah_Davids>sftp1.cm
ready  12:39:59

 

Figura 2 – Executando o sftp1.cm
O problema é uma incompatibilidade entre a forma como os comandos nativos do VOS e o POSIX de código aberto tratam as entradas. No entanto, o SFTP, assim como o FTP, permite criar um arquivo com uma lista de solicitações (figura 3) que será executada automaticamente (figura 4).

 


put foo
get bar

 

Figura 3 – sftp2.input – arquivo contendo solicitações para o sftp executar

 


sftp -b sftp2_input [email protected]
[email protected]'s password:
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:06:45

 

Figura 4 – execução com um arquivo de entrada contendo solicitações e uma solicitação de senha
Você notará na figura 4 que o sftp está solicitando uma senha. Não há como inserir a senha no arquivo de entrada. A ÚNICA maneira de ignorar a solicitação de senha é usar a autenticação por chave pública (figura 5).

 

sftp -b sftp2_input [email protected]
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/foo
sftp> get bar
Couldn't stat remote file: No such file or directory
File "/SysAdmin/Noah_Davids/bar" not found.
Ready  13:12:28

 

Figura 5 – Execução com um arquivo de entrada contendo solicitações, utilizando autenticação por chave pública para eliminar a solicitação de senha

 

Você pode encontrar um artigo sobre como configurar a autenticação por chave pública aqui – http://members.cox.net/ndav1/self_published/publickey_authentication_setup.html

Infelizmente, o sftp simplesmente executa todas as solicitações do arquivo de entrada, uma após a outra; não há nenhum mecanismo para verificar se a transferência foi bem-sucedida ou não.

Como não é possível usar macros de comando, há alguma alternativa? O pacote gnu_tools vem com um programa chamado expect. Ele pode ser usado para enviar comandos, aguardar qualquer número de respostas diferentes e executar uma ação com base no que for detectado no fluxo de saída. Não sou especialista em expect, mas o script da figura 6 ajudará você a dar os primeiros passos. Se você pesquisar na web por “scripts expect”, encontrará muitas referências que o ajudarão a personalizar meu exemplo simples.

 

# If we get an end-of-file (eof) it means that the sftp process
# terminated. Report the last command that was sent.
#
proc goteof {cmd} {
puts "sftp connection unexpectedly closed n"
puts "last text received wasn"
puts "<<"
puts $cmd
puts ">>nnn"
exit
}
# Este procedimento realiza correspondências com expressões regulares em busca de sequências-chave
# na saída obtida do comando que foi executado. Neste caso
# Estou apenas informando o tipo de erro, mas outras medidas podem ser tomadas
# também. Eu também verifico apenas dois erros. Existem outros. Você terá
# para adicioná-los à medida que os encontrar.
#
proc checkforerrors {buf cmd} {
se [regexp {.*não encontrado} $buf] {
exibe “$cmd FALHA: não encontrado”
retornar 1
}
if [regexp {.*Permissão negada} $buf] {
exibe “$cmd FALHA: problemas de acesso”
retornar 1
}
retornar 0
}# defina o tempo limite como -1 para que não haja tempo limite. O padrão é 10 segundos
# e a maioria das transferências de arquivos leva mais tempo do que isso. Decidi não definir
# tempo limite, você pode alterar isso.
definir tempo limite como -1

# iniciar sftp
iniciar sftp [email protected]

# aguardar o prompt do SFTP, mas se recebermos um prompt de autenticação, terminando em
# sim/não: relatar um problema de segurança e sair.
expect {
“sim/não?” { puts
“nnnConectamos ao servidor errado ou o servidor foi reiniciado.”
puts
“A chave do servidor deve ser validada antes que este script possa ser executado novamente.nnn”
exit }
sftp>
}

# Mude para um diretório conveniente para testes
send “cd sftp_test”
expect {
eof { goteof “cd sftp_test” }
sftp>
}

# Chamar a função `checkforerrors`, passando todos os caracteres coletados no prompt `
` # `sftp>`. Também o comando que foi enviado ao `sftp.` Se o procedimento `
` # `checkforerrors` retornar 1, sair do script. Novamente, você pode `
` # realizar outras ações. `
` if {[checkforerrors $expect_out(buffer) “cd sftp_test”] == 1} { exit }

enviar “put foo”
expect {
eof { goteof “put foo” }
sftp>
}
if {[checkforerrors $expect_out(buffer) “put foo”] == 1} { exit }

enviar “get barr”
expect {
eof { goteof “get bar” }
sftp>
}
if {[checkforerrors $expect_out(buffer) “get bar”] == 1} { exit }

enviar “quitr”
esperar eof
imprimir “script concluído”

 

Figura 6 – sftp3.exp – script Expect para automatizar o SFTP

 

expect sftp3.exp
spawn sftp [email protected]
Connecting to 172.16.1.116...
The authenticity of host 172.16.1.116(172.16.1.116)' can't be established
+.
RSA key fingerprint is 37:f4:1a:56:64:af:ab:8a:7c:0b:36:47:c5:6c:1d:1a.
Are you sure you want to continue connecting (yes/no)?
Conectamos ao servidor errado ou o servidor foi reiniciado.
A chave do servidor deve ser validada antes que este script possa ser executado novamente. pronto 10:41:10

 

Figura 7 – Execução do script expect sftp3.exp com aviso de segurança

 

expect sftp3.exp
spawn sftp [email protected]
Connecting to 172.16.1.116...
sftp> cd sftp_test
sftp> put foo
Uploading foo to /SysAdmin/Noah_Davids/sftp_test/foo
sftp> get bar
Não foi possível acessar o arquivo remoto: Arquivo ou diretório inexistente
Arquivo “/SysAdmin/Noah_Davids/sftp_test/bar” não encontrado.
sftp> get bar FALHA: arquivo não encontrado 10:42:11

 

Figura 8 – execução do script expect sftp3.exp sem avisos, mas com falha na transferência

Por fim, no meu blog sobre FTP, mencionei que o FTP era capaz de ler arquivos que ainda estavam abertos e que, ocasionalmente, isso resultou na transferência de arquivos incompletos. Sugeri que, se a macro de FTP esperar que um arquivo apareça em um determinado local e depois o transfira, ela deve verificar se o arquivo não está mais bloqueado. O mesmo problema pode ocorrer com o SFTP, e a solução é a mesma. Você pode colocar a verificação de bloqueio do arquivo em uma macro de comando (figura 9) e, quando o arquivo não estiver mais bloqueado, chamar o comando `expect` com o script apropriado.

&label AGAIN
&if (exists new_file) = 1 & (locked new_file) = 0 &then &goto EXPECT
display_line new_file not ready for transfer as of (time)
sleep -seconds 15
&goto AGAIN
&
&
&label EXPECT
expect sftp3.exp

 

Figura 9 – Teste da macro de comando para verificar o bloqueio do arquivo antes de chamar o `expect`

© 2024 Stratus Technologies.