跳转至主要内容
很多人都创建了使用FTP传输文件的自动化流程。有几种不同的方法可以做到这一点,有些比其他方法更好。本博客将讨论不同的方法,并确定每种方法的优缺点。它还将涵盖一个可能导致文件传输不完整的问题。
最简单的方法是把你的用户名、密码和所有的FTP请求放到一个命令宏中(图1),然后执行即可(图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

图1 - ftp1.cm - 简单命令宏
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.
图2 - ftp1.cm - 执行简单的命令宏
这种方法的缺点是,你的用户ID,更重要的是你的密码是以清晰的文本作为宏的一部分。任何能够访问宏的人都可以看到它。第二种方法是使用.netrc文件来保存你的用户ID和密码。(图3)。命令宏(图4)则只需包含要执行的FTP请求(图5)。
machine 172.16.1.116
login Noah_Davids
password MYPASSWORD
图3 - .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
图4 - ftp2.cm - 没有用户ID和密码的命令宏
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.
图5 - ftp2.cm - 执行没有用户ID和密码的命令巨集
.netrc文件只有在文件的所有者是唯一一个可以访问该文件的人时才能工作(图6)。如果其他任何人有读取权限(图7),则无法工作,并显示密码提示(图8)。
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.*
n  *.*
图6 - .netrc文件上正确的ACL。
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.*
r  *.CAC
n  *.*
图7 - .netrc文件的ACL不正确。
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.
图8 - 当.netrc有错误的ACL时的密码提示
你可以通过创建一个ftp宏将所有的命令放在.netrc文件中。如果将宏命名为"init"(图9),则在登录后会自动执行,这使得VOS命令宏只有1行长(图10),即ftp命令。这种方法的主要问题是没有错误恢复功能,不能用(command_status)函数检查任何一个FTP请求的状态(图11)。
machine 172.16.1.116
login Noah_Davids
password MYPASSWORD
macdef init
put foo
get bar
quit
图9 - 带有init宏的.netrc文件
ftp 172.16.1.116
图10 - ftp3.cm - 与包含init FTP宏的.netrc文件一起使用时的宏。
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.
图11 - ftp3.cm - 使用init宏时的输出 - 没有错误恢复功能
我见过的很多宏只是循环等待一个文件出现在目录中,当它出现时,宏就用FTP来传输它(图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
图12 - ftp4.cm - 宏等待文件出现,然后传输
这种方法的问题是,FTP可以读取一个仍在打开和正在写入的文件。对于一个大的文件,或者你的时机不好,结果将是只传输了文件的一部分(图13)。
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
图13 - 只传输部分文件
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
1234567890
abcdefghij
this is the last record
图14 - 完整的文件
仅仅检查文件是否存在是不够的,还必须检查文件是否被锁定(图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
图15 - ftp5.cm - 在传输文件之前检查文件是否被解锁。
所以最好的办法是用.netrc文件来存放你的用户名和密码,并在每次请求后用一个VOS命令宏,并能检查command_status来控制实际请求。另外在传输文件之前要检查一下文件是否被锁定。
有些人想知道SFTP,用SFTP自动传输文件是完全不同的,将在我的下一篇博客中讨论。

© 2024Stratus Technologies.