天天看点

【shell】shell实现交互

目录

​​一、shell​​

​​1.1 输入单个指令​​

​​1.2 输入多行指令​​

​​限制输入内容的个数​​

​​控制输入内容的可见性​​

​​ 二、expect​​

​​简介​​

​​实例​​

​​ssh登录​​

​​ ftp文件同步​​

一、shell

自动输入yes

echo "y" | yum install wget ,等同于yum -y  install wget

自动输入回车

echo -e "\n" | yum remove wget

**`echo -e` 的小知识**

若字符串中出现以下字符,则特别加以处理,而不会将它当成一般文字输出:

​<code>​\a​</code>​ 发出警告声;

​<code>​\b​</code>​ 删除前一个字符;

​<code>​\c​</code>​ 最后不加上换行符号;

​<code>​\f​</code>​ 换行但光标仍旧停留在原来的位置;

​<code>​\v​</code>​ 与\f 相同;

​<code>​\n​</code>​ 换行且光标移至行首;

​<code>​\r​</code>​ 光标移至行首,但不换行;

​<code>​\t​</code>​ 插入 ​<code>​tab​</code>​ 符号;

​<code>​\\​</code>​ 插入 ‘' 字符;

​<code>​\nnn​</code>​ 插入 nnn(八进制)所代表的 ascii 字符;

输入多行指令我们需要借助输入重定向操作符 ​<code>​&lt;&lt;​</code>​

以下面这个脚本为例

multi.sh

借助 ​<code>​&lt;&lt;​</code>​ 符号进行自动化输入

但是有时候这种方法并不生效,比如 ​<code>​ssh-keygen​</code>​ 命令,那只有借助强大的 ​<code>​expect​</code>​ 命令了

我们还可以使用 read命令的-n 选项,此选项后面需要接一个数字,可以限制输入内容的个数。

目前,我们输入的内容都是可见的,但有些敏感的数据,如密码,信用卡号等信息,输入时并不想可见。那么可以使用​<code>​read -s​</code>​。

【shell】shell实现交互

这时再输入时,就有一个钥匙的标识,而且输入时不可见。

 二、expect

 expect是一个免费的编程工具,用来实现自动和交互式任务通信,安装 ​<code>​yum install -y expect​</code>​ 

expect的语法:

关键命令send、expect、spawn和interact:

send:用于向进程发送字符串,注意一定要在末尾加\r回车

expect:从进程接收字符串

spawn:启动新的进程

interact:允许用户继续交互

expect 有两种用法,一种是直接写 expect 解释器的脚本,和 bash 类似,以 ​<code>​#!/usr/bin/expect​</code>​ 开头

下面是一个合格的 expect 脚本示例

需要注意的是,在 expect 解释器内, 除了几个特定关键字的命令,其他命令都不可用,这种方式适用于执行命令较少,单次需要交互较多的自动化脚本

第二种用法是在 bash 脚本中执行 expect 配合重定向操作符, 在有大量脚本需要执行的情况下推荐使用该方式

下面是我在 ​<code>​certbot​</code>​ 命令时使用的 shell 脚本,以供参考

 expect是关键的部分,在英文中,expect有“期待”的意思,采用了tcl的模式-动作语法,此语法有以下几种模式:

单一分支语法:

多分支模式语法:

例:expect脚本ssh.exp内容:

经常要面临在某个环境编辑代码然后需要自动同步更新到其他机器的情况。对于这种问题,我们也可以借助expect脚本来实现。

例:

配置文件为sync.cfg:

shell脚本sync_ftp.sh内容:

expect脚本sync_ftp.exp:

由于文件同步是每天都需要进行的,因此可以结合定时任务crond来进一步简化工作。crond是类unix系统下用来周期执行某种任务或者事件的一个守护进程,配置信息存放在/etct/crontab文件中。crontab是系统服务crond的控制命令。关于crontab的使用,在进程章节已经进行了介绍,这里就不再赘述了。

expect命令是很强大的,可以实现各种自动化操作。自此,你不仅可以写出各种厉害的shell脚本,还能让它们自动执行,对于日常工作的处理将会有大大的提升。

注:expect命令

[set timeout 30]     

    基本上认识英文的都知道这是设置超时时间的,现在你只要记住他的计时单位是:秒   

[spawn ssh -l username 192.168.1.1]    

spawn command命令会fork一个子进程去执行command命令,然后在此子进程中执行后面的命令;   

spawn是进入expect环境后才可以执行的expect内部命令,如果没有装expect或者直接在默认的shell下执行是找不到spawn命令的。所以不要用 “which spawn“之类的命令去找spawn命令。好比windows里的dir就是一个内部命令,这个命令由shell自带,你无法找到一个dir.com 或 dir.exe 的可执行文件。    

    它主要的功能是给ssh运行进程加个壳,用来传递交互指令。   

[expect "password:"]   

    这里的expect也是expect的一个内部命令,有点晕吧,expect的shell命令和内部命令是一样的,但不是一个功能,习惯就好了。这个命令的意思是判断上次输出结果里是否包含“password:”的字符串,如果有则立即返回,否则就等待一段时间后返回,这里等待时长就是前面设置的30秒   

[send "ispass\r"]   

    这里就是执行交互动作,与手工输入密码的动作等效。   

    温馨提示: 命令字符串结尾别忘记加上 “\r”,如果出现异常等待的状态可以核查一下。   

[interact]    

    执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。如果你只是登录过去执行一段命令就退出,可改为[expect eof]

expect可以让你使用“-c”选项,直接在命令行中执行它,例如:

expect -c '

        spawn git pull

        expect {

        "usernam*" {send "[email protected]\n"; exp_continue }

        "passwor*" {send "$git_code_password\n" ; exp_continue}

        }

        '