首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用perl的expect对linux下使用fdisk对硬盘自动分区

使用perl的expect对linux下使用fdisk对硬盘自动分区

有一种方法是使用EOF


fdisk /dev/sda <<EOF
n
p
1
1

EOF



因为linux下,EOF


<<EOF
(内容)
EOF


说明 <<EOF 的意思是 EOF 以后的内容,作为流输入 传给前面的应用, 直到遇到EOF ,中止输入..注意 EOF 前面不能有空格





[url=]下载和安装[/url]

Expect 和 Expect::Simple 都可以从 CPAN 网站上直接下载,最新版本为 Expect-1.21 和 Expect::Simple-0.04。比较方便的安装方法是使用 Perl 自带的包管理工具 cpan:


[url=]清单 1. 模块安装[/url]

                              

perl -MCPAN -e 'install Expect::Simple'

[url=]Expect [/url]模块详解

与最初的 Expect 语言类似,Expect 模块的主要功能也通过 spawn,expect,send 三个方法实现。

[url=]spawn[/url]:启动目标程序


[url=]清单 2. spawn 方法原型[/url]

                              

$obj = Expect->spawn( $command, @parameters );

spawn 是 Expect 类的主要方法之一,通过 fork 和 exec 启动目标程序,若成功则返回 Expect 对象,否则返回 undef。参数 $command 指定目标程序,@parameters 为可选参数。下面是一个简单的例子:


[url=]清单 3. spawn 用法示例[/url]

                              

$obj1 = Expect->spawn( "ftp 9.9.9.9" );         
# 启动 ftp 进程

$obj2 = Expect->spawn( "ftp", "9.9.9.9" );      
# 与上一行等效

上述两行执行结果相同,但其实际处理过程存在细微差别。一般情况下我们可以把完整的命令行 ( 甚至可以是复合命令,包括命令、参数、管道符、重定向符等 ) 都写入 $command 而不指定 @parameters。

注:在 spawn 的实现中,$command 和 @parameters 都原封不动地传递给了 Perl 的 exec 函数。根据 exec 函数的说明文档,如果传递进来的是多元列表参数,exec 直接将其传递给 execvp 系统调用;如果传递进来的是标量参数或者单元列表参数,exec 函数将检查是否存在 shell 元字符 ( 如 | & ; ( ) < > 等 ),若存在,则将此参数交给系统 shell 进行解析,否则将其分词后传递给 execvp 系统调用。因此如果 spawn 的是一个含有 shell 元字符的复合命令,我们一般只能将其完整写入 $command。

[url=]expect[/url]:等待特定输出


[url=]清单 4. expect 方法原型[/url]

                              

$obj->expect( $timeout, @match_patterns );

使用 Expect 对象的 expect 方法等待目标程序的特定输出。参数列表中 $timeout 设定超时 ( 以秒为单位 ),@match_patterns 提供一个或多个匹配模式,如果在设定时间内目标程序输出结果和 @match_patterns 中某元素匹配则成功返回。缺省情况下 expect 使用精确匹配,若想使用正则表达式,可以在该模式元素前加 '-re' 前缀 :


[url=]清单 5. 启用正则表达式匹配[/url]

                              

$obj->expect( 10, 'match me exactly', '-re'=>'match\s+me\s+exactly' );

标量上下文中 expect 返回匹配模式在 @match_patterns 中的位置 ( 注意下标从 1 开始 ),若不成功则返回 undef。而列表上下文中 expect 返回一个包含详细匹配信息的列表:


[url=]清单 6. expect 方法的列表返回值[/url]

                              

( $pos, $err, $match, $before, $after ) = $obj->expect( $timeout, @patterns );

其中 $pos 就是在标量环境中的返回值,$err 是出错信息,$match 为成功匹配的字串,$before 为匹配字串之前的输出部分,$after 为匹配字串之后的输出部分。

[url=]send[/url]:发送数据

[url=]清单 11. send 方法原型[/url]

                              

$obj->send( @strings );

