转载How to use ftp in a shell script

How to use ftp in a shell script

Bruce EdigerBruce Ediger's home page


Party on!
Continue using Mozilla's browser.

You might also consider using Linux. It's faster and has less malware.

Sometimes I want to FTP a file from one machine to another. Usually, I can do the transfer interactively, but every so often, I would like to have a shell script do the file transfer. This task has eluded me in the past, but I finally figured it out. I've not seen this particular trick documented in the past, so I submit it for your approval.

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 (non-working) script

#!/bin/sh
HOST='ftp.users.qwest.net'
USER='yourid'
PASSWD='yourpw'
FILE='file.txt' ftp $HOST <<END_SCRIPT
user $USER
$PASSWD
put $FILE
quit
END_SCRIPT
exit 0

The above script will just hang if run in the foreground (in an xterm), or if run in the background (from a cron job), it will fail to perform the work of transferring file.txt.

/dev/tty names a strange, magic device. Each process (more strictly each process group) has a different /dev/tty, and you can not naively make ftp clients read the password from some non-magic, yet convenient source, like a "here document". When run in an xterm, the script above appears to hang because it reads the password from /dev/tty. The xterm constitutes the script's /dev/tty, so the script waits for keyboard input.

Example Working Script

#!/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

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.

You must the token that ends the "here document" (END_SCRIPT in the example above) at the beginning of a line. Even if the ftp command line and the login and transfer script are indented, END_SCRIPTshould appear with the 'E' as the first character of the line.

Further Refinements

The above sh script will spew lots of ftp client output to standard output. Even if everything works perfectly, the user running the above script will see lots of incomprehensible text scrolling by quite rapidly. One refinement would send output to different places:

ftp -n $HOST > /tmp/ftp.worked 2> /tmp/ftp.failed <<END_SCRIPT

One could further refine error handling by acting on the ftp client program's exit status:

ftp -n $HOST > /tmp/ftp.worked 2> /tmp/ftp.failed <<END_SCRIPT
blah blah
END_SCRIPT EXITSTATUS=$? if [ $EXITSTATUS != "0" ]
then
# handle the error...
fi

Except that the above doesn't always work - most FTP clients always exit with a status of 0. This leads to ugly "false negatives": the file transfer fails, but the script doesn't detect the problem.

One way to verify that a file transfer took place - transfer it back:

#!/bin/sh

ftp -n << END_SCRIPT
open $1
user $2 $3
put $4
get $4 retrieval.$$
bye
END_SCRIPT if [ -f retrieval.$$ ]
then
echo "FTP of $4 to $1 worked"
rm -f retrieval.$$
else
echo "FTP of $4 did not work"
fi

Regular FTPs there and back of large files can consume a lot of time.

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.


Alternative #1

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

#!/bin/sh
USER=userid
PASSWD=userpw
ftp -n f2dev <<SCRIPT
user $USER $PASSWD
binary
get some.file
quit
SCRIPT

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:

machine something.else.com
login myid
password mypassword

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

$ ls -l .netrc
-rw------- 1 bediger users 51 Dec 16 13:30 .netrc

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.


$Id$

