浅记初次使用expect、scp中出现的一些小问题

之前也学过一些shell,不过学得并非很深刻,动手写的代码的时间也不是不少。前不久将shell比较细的过了一遍,leader布置了任务让用shell写一个脚本将redis源码压缩包从一个服务器上传到另一个服务器,同时在本服务器上传入命令,解压源码包并在另外一个服务器上启动redis服务。html

虽然学了一些shell,可是本次任务中须要使用的SCP和expect倒是第一次使用,其中也遇到了一些问题,因此在这里总结一下。linux

Expect

现代的Shell对程序提供了最小限度的控制(开始,中止,等等),而把交互的特性留给了用户。 这意味着有些程序, 你不能非交互的运行,好比说passwd。简单点说就是你得手动输入密码,shell没有提供给你将密码直接在程序中一次性搞定的方法。redis

也正是由于如此,expect诞生了。shell

注意expect是独立于shell以外的,或者说他们彻底不是一个东西(可是二者都是linux下很强大的工具)。当时我由于绝得expect是shell的一个补充,因此在expect中使用了不少shell的语法,呵呵!!!结果你懂的。小程序

我在这里就简单说一下我用到的expect的基本语法,以及走过的坑,同时若是你们有愿望去学习一下的话我会在后面提供几个给我很多借鉴的网页,以便你们深刻学习。centos

  1. 最简单的#!/usr/bin/env sh和#!/usr/bin/env expect 就懒得说了;
  2. 其次在expect中,传入参数的个数是用$argc访问的,然而在shell中$#。虽然很简单,可是shell中下面这几个参数仍是记得的好:

  

  3. shell中设置变量,$a="hello world",expect中 set a "hello world" 服务器

  4. 在expect中查看变量的值:send_user "$a";ssh

  5. 在expect中执行shell的程序: spawn <shellCommand>工具

  6. expect中查看传入的参数的值:[lindex $argv 1] [lindex $argv 2] [lindex $argv 3]...[lindex $argv n]学习

  7. 特别有用的:用于进行交互的expect 和 send。我也没学得太深,只能大概举一个例子:

  spawn ssh -l username 192.168.1.1

  expect "*password:"

  send "ispass\r"

  就差很少这个样子吧!特别注意的是:send 后面的密码最后必定要跟一个\r,不然你等着错吧!!!

  恰好到这里就再说说我遇到的一个大坑——状况是这样的,为了提升代码的复用性,导师都是让我不要把什么密码啊这一类的写死的,要么传参要么设置环境变量值,我选择了传参的方法,就好比下面这个程序:

  hello.sh

  #!/usr/bin/env expect

  set host [lindex $argv 1] 

  set passwd [lindex $argv 2] 

  spawn ssh -l username $host

  expect "*password:"

  send "$passwd"

  执行的命令是这样的:./hello.sh "192.168.1.1" "ispass\r"

  好了,TMD。一直出错,不记得具体报什么错了,好像是提示密码错误。怎么会出错呢,纠结,纠结.....足足纠结几个小时啊!!!不知道错哪儿了

  后来看到了这篇文档(http://blog.itpub.net/27042095/viewspace-745589/)的第一张图片,恍然大悟啊!!!赶快改正过来。

  hello.sh

  #!/usr/bin/env expect

  set host [lindex $argv 1] 

  set passwd [lindex $argv 2] 

  spawn ssh -l username $host

  expect "*password:"

  send "$passwd\r"

  执行命令:./hello.sh "192.168.1.1" "ispass"

  8. 这个必定要注意:若是你在expect中利用ssh登陆了某个服务器,你但愿直接进入那个服务器(简单点说就是你如今是在服务器长操做了,看到的是服务器的文件)必定要使用interact

  简单举一个例子吧:

  #!/usr/bin/expect
  set timeout 30
  spawn ssh -l username 192.168.1.1
  expect "password:"
  send "ispass\r"
  interact
  expect eof

  9.程序嘛!仍是尽可能有expect eof 和exit的好一点;

  10. 最大的坑来了,expect的if用法:

  if { <条件判断> } {
    <commands>...
  } else {
    <commands>...
  }

  也许你没仔细看,我来提醒你一下:

  1. if的后面是大括号{},不是();
  2. if和后面的大括号之间是有一个空格的,你造吗?
  3. 注意下面这张图片的红色框起来的部分:

  

  你造上面红色框框起来的部分必须在一行吗?并且彼此之间是必须有空格分隔的。唉,当时这个问题,都快把本身调试哭了!!!

  有了上面的语法,你们简单编辑一个小程序已经够了!!!至少完成个人任务我只用到了上面的语法,若是你们想比较深刻的学习,下面的几个网站值得一看呢!!!

  很浅的语法:http://www.cnblogs.com/arlenhou/p/learn_expect.html

  例子虽短,但给我比较多启发的一个网站:https://www.centos.bz/tag/expect/

  expect学习笔记及实例详解(真的不错) :http://blog.itpub.net/27042095/viewspace-745589/

  Expect 教程中文版:http://fanqiang.chinaunix.net/a4/b8/20010912/1000001278.html

SCP

scp的语法是简单又实用,原本还想讲一下的。不过实在感受下面这篇文档已经太棒了,因此这里直接给个链接吧!!!

SCP 命令:http://www.cnblogs.com/hitwtx/archive/2011/11/16/2251254.html

 

最后须要提一下的是,本程序中用到了利用ssh控制远程服务器执行命令的方法:

ssh <username>@<host> "<command1>;<command2>...<command3>"

如:ssh zhangsan@192.168.1.1 "cd /home;ls -l"

注意两个点:

一、双引号,必须有。若是不加双引号,第二个ls命令在本地执行;

二、分号,两个命令之间用分号隔开。

相关文章
相关标签/搜索