交互式进程(如telnet)的自动处理脚本【转】

半兽人 发表于: 2017-11-14   最后更新时间: 2021-09-07 09:43:57  
{{totalSubscript}} 订阅, 6,144 游览

最近写了不少bash脚本,方便开发和调试;不到三个月的时间就累积了二十几个不同功能的小工具;现在小结一下,记录bash编程的一点心得和体会。

一如既往,当我遇到经常需要键入相似的命令组合、反复执行类似的操作的时候,我就会设法写个批处理、自动化的脚本,以减少重复劳动。我们的工作进程一般都预留一个调试控制台端口,可以利用telnet执行自定义的调试指令。比较典型的一个工作场景的操作如下:

user$telnet 127.0.0.1 23  
telnet to 127.0.0.1:23, connecting...  
escape character is "^]"  
>getCustomValue  
CustomValue = 0  
>setCustomValue 12345  
CustomValue = 12345  
>^]  
telnet>quit  
Close connection ...  
user$  

当需要反复操作,例如想随时查看一些调试信息时,我就会觉得啰嗦,总想偷懒,寻找减少敲击次数的方法。

对于利用脚本执行这种交互式的操作,网上查到的解决办法主要有两大方向:一是通过输入重定向,二是使用如expect等的工具。个人偏好用bash,因此选择了方法一。原始代码如下:

#!/bin/bash  

rm -f tmp_in  
mknod tmp_in p  
exec 8<> tmp_in  

telnet 127.0.0.1 23 <&8 &  
echo "getCustomValue" >> tmp_in  
echo "setCustomValue 12345" >> tmp_in  

大概的原理是用mknod tmp_in p建立一个管道文件,作为输入重定向。因此我们可以不断向tmp_in输入字符,传递给telnet,从而执行一个又一个自定义指令。

当然,这个脚本需要完善的地方还有很多,例如ip、端口和命令等内容都写死了,不方便重用;还有就是telnet在后台一直等待tmp_in的输入,在脚本结束后telnet还在后台执行没退出。根据我的需要把脚本改为:

#!/bin/bash  

#parse arguments  
if [ $# -lt 2 ] ; then  
    echo "$0 [port] [custom command] ..."  
    exit  
else  
    port=$1  
    command="$2 $3 $4 $5 $6 $7 $8 $9"  
fi  

#redirect input  
rm -f tmp_in  
mknod tmp_in p  
exec 8<> tmp_in  

#process custom command  
telnet 127.0.0.1 ${port} <&8 &  
echo "${command}" >> tmp_in  
sleep 1  

#quit: escape character ^] ascii is \035  
echo -e "\035quit" >> tmp_in  

这样,之前的操作可以用./customTelnet.sh 23 getCustomValue./customTelnet 23 setCustomValue 12345两个命令操作代替了。稍微一提的是退出符"^]",在命令交互时是按ctrl+],查ascii码表可知是0x1D,即035,最初我写脚本的时候没认真看echo的说明,忘了加-e选项,困扰了不少时间;此外是"\035quit“不能分开两个echo,否则相当于中间插入回车,又回到了telnet的命令交互模式。

这个脚本的真正”威力“在于和其他工作工具协作实现自动化。例如:利用./customTelnet xx | grep xx | awk xx | sed xx实现对调试信息的进一步处理,或者是作为一个基本命令在另一个脚本里执行:for port in portlist do ./custom ${port} xx,等等...这样这个脚本可以作为许多业务操作实现复杂功能的基本组件。类似地,凡是像telnet那样有交互式控制台的进程,例如我现在项目需要用到的mysql、ftp等,都可以写脚本进行自动化批处理。

当然,这个脚本可以改进的地方还有很多,例如输入参数的处理,标准输入重定向的临时文件处理,ip地址,延时操作等等。

学习bash,最好的方法是实践,在编写bash脚本的过程中,还需要学习到其他方面的内容,例如awk、sed等常用命令、正则表达式还有linux的系统管理等。不像c/c++,我对bash的语法是很不熟悉,经常是使用的时候再细查,过后可能又会忘掉...此外,现在我复用的基础模块是文件,还没接触过函数,毕竟我的脚本还很简单。期待以后掌握函数之后能发挥bash更大的效能。

更新于 2021-09-07

查看Linux更多相关的文章或提一个关于Linux的问题,也可以与我们一起分享文章