How to use ftp in a shell script的更多相关文章

  1. shell script练习

    执行脚本的几种方式: 1. sh a.sh 或者  bash a.sh  调用的是 /bin/bash 进程执行的,所以脚本不需要执行权限. 2. 直接使用绝对路径执行, /home/script/a ...

  2. Linux 脚本运维总结之Shell script

    1. 本地变量和环境变量 变量类型 定义形式 声明位置 显示命令 作用域 本地变量 VARNAME=value 命令行或shell脚本 set (显示所有变量) 本用户,本进程 环境变量 export ...

  3. shell 编程 && bash 简介(shell 变量、shell操作环境、数据流重导向、管线命令、shell script)

    如何学习一门编程语言 数据类型 运算符 关键字 1 认识BASH 这个shell linux是操作系统核心,用户通过shell与核心进行沟通,达到我们想要的目的.硬件.核心.用户之间的关系: 原理:所 ...

  4. shell及脚本4——shell script

    一.格式 1.1 开头 必须以 "# !/bin/bash"  开头,告诉系统这是一个bash shell脚本.注意#与!中间有空格. 二.语法 2.1 数值运算 可以用decla ...

  5. shell script

    一.shell script的编写与执行 1.shell script 的编写中还需要用到下面的注意事项: a.命令的执行是从上到下,从左到右地分析与执行 b.命令.参数间的多个空白都会被忽略掉 c. ...

  6. (copy) Shell Script to Check Linux System Health

    source: http://linoxide.com/linux-shell-script/shell-script-check-linux-system-health/ This article ...

  7. 这些年我们一起搞过的持续集成~Jenkins+Perl and Shell script

    这些年我们一起搞过的持续集成~Jenkins+Perl and Shell script ##转载注明出处:http://www.cnblogs.com/wade-xu/p/4378224.html ...

  8. CentOS Linux下一个tomcat起停,查看日志的shell script

    CentOS 的tomcat安装目录:/usr/local/tomcat vi MyTomcatUitl.sh          创建文件chmod u+x MyTomcatUtil.sh   赋执行 ...

  9. Shell script for logging cpu and memory usage of a Linux process

    Shell script for logging cpu and memory usage of a Linux process http://www.unix.com/shell-programmi ...

随机推荐

  1. 利用js 获取本日 本周 本月时间代码

    function showToDay() { var Nowdate=new Date(); M=Number(Nowdate.getMonth())+1 alert(Nowdate.getMonth ...

  2. 一个小的考试系统 android 思路

    一个小的考试系统 android 思路 假如有 100 组,每组有4个单选钮,设置超时检测确认后去测结果估分视图去切换,如果还有,就再显示下一组 所有结束就给个总结显示 有超时结束过程加上 提示正确选 ...

  3. Win8.1恢复这台电脑里的6个文件夹

    平台:win8.1 问题:网络下载的ghost版8.1,装好后“这台电脑”里没有6个常用的文件夹. 解决:导入下列注册表项即可 Windows Registry Editor Version 5.00 ...

  4. vue踩坑记-在项目中安装依赖模块npm install报错

    在维护别人的项目的时候,在项目文件夹中安装npm install模块的时候,报错如下: npm ERR! path D:\ShopApp\node_modules\fsevents\node_modu ...

  5. 修改tomcat小猫图标,设置项目的favicon图标

    修改tomcat小猫图标,设置项目的favicon图标,方式有两种:全局方式和局部方式 1.全局方式: 进入tomcat服务器\webapps\ROOT,然后用自己项目的favicon.ico替换to ...

  6. Android JNI用于驱动測试

    硬件平台:S3C6410 操作系统:Ubuntu.windows 板子系统:Android 开发工具:jdk.ndk,eclipse 本次測试从linux内核模块编译開始.以S3C6410的pwm驱动 ...

  7. Activity启动过程源代码分析

    事实上写分析源代码文章总会显得非常复杂非常乏味,可是梳理自己看源代码时的一些总结也是一种提高. 这篇博客分析下Activity启动过程源代码,我会尽量说得简单点. 个人的观点是看源代码不能看得太细,否 ...

  8. Eclipse如何从SVN更新和上传修改部分项目

    1:右击项目,选择team菜单,点击与资源库同步 2:第一个箭头表示别人改动的部分 3:右击,更新,将同事改动的部分同步到自己的项目里面 4:第二个指向右边的箭头表示自己修改的文件 5:右击,提交,将 ...

  9. sampleviewer add menu item error 'assert'

    可以跟踪到 mfc提供的源代码内部,(注:如果打开了mfc源代码,设置了断点,但是跟不进去,那就需要更新PDB文件,具体网上搜)打开 wincore.cpp文件(D:\Program Files\Mi ...

  10. Dcloud课程7 单例模式一般用在什么场景

    Dcloud课程7 单例模式一般用在什么场景 一.总结 一句话总结:连接数据库,这样就保证了和数据之间只有一个连接,从而能够不占用多余资源,这样就极大的减少了资源浪费,减少了mysql或者说服务器压力 ...