Pular para o conteúdo principal
Muita gente criou processos automatizados para transferir arquivos usando FTP. Há várias maneiras diferentes de fazer isso, algumas melhores do que outras. Este blog vai discutir as diferentes abordagens e identificar as vantagens e desvantagens de cada uma delas. Também abordará um assunto que pode resultar em arquivos incompletos sendo transferidos.
A abordagem mais simples é colocar seu ID de usuário, senha e todas as suas solicitações FTP em uma macro de comando (figura 1) e apenas executá-la (figura 2).
&attach_input
ftp 172.16.1.116
Noah_Davids
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 - ftp1.cm - macro de comando simples
ftp1
Connected to 172.16.1.116.
220 phx_vos-m16 FTP server (FTP 1.0 for Stratus STCP) ready. (Compatible with OS
+ TCP/IP)
User (172.16.1.116:Noah_Davids): 331 Password required for nd.
Password:
230 User Noah_Davids.CAC logged in.
200 PORT command successful.
150 Opening data connection for foo (172.16.1.34,49253)0.
226 Transfer complete.
80 bytes sent in 0.01 seconds (6.85 Kbytes/sec)
200 PORT command successful.
550 bar: No such file or directory.
recvrequest: Bad file number.
Get transfer did not complete
Could not get file
221 Goodbye.
Figura 2 - ftp1.cm - execução de macro de comando simples
A desvantagem desta abordagem é que seu ID de usuário e, mais importante, sua senha estão em texto claro como parte da macro. Qualquer pessoa que tenha acesso à macro pode vê-la. A segunda abordagem é usar o arquivo .netrc para manter seu ID de usuário e senha. (figura 3). A macro de comando (figura 4) inclui então apenas as solicitações FTP a serem executadas (figura 5).
machine 172.16.1.116
login Noah_Davids
password MYPASSWORD
Figura 3 - arquivo .netrc
&attach_input
ftp 172.16.1.116
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 4 - ftp2.cm - macro de comando sem ID de usuário e senha
ftp2
Connected to 172.16.1.116.
220 phx_vos-m16 FTP server (FTP 1.0 for Stratus STCP) ready. (Compatible with OS
+ TCP/IP)
331 Password required for nd.
230 User Noah_Davids.CAC logged in.
200 PORT command successful.
150 Opening data connection for foo (172.16.1.34,49256)0.
226 Transfer complete.
80 bytes sent in 0.04 seconds (2.09 Kbytes/sec)
200 PORT command successful.
550 bar: No such file or directory.
recvrequest: Bad file number.
Get transfer did not complete
Could not get file
221 Goodbye.
Figura 5 - ftp2.cm - execução de macro de comando sem ID de usuário e senha
O arquivo .netrc só funciona se o proprietário for o único com acesso ao arquivo (figura 6). Se alguém mais tiver acesso lido (figura 7), ele não funcionará e um prompt de senha será exibido (figura 8).
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.*
n  *.*
Figura 6 - ACLs corretas em arquivo .netrc
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.*
r  *.CAC
n  *.*
Figura 7 - ACLs incorretas em arquivo .netrc
ftp2
Connected to 172.16.1.116.
220 phx_vos-m16 FTP server (FTP 1.0 for Stratus STCP) ready. (Compatible with OS
+ TCP/IP)
User (172.16.1.116:Noah_Davids): 331 Password required for put foo.
Password:
530 Login incorrect.
Login failed.
221 Goodbye.
Figura 8 - prompt de senha quando .netrc tem as ACLs erradas
Você pode colocar todos os comandos no arquivo .netrc, criando uma macro FTP. Se a macro for denominada "init" (figura 9) ela é executada automaticamente após o login, isto faz com que a macro de comando VOS tenha apenas 1 linha de comprimento (figura 10), o comando ftp. O maior problema com esta abordagem é que não há recuperação de erros; não é possível verificar o status de nenhuma das solicitações FTP com a função (comando_status) (figura 11).
machine 172.16.1.116
login Noah_Davids
password MYPASSWORD
macdef init
put foo
get bar
quit
Figura 9 - Arquivo .netrc com macro init
ftp 172.16.1.116
Figura 10 - ftp3.cm - macro quando usado com arquivo .netrc contendo a macro init FTP
ftp3
Connected to 172.16.1.116.
220 phx_vos-m16 FTP server (FTP 1.0 for Stratus STCP) ready. (Compatible with OS
+ TCP/IP)
331 Password required for nd.
230 User Noah_Davids.CAC logged in.
put foo
200 PORT command successful.
150 Opening data connection for foo (172.16.1.34,49276)0.
226 Transfer complete.
80 bytes sent in 0.01 seconds (9.52 Kbytes/sec)
get bar
200 PORT command successful.
550 bar: No such file or directory.
recvrequest: Bad file number.
Get transfer did not complete
quit
221 Goodbye.
Figura 11 - ftp3.cm - saída ao utilizar a macro init - sem recuperação de erros
Muitas macros que eu tenho visto apenas loop esperando um arquivo aparecer em um diretório, quando ele faz a macro usa FTP para transferi-lo (figura 12).
&attach_input
&label AGAIN
&if (exists new_file) = 1 &then &goto FTP
display_line No new_file as of (time)
sleep -seconds 15
&goto AGAIN
&
&
&label FTP
ftp 172.16.1.116
put new_file
&if (command_status) = 226 &then ..display_line OK
&else &do
..display_line
..display_line ERROR
..display_line
&end
quit
Figura 12 - ftp4.cm - macro aguardando o aparecimento de um arquivo e depois a transferência
O problema com esta abordagem é que o FTP pode ler um arquivo que ainda está aberto e sendo escrito. Para um arquivo grande ou se seu timing for apenas ruim, o resultado será que apenas parte do arquivo será transferida (figura 13).
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
Figura 13 - apenas parte do arquivo é transferida
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
this is the last record
Figura 14 - arquivo completo
Não basta verificar se o arquivo existe, é preciso verificar também se o arquivo está bloqueado (figura 15).
&attach_input
&label AGAIN
&if (exists new_file) = 1 & (locked new_file) = 0 &then &goto FTP
display_line new_file not ready for transfer as of (time)
sleep -seconds 15
&goto AGAIN
&
&
&label FTP
ftp 172.16.1.116
put new_file
&if (command_status) = 226 &then ..display_line OK
&else &do
..display_line
..display_line ERROR
..display_line
&end
quit
Figura 15 - ftp5.cm - verificando se um arquivo está desbloqueado antes de transferi-lo
Portanto, a melhor abordagem é usar o arquivo .netrc para manter seu ID de usuário e senha e uma macro de comando VOS com a capacidade de verificar o status do comando_ após cada solicitação para controlar as solicitações reais. Também antes de transferir um arquivo, verifique se ele não está bloqueado.
Alguns de vocês estão se perguntando sobre o SFTP; automatizar a transferência de arquivos com SFTP é completamente diferente e será discutido em meu próximo blog.

© 2024 Stratus Technologies.