Skip to main content
Lots of people have created automated processes to transfer files using FTP. There are several different ways to do this, some better than others. This blog will discuss the different approaches and identify the advantages and disadvantages of each. It will also cover an issue which can result in incomplete files being transferred.
The simplest approach is to put your user ID, password and all your FTP requests into a command macro (figure 1) and just execute it (figure 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

Figure 1 – ftp1.cm – simple command macro
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.
Figure 2 – ftp1.cm – execution of simple command macro
The draw back of this approach is that your user ID and more importantly your password are in clear text as part of the macro. Anyone who has access to the macro can see it. The second approach is to use the .netrc file to hold your user ID and password. (figure 3). The command macro (figure 4) then just includes the FTP requests to execute (figure 5).
machine 172.16.1.116 login Noah_Davids password MYPASSWORD
Figure 3 – .netrc file
&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
Figure 4 – ftp2.cm – command macro without user ID and password
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.
Figure 5 – ftp2.cm – executing command macro without user ID and password
The .netrc file works only if the owner is the only one with access to the file (figure 6). If anyone else has read access (figure 7) it will not work and a password prompt is displayed (figure 8).
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.* n  *.*
Figure 6 – correct ACLs on .netrc file
display_access .netrc -all
%phx_vos#m15_mas>SysAdmin>Noah_Davids>.netrc
w  Noah_Davids.* r  *.CAC n  *.*
Figure 7 – incorrect ACLs on .netrc file
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.
Figure 8 – password prompt when .netrc has the wrong ACLs
You can place all of the commands in the .netrc file by creating an FTP macro. If the macro is named “init” (figure 9) it is automagically executed after login, This makes the VOS command macro just 1 line long (figure 10), the ftp command. The major problem with this approach is there is no error recovery; you cannot check the status of any of the FTP requests with the (command_status) function (figure 11).
machine 172.16.1.116 login Noah_Davids password MYPASSWORD macdef init put foo get bar quit
Figure 9 – .netrc file with init macro
ftp 172.16.1.116
Figure 10 – ftp3.cm – macro when used with .netrc file containing init FTP macro
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.
Figure 11 – ftp3.cm – output when using init macro – no error recovery
Many macros that I have seen just loop waiting for a file to appear in a directory, when it does the macro uses FTP to transfer it (figure 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
Figure 12 – ftp4.cm – macro waiting for a file to appear and then transfer
The problem with this approach is that FTP can read a file that is still open and being written. For a large file or if your timing is just bad the result will be that only part of the file will be transferred (figure 13).
1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij
Figure 13 – only part of the file is transfered
1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij 1234567890 abcdefghij this is the last record
Figure 14 – complete file
It is not enough to check to see if the file exists, you must also check to see if the file is locked (figure 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
Figure 15 – ftp5.cm – checking that a file is unlocked before transferring it
So the best approach is to use the .netrc file to hold your user ID and password and a VOS command macro with the ability to check the command_status after each request to control the actual requests. Also before transferring a file check to make sure that it is not locked.
Some of you are wondering about SFTP; automating file transfers with SFTP is completely different and will be discussed in my next blog.

© 2024 Stratus Technologies.