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

虽然学了一些shell,但是本次任务中需要使用的SCP和expect却是第一次使用,其中也遇到了一些问题,所以在这里总结一下。

Expect

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

也正是因为如此,expect诞生了。

注意expect是独立于shell之外的,或者说他们完全不是一个东西(但是两者都是linux下很强大的工具)。当时我因为绝得expect是shell的一个补充,所以在expect中使用了很多shell的语法,呵呵!!!结果你懂的。

我在这里就简单说一下我用到的expect的基本语法,以及走过的坑,同时如果大家有愿望去学习一下的话我会在后面提供几个给我不少借鉴的网页,以便大家深入学习。

  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";

  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
  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"

注意两个点:

1、双引号,必须有。如果不加双引号,第二个ls命令在本地执行;

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

浅记初次使用expect、scp中出现的一些小问题的更多相关文章

  1. 在Android初次的前期学习中的二个小例子(2)

    Hello13:SQLite数据库 一.简述SQLite的概念和主要特性 SQLite是一个轻量级的关系型数据库,运算速度快,占用资源少,使用非常方便,支持SQL语法标准和数据库事务原则. 相对于Sh ...

  2. C# 中堆与栈的浅记

    C# 中堆与栈的浅记 什么是堆和栈? 简言之.堆和栈是驻留在内存中的区域,它们的作用是帮助我们运行代码.在.Net Framework 环境下,当我们的代码运行时,内存中的堆和栈便存储了这些代码,并包 ...

  3. C#中值类型和引用类型的差别浅记

    C#中值类型和引用类型的差别浅记         在C#中,变量的类型分为两种.各自是值类型和引用类型.         值类型的变量直接存储值,说得更详细一些,就是值类型变量在内存中直接存储它们自身 ...

  4. hybrid浅记

    目前首次接触hybrid项目,故根据翻阅了解后,浅记对它的认识. hybrid是携程推出的一个项目框架,其优点是:跨平台.开发效率高.开发成本相对较低,其不足是:体验不如Native hybrid设计 ...

  5. expect脚本中,变量的写法

    一.expect脚本中,变量的不同写法 shell脚本中定义时间变量的写法:time=`date "+%Y%m%d"` ==>>直接照搬到expect中,设置的变量是不 ...

  6. Nancy总结(二)记一次Nancy 框架中遇到的坑

    记一次Nancy 框架中遇到的坑 前几天,公司一个项目运行很久的Nancy框架的网站,遇到了一个很诡异的问题.Session 对象跳转到另外一个页面的时候,session对象被清空了,导致用户登录不上 ...

  7. 转:浅谈CSS在前端优化中一些值得注意的关键点

    前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...

  8. 浅谈Python在信息学竞赛中的运用及Python的基本用法

    浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...

  9. 记一次解决cmd中执行java提示"找不到或无法加载主类"的问题

    今天遇到一个问题:在cmd命令行中,用javac编译java文件可以成功,但是用java执行却提示“找不到或无法加载主类”.现将该问题的原因以及解决办法记录一下. 先理解一下系统变量path和clas ...

随机推荐

  1. PTA L2-006 树的遍历-二叉树的后序遍历+中序遍历,输出层序遍历 团体程序设计天梯赛-练习集

    L2-006 树的遍历(25 分)   给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格式: 输入第一行给出一个正整数N(≤),是二叉树中结点的 ...

  2. MediaPlayer滑动不准的问题

    因为MediaPlayer在seekto是异步进行的,如果在滑动过程中暂停,会导致滑动不准确的情况,这时候就需要添加滑动完成的监听即setOnSeekCompleteListener

  3. Java工具类-设置字符编码

    package common; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.Filter ...

  4. div的border & width

    长时间不用css,发现有些基础知识竟有些遗忘,由于项目中的一些css样式,进行了以下相关测试. div的width及height均设置为0后,div的border会怎样显示.经过测试后,发现borde ...

  5. ExtJs基础

    方法和属性 Ext.caeate方法相当于创建一个实例对象 renderTo:Ext.getBody()  新创建的组件渲染到什么位置 grid.render('grid-example'); /re ...

  6. Java 创建线程的方法

    为了偷懒少敲几个字这里我写了一个Util类: package test; public class Util { static void println() {System.out.println() ...

  7. shell中的特殊变量

    常见的特殊变量: $* 和 $@ 的区别: 1. 在这两个变量没有被双引号""引起来的时候,它们没有区别. 2. 在这两个变量被双引号""引起来的时候,&quo ...

  8. Sqli-labs less 12

    Less-12 本关和less11是类似的,只是在id 的参数的处理上有一定的不同 当输入username:admin" Password: (随便) 报错后的结果为: You have a ...

  9. Spring的Web服务

    Spring支持:使用JAX-RPC暴露服务,访问Web服务 除了上面所说的支持方法,你还可以用XFire xfire.codehaus.org 来暴露你的服务.XFire是一个轻量级的SOAP库,目 ...

  10. nyoj 1007 GCD(数学题 欧拉函数的应用)

    GCD 描述 The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b) ...