Uploading a file using ftp and/or a .netrc file from the command line

My first recommendation

Forget about all this ftp(1) thing. Only use this if there really is no other alternative. ftp(1) is a very unsafe protocol. The password as well as the data gets sent unencrypted in plain text.Just like telnet(1) it should be retired. Use one of the safer encrypted alternatives like scp(1) or sftp(1)

If you are forced to use ftp(1), first test on your local FreeBSD box. That means less trial and error transmissions of the password over the internet.

  • Make sure ftp is running

    If not acquire root privilege to start ftpd manually:

    Code:
    [cmd=$]sudo /usr/libexec/ftpd -D[/cmd]
    
    [cmd=$]netstat -a -f inet[/cmd]
    
    Active Internet connections (including servers)
    Proto Recv-Q Send-Q Local Address          Foreign Address        (state)
    [color=blue]tcp4       0      0 *.ftp                  *.*                    LISTEN[/color]
    tcp4       0      0 *.submission           *.*                    LISTEN
    tcp4       0      0 *.smtp                 *.*                    LISTEN
    tcp4       0      0 *.ssh                  *.*                    LISTEN
    udp4       0      0 localhost.ntp          *.*                    
    udp4       0      0 static.85-10-195.ntp   *.*                    
    udp4       0      0 *.ntp                  *.*                    
    udp4       0      0 *.syslog               *.*
  • Check a login

    Code:
    [cmd=$]ftp 'ftp://adriaan:PasswordSentInPlainText@localhost'[/cmd]
    
    Trying 127.0.0.1:21 ...
    Connected to localhost.
    220 j65nko.org FTP server (Version 6.00LS) ready.
    331 Password required for adriaan.
    230 User adriaan logged in.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    200 Type set to I.
    [cmd=ftp>] ls[/cmd] 
    229 Entering Extended Passive Mode (|||23233|)
    150 Opening ASCII mode data connection for '/bin/ls'.
    total 20
    -rw-r--r--  1 adriaan  adriaan  1016 Feb 14 20:15 .cshrc
    -rw-r--r--  1 adriaan  adriaan   254 Feb 14 20:15 .login
    -rw-r--r--  1 adriaan  adriaan   165 Feb 14 20:15 .login_conf
    -rw-------  1 adriaan  adriaan   381 Feb 14 20:15 .mail_aliases
    -rw-r--r--  1 adriaan  adriaan   338 Feb 14 20:15 .mailrc
    -rw-r--r--  1 adriaan  adriaan   750 Feb 14 20:15 .profile
    -rw-------  1 adriaan  adriaan   283 Feb 14 20:15 .rhosts
    -rw-r--r--  1 adriaan  adriaan   980 Feb 14 20:15 .shrc
    drwxr-xr-x  2 adriaan  adriaan   512 Feb 14 20:22 DESTINATION
    -rw-r--r--  1 adriaan  adriaan    15 Feb 14 20:18 TESTFILE
    226 Transfer complete.
    [cmd=ftp>] bye[/cmd]
    221 Goodbye.
    $
  • Create a test file to upload

    $ echo THIS is a TEST >TESTFILE


  • Upload the file TESTFILE to the folder DESTINATION

    Code:
    [cmd=$]echo put ./TESTFILE | ftp 'ftp://adriaan:PasswordSentInPlainText@localhost/DESTINATION/'[/cmd]
    
    Trying 127.0.0.1:21 ...
    Connected to localhost.
    220 j65nko.org FTP server (Version 6.00LS) ready.
    331 Password required for adriaan.
    230 User adriaan logged in.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    200 Type set to I.
    250 CWD command successful.
    local: ./TESTFILE remote: ./TESTFILE
    229 Entering Extended Passive Mode (|||65157|)
    150 Opening BINARY mode data connection for './TESTFILE'.
    100% |********************|    15      271.26 KiB/s    00:00 ETA
    226 Transfer complete.
    15 bytes sent in 00:00 (94.50 KiB/s)
    221 Goodbye.
    $

    As you see we simply send the put command to standard output. Because of the he shell pipe '|', this command will be read as standard input by ftp(1).


  • Using this shell pipe method in a script

    Code:
    #!/bin/sh
    
    cat <<END | ftp 'ftp://adriaan@localhost/DESTINATION/'
    put ./TESTFILE
    END

    Running it:
    Code:
    [cmd=$]./upload-it[/cmd]
    
    Trying 127.0.0.1:21 ...
    Connected to localhost.
    220 j65nko.org FTP server (Version 6.00LS) ready.
    331 Password required for adriaan.
    Password: 
    230 User adriaan logged in.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    200 Type set to I.
    250 CWD command successful.
    local: ./TESTFILE remote: ./TESTFILE
    229 Entering Extended Passive Mode (|||26300|)
    150 Opening BINARY mode data connection for './TESTFILE'.
    100% |************************|    15      215.41 KiB/s    00:00 ETA
    226 Transfer complete.
    15 bytes sent in 00:00 (88.24 KiB/s)
    221 Goodbye.

