当我们有很多台linux服务器的时候,而每台服务器都需要做同一个操作,比如很多节点的集群环境下,要更改一个配置文件,哪怕只是一行,在传统情况下,也需要每台去单独操作。
最近也是有这样的需求,需要操作的机器特别多,所以就写了一个小的程序
看到这里,可能有同学说了,我做了 ssh 免密码登录,可以用shell写个循环也能实现啊。可是当你做ssh的时候,不也是一台一台的操作吗?
其实用 shell 也可以做,并且shell 没有依赖,只不是你要提前把 ssh 免密码登录做好。
而使用 shell 若不做免密码,循环的时候,要输入每台的密码,我曾经在网上搜索过,好像没有什么方法可以把这个交互式做成自动化。
言归正传,本次使用 python ,并且使用 python 的 paramiko 模块,来操作。
paramiko 模块需要 gcc , openssl , pycrypto 等依赖,下面就来安装它。
## debian & ubuntu 平台
apt-get update
apt-get install gcc g++ openssl libssl-dev python-dev python-pip libffi-dev
## centos redhat 等平台,需要先安装 epel 第三方仓库
yum install epel-release
##之后再安装
yum install gcc gcc-c++ openssl openssl-devel python-devel python-pip libffi-devel
并且 paramiko 至少需要 python 2.7 以上的版本才支持。如果你 python 低于这个版本,请自行升级
依赖安装完以后,把 pip 升级到最新版本
pip install --upgrade pip
安装 paramiko
pip install pycrypto
pip install paramiko
请注意,pip 需要root权限,过程若有报错,请看详细情况,一般是上面的依赖没有安装好
目前已经将代码写成命令行操作了,下面直接上代码,然后再说用法
#!/usr/bin/python
# -- coding: utf-8 --
import paramiko
from optparse import OptionParser
from sys import argv
def ssh2(ip, port, username, password, cmd):
for hosts in ip:
try:
paramiko.util.log_to_file('paramiko__.log')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hosts, port, username, password, timeout=7)
stdin, stdout, stderr = ssh.exec_command(cmd)
cmd_result = stdout.read(), stderr.read()
print '%s --> command has been submitted, results are as follows.' % (hosts)
for o in cmd_result:
print o,
ssh.close()
print "\n"
except Exception, msg:
print hosts, msg
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("--ip",
dest="ipaddr",
help="target host ip address"
)
parser.add_option("--ipfile",
dest="ipfile",
help="ip list file"
)
parser.add_option("--port",
dest="port",
help="ssh port number"
)
parser.add_option("--username",
dest="username",
help="ssh user name"
)
parser.add_option("--password",
dest="password",
help="ssh password"
)
parser.add_option("--cmd",
dest="cmd",
help="Commands to execute"
)
(options, args) = parser.parse_args()
if "--ip" in argv and "--ipfile" in argv:
print "Accept only one argument, use --ip or --ipfile"
exit(1)
if options.ipaddr == None:
ip_list = open(options.ipfile, "r")
ip = ip_list.read().split("\n")[:-1]
ip_list.close()
if options.ipfile == None:
ip_list = options.ipaddr
ip = ip_list.split(",")
cmd = options.cmd
port = int(options.port)
username = options.username
password = options.password
ssh2(ip, port, username, password, cmd)
将代码保存到一个文件,之后执行 python 文件名 -h ,即可以查看帮助,run_cmd.py 是我保存的名字,如下:
root@ainy:~# python run_cmd.py -h
Usage: run_cmd [options]
Options:
-h, --help show this help message and exit
--ip=IPADDR target host ip address
--ipfile=IPFILE ip list file
--port=PORT ssh port number
--username=USERNAME ssh user name
--password=PASSWORD ssh password
--cmd=CMD Commands to execute
root@ainy:~#
-h 查看帮助信息
–help 查看帮助信息
–ip 指定目标主机的IP地址,多个IP地址时,请使用英文状态的逗号分隔
–ipfile ip地址列表文件,可以把IP地址写一个文件里面,一行一个
–port ssh 端口号
–username ssh账号
–password ssh密码
–cmd 需要执行的命令,命令中包含空格,请使用双引号引起来
PS: –ip 参数 和 –ipfile 参数,您必须指定其中一个,程序也只接受一个
示例:
# 单个主机
python run_cmd.py --ip 192.168.1.22 --port 22 --username root --password 123456 --cmd "ls -l"
# 多个主机
python run_cmd.py --ip 192.168.7.19,192.168.7.20,192.168.10.177,192.168.73.145 --port 22 --username root --password 123456 --cmd "ls -l"
# 使用IP地址列表文件
python run_cmd.py --ipfile /root/kvmip.txt --port 22 --username root --password 123456 --cmd "ls -l"
IP 地址列表文件,请使用纯文件文件,并把换行符设置为 unix\linux 格式,否则会出错。
在windows 操作系统上,请不使用 记事本来创建 IP 列表文件,因为其换行符和 linux 不同,windows上您可以使用任何一款代表编辑器,上面可以转换换行符格式
在 linux 系统,您也可以直接使用 vim 等编辑器工具来创建IP列表文件。其换行符默认即是 unix\linux 格式