用expect实现通过scp自动上传文件的脚本
所以使用第二种方法,expect。
expect是基于tcl的一种脚本语言,它主要是为了实现交互式的脚本(貌似perl也可以做到,但是我不会-_-)。
expect并不在linux的默认安装包里,因此需要独自安装。源码很好找。另外,expect的安装需要tcl的源码。。
Tcl安装方法:下载tcl包。(建议8.4.13,因脚本己在8.4.13下测试通过。下同),解压后进入源码根文件夹,执行以下命令
Cd unix
./configure --prefix=/usr/tcl
Make
Make install
Cd ..
cp ./unix/tclUnixPort.h ./generic/
不要删除源码。安装expect需要用到
然后解压expect包,(建议5.43.0)进入expect源码根文件夹
./configure -prefix=/usr/expect -with-tcl=/usr/tcl/lib -with-x=no -with-tclinclude=/root/tcl8.4.13/generic
加粗斜体部分为你的tcl源码包的文件夹
然后
Make
Make install
这样expect就安装好了,自动传文件的脚本在最后(-_-刚刚用cublog,不知道怎么在代码后面写正文,所以直接把代码放最后了)
set remotedir [lindex $argv 0]
这是expect声明变量的方法,中括号内表示的是输入的第一个参数,expect与其它脚本稍有不同,它的第一个参数是argv0,而其他脚本一般为argv1
set timeout 10000000000
这句是设置超时时间。应该是秒,但是好像不大准确的样子。默认的timeout是10,我设成这么大是因为传送的文件比较多,估计10秒内传不完
if {$file == 0} { if {$load == 0} {spawn scp $mydir $remotedir} else {spawn scp $remotedir $mydir } }
这就是expect中恶心的if-else语句了。。。这个东西写了我很久,它的条件判断需要放在大括号内,大括号不能独成一行(可以理解,没有";"嘛),另外,else貌似也不能独成一行,必须接到前一个if的后面。而且与大括号之间要有间隔-_-。。具体没搞懂,不过直接写在一行内肯定不会错。
expect "Are you sure you want to continue connecting (yes/no)?" { send "yes\r" } "Password:" { send "$password\r" }"Permission denied*" { break } "*No route to host" { break } "*No such file or directory" { break } timeout { break } eof {break }
这句就是整个脚本最关键的了。expect后面跟了很多字符串,如果得到了与某个字符串相匹配的串,那么执行该字符串后面的语句。比如得到了"Password:",那就执行send "$password\r"。这里也不能分行写。我从网上找的教程有一个分行写。。害死我了
另外,求高人指点如果用expect spawn一个没有输出的程序?比如
ls -l > log.txt
|
PS:有一个问题需要注意一下,如果在expect中
spawn ls /*
会出错,提示找不到/*这个文件,看起来expect是把*解释成了普通字符而非正则表达式。