Using a .netrc to automate the ftp upload

This file is documented in at the end of ftp(1).

Code:
[cmd=$]mkdir WORK ; mv TESTFILE WORK ; cd WORK[/cmd]

[cmd=$]touch .netrc ; chmod g=,o= .netrc ; ls -l .netrc[/cmd]
-rw-------  1 adriaan  adriaan  0 Feb 14 20:52 .netrc

ftp(1) explains why this files needs these strict permissions:
Code:
     [b]password[/b] [u]string[/u]
               Supply a password.  If this token is present, the auto-login
               process will supply the specified string if the remote server
               requires a password as part of the login process.  Note that if
               this token is present in the [file].netrc[/file] file for any user other
               than anonymous, ftp will abort the auto-login process if the
               [file].netrc[/file] is readable by anyone besides the user.

Put the following contents in the .netrc file:

Code:
machine localhost login adriaan password PasswordSentInPlainText

macdef init
prompt off
preserve on
put TESTFILE /home/adriaan/DESTINATION/TESTFILE
ls DESTINATION
quit

Please note that a macro definition, here (init) needs to terminated
with a empty new line. That is two times an newline (\0x0a).

As explained in ftp(1), it tries to locate the .netrc, in the directory named in the HOME environment variable

Code:
     The [file].netrc[/file] file contains login and initialization information used by the
     auto-login process.  It resides in the user's home directory, unless
     overridden with the [file]-N netrc[/file] option, or specified in the [file]NETRC[/file] environ-
     ment variable.

Because we are in the directory WORK we set HOME temporarily by using env(1)

Code:
[cmd=$]env HOME=. ftp localhost[/cmd]

Trying 127.0.0.1:21 ...
Connected to localhost.
220 j65nko.org FTP server (Version 6.00LS) ready.
331 Password required for adriaan.
230 User adriaan logged in.
Remote system type is UNIX.
Using binary mode to transfer files.
[b]prompt off[/b]
Interactive mode off.
[b]preserve on[/b]
Preserve modification times on.
[b]put TESTFILE /home/adriaan/DESTINATION/TESTFILE[/b]
local: TESTFILE remote: /home/adriaan/DESTINATION/TESTFILE
229 Entering Extended Passive Mode (|||39224|)
150 Opening BINARY mode data connection for '/home/adriaan/DESTINATION/TESTFILE'.
100% |**************************|    15      261.57 KiB/s    00:00 ETA
226 Transfer complete.
15 bytes sent in 00:00 (87.19 KiB/s)
[b]ls DESTINATION[/b]
229 Entering Extended Passive Mode (|||42308|)
150 Opening ASCII mode data connection for '/bin/ls'.
total 2
-rw-r--r--  1 adriaan  adriaan  15 Feb 14 20:57 TESTFILE
226 Transfer complete.
[b]quit[/b]
221 Goodbye.

My final recommendation:

Forget about all this ftp(1) thing. Only use this if there really is no other alternative. ftp(1) is a very unsafe protocol. The password as well as the data gets sent unencrypted in plain text.Just like telnet(1) it should be retired. Use one of the safer encrypted alternatives like scp(1) or sftp(1)
 
Back
Top