当交互式程序等待用户输入时,可以使用 send 方法向其提供输入数据。需要注意,send 送出的数据可能会回显在终端上 ( 具体与终端设置有关 ),此数据会进入 Expect 对象的匹配缓冲区,被下一个 expect 动作接收。为了避免 send 数据对 expect 匹配造成混乱,一般可以使用 $obj->stty("-echo" )方法关闭终端回显,或者在 spawn 前使用 $obj->raw_pty(1)将终端设定成 raw 模式 (raw 模式将关闭回显,禁止回车 - 换行符翻译 ),或者为expect 提供更加精确的匹配模式。



linux下使用fdisk命令对硬盘自动分区需要进行交互命令的选择,如果有多个硬盘需要分区,想用脚本实现自动化分区。





$exp = new Expect;  #new一个Expect.
$exp->spawn($command,@params);  #fork和exec一个新进程用来执行$command命令.
$exp->expect($timeout,$content); #'-re'.在$timeout内,期待出现包含$content内容的正则表达式,如果不加re默认是精确匹配,也可以使用正则表达式,expect($timeout,re=>'').
$exp->send($string);  #向终端发送字符
$exp->debug(0|1|2);  #打印debug 信息,不同的数字表示不同的bug级别
$exp->interact();   #和用户进行交互,把控制权转交给用户
$exp->soft_close();  #软关闭,直到$timeout时间到达,才关掉该进程
$exp->hard_close();  #硬关闭,立刻关闭该进程
$exp->match();   #返回匹配的结果
$exp->match_number(); #返回匹配的个数
$exp->send_slow(); # 就是让command慢慢敲进去..
$exp->stty();
#它和外部命令 stty 类似,设定 terminal 的模式,-raw 还是 -cooked.开关回显 echo 和 -echo.










原本的expect脚本语言实现fdisk 自动分区


$ vi fdisk.exp

Shell代码

1.
#!/usr/bin/expect -f  

2.
  

3.
spawn fdisk /dev/hda  

4.
expect -exact "Command (m for help): "  

5.
send -- "p\r"  

6.
expect -exact "Command (m for help): "  

7.
send -- "q\r"  

8.
expect eof  



$ chmod +x fdisk.exp
$ ./fdisk.exp ##

输出如下

Shell代码

1.
spawn fdisk /dev/hda  

2.
  

3.
The number of cylinders for this disk is set to 9729.  

4.
There is nothing wrong with that, but this is larger than 1024,  

5.
and could in certain setups cause problems with:  

6.
1) software that runs at boot time (e.g., old versions of LILO)  

7.
2) booting and partitioning software from other OSs  

8.
   (e.g., DOS FDISK, OS/2 FDISK)  

9.
  

10.Command (m for help): p  

11.  

12.Disk /dev/hda: 80.0 GB, 80026361856 bytes  

13.255 heads, 63 sectors/track, 9729 cylinders  

14.Units = cylinders of 16065 * 512 = 8225280 bytes  

15.  

16.   Device Boot    Start       End    Blocks   Id  System  

17./dev/hda1   *         1      1275  10241406   83  Linux  

18./dev/hda2          1276      1340    522112+  82  Linux swap  

19./dev/hda3          1341      9729  67384642+   5  Extended  

20./dev/hda5          1341      4987  29294496   83  Linux  

21./dev/hda6          4988      6203   9767488+  83  Linux  

22./dev/hda7          6204      7419   9767488+  83  Linux  

23./dev/hda8          7420      8635   9767488+  83  Linux  

24./dev/hda9          8636      9729   8787523+  83  Linux  

25.  


26.Command (m for help): q  


或者


vim ./Auto_partitions.exp


#!/usr/bin/expect
set SIZE ""
set date [exec date "+%Y-%m-%d"]
set DEV [exec fdisk -l | grep "Disk /dev/*" | cut -c 6-13 | grep -v "a" ]
puts "$DEV"
spawn fdisk $DEV
expect "Command (m for help):"
exec sleep 0.5
send "n\r"
expect "*"
send "p\r"
expect "(1-4):"
send "1\r"
expect "default 1):"
send "\r"
expect "*):"
send "\r"
expect "Command (m for help):"
send "w\r"
interact


使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄、收藏。可是为什么要这么写却不知其然。本文用一个最短的例子说明脚本的原理。
  脚本代码如下:

1

2

3

4

5

6

7

8

##############################################

#!/usr/bin/expect

set timeout 30

spawn ssh -l username 192.168.1.1

expect "password:"

send "ispassr"

interact

##############################################

返回列表