Shell 交互输入自动化,我们知道命令可以接受命令行参数。Linux也支持很多交互式应用程序,如passwd
和ssh
。
我们可以创建自己的交互式shell脚本。对于普通用户而言,相较于记忆命令行参数及其正确的顺序,同一系列提示信息打交道要更容易。例如,一个备份用户工作成果的脚本看起来应该像这样:
$ backupWork.sh
如果你需要返回到同一交互式应用,实现交互式应用自动化能够节省大量的时间;如果你正在开发此类应用,这也可以避免你陷入重复输入的挫折感中。
预备知识
任务自动化的第一步就是运行程序,然后注意需要执行什么操作。之前讲过的脚本命令可能会派上用场。
实战演练
观察交互式输入的顺序。参照上面的代码,我们可以将涉及的步骤描述如下:
notes[Return]docx[Return]
输入notes
,按回车键,然后输入docx
,再按回车键。这一系列操作可以被转换成下列字符串:
"notes\ndocx\n"
按下回车键时会发送\n
。添加\n
后,就生成了发送给stdin
的字符串。
通过发送与用户输入等效的字符串,我们就可以实现在交互过程中自动发送输入。
工作原理
先写一个读取交互式输入的脚本,然后用这个脚本做自动化演示:
#!/bin/bash
# backup.sh
# 使用后缀备份文件。不备份以~开头的临时文件
read -p " What folder should be backed up: " folder
read -p " What type of files should be backed up: " suffix
find folder -name "*.suffix" -a ! -name '~*' -exec cp {} \
BACKUP/LOGNAME/folder
echo "Backed up files fromfolder to BACKUP/LOGNAME/$folder"
按照下面的方法向脚本发送自动输入:
$ echo -e "notes\ndocx\n" | ./backup.sh
Backed up files from notes to /BackupDrive/MyName/notes
像这样的交互式脚本自动化能够在开发和调试过程中节省大量输入。另外还可以确保每次测试都相同,不会出现由于输入错误导致的bug假象。
我们用echo -e
来生成输入序列。-e
选项表明echo
会解释转义序列。如果输入内容比较多,可以用单独的输入文件结合重定向操作符来提供输入:
$ echo -e "notes\ndocx\n" > input.data
$ cat input.data
notes
docx
你也可以选择手动构造输入文件,不使用echo
命令:
$ ./interactive.sh < input.data
这种方法是从文件中导入交互式输入数据。
如果你是一名逆向工程师,那可能免不了要同缓冲区溢出攻击打交道。要实施攻击,我们需要将十六进制形式的shellcode
(例如\xeb\x1a\x5e\x31\xc0\x88\x46
)进行重定向。这些字符没法直接输入,因为键盘上并没有其对应的按键。因此,我们需要使用:
echo -e "\xeb\x1a\x5e\x31\xc0\x88\x46"
这条命令会将这串字节序列重定向到有缺陷的可执行文件中。
echo
命令和重定向可以实现交互式输入的自动化。但这种技术存在问题,因为输入内容没有经过验证,我们认定目标应用总是以相同的顺序接收数据。但如果程序要求的输入顺序不同,或是对某些输入内容不做要求,那就要出岔子了。
expect
程序能够执行复杂的交互操作并适应目标应用的变化。该程序在世界范围内被广泛用于控制硬件测试、验证软件构建、查询路由器统计信息等。
补充内容
expect
是一个和shell类似的解释器。它基于TCL语言。我们将讨论如何使用spawn
、expect
和send
命令实现简单的自动化。借助于TCL语言的强大功能,expect
能够完成更为复杂的任务。你可以通过网站http://www.tcl.tk学到有关TCL语言的更多内容。
用expect
实现自动化
Linux发行版默认并不包含expect
。你得用软件包管理器(apt-get
或yum
)手动进行安装。
expect
有3个主要命令,如下表所示:
命令 | 描述 |
---|---|
spawn |
运行新的目标应用 |
expect |
关注目标应用发送的模式 |
send |
向目标应用发送字符串 |
下面的例子会先执行备份脚本,然后查找模式*folder*
或*file*
,以此确定备份脚本是否要求输入目录名或文件名并作出相应的回应。如果重写备份脚本,要求先输入备份文件类型,后输入备份目录,这个自动化脚本依然能够应对。
#!/usr/bin/expect
#文件名: automate_expect.tcl
spawn ./backup .sh
expect {
"*folder*" {
send "notes\n"
exp_continue
}
"*type*" {
send "docx\n"
exp_continue
}
}
运行该脚本:
$ ./automate_expect.tcl
spawn
命令的参数是需要自动化运行的应用程序及其参数。
expect
命令接受一组模式以及匹配模式时要执行的操作。操作需要放入花括号中。
send
命令是要发送的信息。和echo -n -e
类似,send
不会自动添加换行符,也能够理解转义字符。