Another automated FTP bash script

from http://www.stratigery.com/scripting.ftp.html

Another solution from the site above for performing FTP PUTs on a schedule.

The Problem

The problem I always encountered in scripting ftp transfers involved getting a password to the ftp server. Typical ftp client programs under Unix, Linux, Solaris and NetBSD all read the ftp password from /dev/tty.

Example Working Script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<kbd>#!/bin/sh
HOST='ftp.users.qwest.net'
USER='yourid'
PASSWD='yourpw'
FILE='file.txt'
 
ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
put $FILE
quit
END_SCRIPT
exit 0
</kbd>
<kbd>#!/bin/sh
HOST='ftp.users.qwest.net'
USER='yourid'
PASSWD='yourpw'
FILE='file.txt'

ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
put $FILE
quit
END_SCRIPT
exit 0
</kbd>

The Tricks

Getting the password to the ftp server without having the ftp client program read the password from /dev/tty requires two tricks:

  1. Using the -n option on the ftp client program to prevent the ftp client from trying to log in immediately. That way, the ftp client does not ask for a user ID and password. No use of /dev/tty.
  2. Use the ftp client program command quote to send user ID and password to the ftp server.

Control of ftp by a shell script

One obvious improvement would have the ftp client program controlled by the shell script. I don’t think that would comprise an impossible task, but I also don’t think that it would have much value. Scripting ftp transfer using expect might cause you less pain, except that it is sensitive to the environment that it is run in. Changes to default program inputs and outputs can break it.


Alternative #1

I saw a second way of doing this in a usenet article:

1
2
3
4
5
6
7
8
9
10
<kbd>#!/bin/sh
USER=userid
PASSWD=userpw
ftp -n f2dev <<SCRIPT
user $USER $PASSWD
binary
get some.file
quit
SCRIPT
</kbd>
<kbd>#!/bin/sh
USER=userid
PASSWD=userpw
ftp -n f2dev <<SCRIPT
user $USER $PASSWD
binary
get some.file
quit
SCRIPT
</kbd>

It still uses the “-n” trick, but it sends user ID and password in the same “user” command.


Alternative #2

Use a .netrc file

Linux, Unix and BSD users have the alternative of using a .netrc file. The ftp man page documents the format of .netrc. To accomplish the task of using ftp in a shell script you would have to fill out a .netrc file something like this:

1
2
3
4
5
<kbd>
machine something.else.com
login myid
password mypassword
</kbd>
<kbd>
machine something.else.com
login myid
password mypassword
</kbd>

ftp demands that .netrc not have group or world read or write permissions:

1
2
3
4
<kbd>
$ ls -l .netrc
-rw-------    1 bediger  users          51 Dec 16 13:30 .netrc
</kbd>
<kbd>
$ ls -l .netrc
-rw-------    1 bediger  users          51 Dec 16 13:30 .netrc
</kbd>

Using a .netrc file has a few problems that may or may not prevent you from using it.

  • A shell scripkt that does FTP using .netrc is no longer self-contained. You have to keep track of two files, which means that bugs can be less than obvious.
  • ftp reads it’s user ID’s .netrc. If you develop your script under a given user ID, then put it in production under a second user ID, you have to coordinate .netrc file contents between those two user IDs.

Alternative #3

Apparently, the Ckermit program from Columbia University understands FTP. You could use Ckermit to script FTP transfers. This looks to have advantages and disadvantages. On the “pro” side, it appears that Ckermit can exit on various errors, like unknown user IDs, or bad passwords. On the “con” side, you have to have Ckermit. I don’t recall that it had a too onerous install, but it doesn’t come with many Linux distros these days, and it probably doesn’t come with any vendor Unix.

See also http://www.linuxforums.org/forum/programming-scripting/106665-automatic-ftp-upload-via-script.html

#!/bin/bash
# puts the file bookmarks.html
cd $HOME/.mozilla/firefox/
cd ./*.default/
UDIRX=`pwd`
HOST='www.linuxforums.org'
USER='core-wizard'
PASSWD='leethaxor'
BASENAME=$(basename $UDIRX)
echo '$UDIRX is' $UDIRX
echo '$BASENAME is' $BASENAME

ftp -n -v $HOST << EOT
ascii
user $USER $PASSWD
prompt
mkdir .mozilla
cd .mozilla
mkdir firefox
cd firefox
mkdir $BASENAME
cd $BASENAME
put bookmarks.html
bye
EOT
sleep 12