扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
企业主机服务器日常运维工作中,经常需要登录并以 root 方式执行系统操作,如果在主机数量少的情况下,手工方式登录并执行效率尚可,但如果主机数量庞大(如笔者运维的国外客户服务器数量达 2000+),依次对一台台服务器进行手工操作工作量巨大且出错概率与主机数量成线性增大。 本文分析了在大数量企业服务器情况下,利用 shell 管道,Java SSHD 开源包,Expect 脚本三种方式实现自动登录并执行系统运维操作,三种方式分别适用于不同的场景,可以满足绝大多数企业主机服务器自动化运维的工作内容,大大减轻了系统管理 员的工作量,同时降低了操作失误的风险。 本文中的三种方式的代码示例稍作修改,即可直接用于实际的生产主机的运维工作。
采用自动化脚本进行企业服务器运维的原因
传统 Unix 主机服务器手工运维方式的问题
大型企业的 IT 基础设施中,Unix 主机服务器占据重要的地位。在日常运维工作中,经常需要登录并以 root 方式执行系统操作。如果在主机数量少的情况下,手工方式登录并执行运维工作的效率尚可,但如果主机数量庞大(如笔者运维的国外客户服务器数量达 2000+),依次一台台服务器的登录和操作工作量巨大,且出错的概率随服务器数量的增加的递增。
采用自动化脚本进行运维的特点及好处
在大数量 Unix 企业服务器情况下,为了提高运维工作效率,减低手工操作而出错的风险,采用自动化脚本进行运维是一个很好的方式。通过向脚本提供主机列表,用户名账户名密 码等输入参数方式,让其自动登录远程目标主机并执行相应的运维操作,批量处理所有涉及的企业服务器主机。该方式下系统管理及运维人员只需要在自动化脚本中 提供一次系统运维操作的步骤命令,设定主机列表及正确的帐号密码输入参数,利用 nohup 方式后台运行该脚本,在完成后监控该脚本的输出日志就可以完成上千台服务器的重复运维工作,并大大减轻了系统管理及运维人员的工作量,降低了重复操作中出 错的风险。
本文介绍了利用 shell 管道,Java SSHD 开源包,Expect 脚本三种方式实现自动登录并执行系统运维操作的案例。三种方式分别适用于不同的场景,如 shell 管道方式适用于 Telnet/FTP 协议登录的普通账户,SSHD 开源包适用于 ssh1/ssh2 安全登录协议下的登录运维,Expect 脚本适用于 SSHD 协议且需要 sudo 切换到 root 帐号权限的运维操作。
自动化脚本运维的具体实现
利用 shell 管道进行自动化运维
在企业 Unix 服务器上如果开放了 telnet 或者 FTP 协议,通常可以利用 shell 的 EOF 和 << 管道功能将后续的输入作为子命令或子 Shell 的输入,直到遇到 EOF 为止,再返回到主调 Shell,当 s h e l l 看到 < < 的时候,它就会知道下一个词是一个分界符。在该分界符以后的内容都被当作输入,直到 shell 又看到该分界符 ( 位于单独的一行 )。这个分界符可以是你所定义的任何字符串
例如:
<
(你需要执行的操作内容)
EOF
利用该功能,可以将需要 ftp 或者 telnet 登录的运维操作做成自动化脚本,将本来需要交互式输入的帐号和密码及登录后需要的操作指令包在 EOF 和 << 管道符中,以实现自动化 ftp 或者 telnet 到多台服务器并执行。
考虑如下场景:一批客户的 Unix 服务器主机要打 patch,需要将 patch 包用 ftp 上载到服务器指定目录,服务器数量巨大(超过 1000+),单个手工的上载操作是不现实的,因此我们使用 shell EOF 和管道功能编写自动化 ftp 脚本
autoftp 脚本示例如下:
清单 1. autoftp.sh 脚本示例
#!/bin/bash
# 指定 ftp 服务器的 i
serverip=192.168.1.159
# 指定 ftp 服务器的 ftp 用户
ftpuser=ftptest
# 指定 ftp 服务器的 ftp 用户密码
ftppwd=123456
# 指定 client 主机本地下载文件存放的目录
localdir=/home/xiutuo/ftp
# 指定 server 主机的 ftp 目录
remotedir=/opt/IBM/DB2/
# 登录 server 主机的
ftp -v -n $serverip << EOF > /tmp/autoftp.log.2010.XX.XX 2>&1
set head off
set echo off
set wrap off
# 指定 ftp 用户和密码
$ftpuser
$ftppwd
# 指定 server 主机的 ftp 目录和本地目录
lcd $localdir
cd $remotedir
bin
# 上传 patch 包文件至 server 主机的指定目录
put patchXXX.tar.gz
EOF
如上可以看到 FTP 登录和上传不再需要手工与每台 server 交互。读者可以修改该脚本,让服务器主机 IP 或主机名通过读配置文件循环获得,从而实现对多台服务器主机的操作。也可以修改 ftp 用户 / 密码部分代码,改成读取输入参数,以增强安全性。
Java SSHD 开源包自动化运维
上述的 Ftp,telnet 管道方式的运维是简单可行的,但是现在业界大型的企业处于安全性的考虑,逐步淘汰此类协议的登陆方式,而改用基于公钥体系的 SSHD 登陆协议。关于 SSHD 协议具体内容已超出本文涉及的范围,请各位感兴趣的读者参考 open-ssh 官方网站。
在 SSHD 下的登陆是不允许 shell 管道方式的(如果允许的话意味着 ssh 跟 telnet,ftp 一样丧失了安全性),在此种情况下如果系统管理员要进行自动化运维操作,可以采用 Java 开源的 SSHD 包来进行。
Java ganymed 开源包是成熟的 SSHD 客户端,采用封装 socket 编程方式进行底层的 ssh 通信协议,用户调用其 API 与自己使用 SSHD 命令行登陆服务器的步骤和方法都一致,很容易理解和掌握。开源包的很多 Demo 实例,使即使对 Java 编程不熟悉的系统管理人员,也可以通过简单的修改 demo 代码来实现自身需求的自动化运维操作。
考虑如下案例:一个企业的所有服务器需要将 /etc/services 文件备份至 /usr/local/etc/ 特定逻辑卷目录,企业服务器都采用 SSH2 安全协议,不允许 telnet,ftp 登录。
用 ganymed 的 SSH2 开源包编写自动化登陆脚本,以管理员账号和密码登陆企业 Unix 服务器,执行 cp 操作进行备份。
ganymed 的 Java 代码示例如下:
清单 2. AutoCp.java 类代码示例
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
public class AutoCopy
{
public static void main(String[] args)
{
String hostname = "9.212.XXX.XXX;
String username = "SolarisAdmin";
String password = "********";
try
{
/* 创建 SSH2 连接实例 */
Connection conn = new Connection(hostname);
/* 打开主机 ssh 端口连接(默认 22) */
conn.connect();
/* 认证方式为 user/passwd */
boolean isAuthenticated = conn.authenticateWithPassword(username, password);
if (isAuthenticated == false)
throw new IOException("Authentication failed.");
/* 已连接到远程主机,打开 session 会话 */
Session sess = conn.openSession();
/* 执行备份操作 */
sess.execCommand(\
"cp /etc/services /usr/local/etc/services; \
ls -lt /usr/local/etc/|grep -i services >&2");
/* 远程主机输入输出流 */
InputStream stdout = new StreamGobbler(sess.getStdout());
InputStream stderr = new StreamGobbler(sess.getStderr());
BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(stdout));
BufferedReader stderrReader = new BufferedReader(new InputStreamReader(stderr));
System.out.println("process result on remote server:");
while (true)
{
String line = stdoutReader.readLine();
if (line == null)
break;
System.out.println(line);
}
System.out.println("Process error from remote server:");
while (true)
{
String line = stderrReader.readLine();
if (line == null)
break;
System.out.println(line);
}
/* 关闭会话 */
sess.close();
/* 关闭连接 */
conn.close();
}
catch (IOException e)
{
e.printStackTrace(System.err);
System.exit(2);
}
}
}
以上可以看到,ganymed 的 SSH2 开源包使用简单,建立 connection 并打开会话 session 后,都是普通的对 session 的 IO 操作,读操作则可以获取服务器端的输出,而写操作则对应对服务器端的敲入命令,一目了然,简便实用。
熟悉 Java 编程的系统管理员可以很快上手,即使是没有 Java 基础的管理员也可简单的修改示例中的 sess.execCommand("cp /etc/services /usr/local/etc/services; ls -lt /usr/local/etc/|grep -i services >&2"); 行操作代码来实现自己的业务需求。
具体的 ganymed API 请参考 ganymed project 官方网站。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者