自动化程序升级与远程控制工具的实现

随着分布式架构的普及,程序的升级和维护变得越来越复杂。为了简化这一过程,自动化升级程序成为了一种常见的解决方案。本文将介绍一种基于expect.net技术的自动化程序升级和远程控制工具的实现过程。

1. 分布式架构下的程序升级

在分布式架构下,程序升级往往需要在多个服务器上进行。传统的手动升级方式不仅耗时,而且容易出错。因此,执行预定义的脚本以自动远程更新程序成为了一种有效的解决方案。这种方式可以节省大量的工作和时间。

2. 批量程序安装工具

有许多工具支持自动执行脚本和远程控制机器,如putty、plink和telnet。但它们有一些限制,例如su命令。"Expect"技术克服了这些问题,它将stdin和stdout重定向到程序,就像操作员在终端执行命令一样。

3.脚本引擎的需求

脚本引擎的需求如下:

  • 使用终端程序通过ssh控制远程服务器
  • 通过sftp将文件传输到远程服务器
  • 在远程服务器上挂载USB驱动器
  • 停止即将升级的服务
  • 将步骤2中上传的文件复制到指定路径,然后启动服务
  • 当出现问题时通知操作员

4. 实现脚本引擎

常用的expect.net API如下:

// 1. 实例化一个可生成进程的ISpawnable对象 ProcessSpawnable(execute_command, command_args) // 2. 执行ISPawnable进程 Session spawn = Expect.Spawn(ISpawnable); // 3. 等待远程服务器的响应。如果得到回复,执行第二个参数中定义的匿名函数。否则抛出异常。 spawn.Expect( "Password:", (s) => Console.WriteLine("found: " + s) ) // 4. 设置等待超时 spawn.Timeout = 30000 // 5. 向远程服务器发送命令 spawn.Send()

以"使用plink登录远程Linux服务器"为例,展示expect.net的特点。

// 执行plink Session spawn = Expect.Spawn( new ProcessSpawnable( "c:\\plink.exe", "-l username -pw password xx.xx.xx.xx -t" ) ) // 等待远程服务器响应包含"$"的字符串。如果在超时前得到字符串,打印出来。 spawn.Expect( "$", s => Console.WriteLine("got: " + s) ) // 向远程服务器发送"su"命令 spawn.Send("su\n") // 等待远程服务器响应包含"Password:"的字符串。如果在超时前得到字符串,打印出来。 spawn.Expect( "Password:", (s) => Console.WriteLine("found: " + s) ) // 向外发送密码 spawn.Send("1234\n") // 等待远程服务器响应包含"root"的字符串。如果在超时前得到字符串,打印出来。 spawn.Expect( "root", (s) => Console.WriteLine("found: " + s) ) // 向外发送chmod命令 spawn.Send("chmod 777 /home/guest\n")

对于"批量升级"工作来说,错误管理非常重要。如果在升级过程中出现问题,工具必须让用户容易且清晰地知道问题所在。

现在设计了一个机制,工具在执行期间会为每个远程服务器本地保留日志。如果执行期间出现问题,日志文件名的尾部会替换为"err"。操作员只需检查文件名带有"err"的文件,就可以知道问题所在。

脚本引擎设计了两个执行参数,它们的含义如下:

  • expect script_file_path remote_server_ip
  • 第一个是执行脚本的路径。第二个是远程服务器的IP。参数定义了脚本文件中变量''的值。

脚本的格式如下:

opcode op1 op2 #opcode 是脚本命令的名称 #op1, op2 是opcode的参数。参数的数量可以是一个或两个,取决于opcode。

脚本命令如下:

  • spawn:实例化一个执行命令和参数的spawn对象。
  • expect:有三种类型的expect命令。
  • 获取进程pid并杀死pid。
  • 挂载USB驱动器。
  • 分配远程服务器IP。

5. 脚本的使用

// 实例化一个名为s1的spawn对象,并执行plink和参数。 spawn s1 "c:\plink.exe", "-l username -pw password -t" // 实例化一个名为s2的spawn对象,并执行psftp。 spawn s2 "c:\psftp.exe", "-l username -pw password " // 在plink上执行"su",并在得到"Password:"字符串后发送密码"1234"。 s1.expect "Password:" "su" s1.expect "#" "1234" // 在plink上执行"chmod"并检查执行结果。之后等待得到"#"字符串。 s1.expect_with_check "#" "chmod 777 /home/guest" s1.expect_with_check "#" "mkdir /home/usb" // 将USB驱动器挂载到/home/usb s1.mountusb osusb /home/usb // 在psftp上执行"put",并等待得到">"字符串,使用expect_longtimeout命令,因为通过ftp上传文件需要更长的时间。 s2.expect_with_check ">" "cd /home/guest/" s2.expect_longtimeout ">" "put c:\test.txt" // 获取执行execute_pcs时的PID,并将其分配给ncspid对象。 s1.assignpid ncspid execute_pcs // 杀死存储在ncspid对象中的PID。 s1.kill "#" ncspid // 在plink上执行"cp"命令,并将/home/guest/test.txt复制到/home/usb/test/。 s1.expect_with_check "#" "cp /home/guest/test.txt /home/usb/test/" s1.expect_with_check "#" "umount /home/usb/" s1.expect "#" rmdir /home/usb/
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485