非常感谢如何增强我的python脚本以解决问题。我有一个文件,其中列出了数千个移动工作站和IP地址,每五分钟更新一次。我使用Paramiko进入每个工作站以验证服务是否正在运行(在此示例中为crond)。我遇到的问题是当我启动我的python脚本时,它将大文件读入内存,当它获得1/3的时候,IP地址已经改变,并且大部分IP地址不再有效。有没有办法让python打开然后在工作站每次搜索之前关闭文件?这将确保IP是当前的IP。我在下面写的python脚本有效,但我再次遇到旧IP信息的问题。谢谢。
The contents of WKSIPS.txt are in the format:
WORK 1234 Cell IP: 10.10.10.10
WORK 4567 Cell IP: 10.10.10.11
#!/usr/bin/python
import paramiko, os, string, threading
import getpass
import socket
import sys
FileName=open('WKSIPS.txt', 'r')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for line in FileName.readlines():
WKSid = line.split()
try:
if WKSid[0] == 'WORK' :
WKSip = WKSid[4]
ssh.connect(WKSip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
Out = stdout.readlines()
print ("WORK " + WKSid[1], Out)
ssh.close()
FileName.close
except paramiko.SSHException, e:
print ('WORK' + WKSid, WKSip, "Invalid Password")
答案 0 :(得分:2)
我建议使用multiprocessing pool创建可以为您处理文件每一行的工作人员,这样可以更快地完成文件。
我使用此代码段的目标是完全避免文件重新加载问题,方法是让您的脚本足够快,以便在5分钟文件刷新之前完成。
#!/usr/bin/python
import paramiko, os, string, threading
import multiprocessing
import getpass
import socket
import sys
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
def worker(line)
WKSid = line.split()
try:
if WKSid[0] == 'WORK' :
WKSip = WKSid[4]
ssh.connect(WKSip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
Out = stdout.readlines()
print ("WORK " + WKSid[1], Out)
ssh.close()
except paramiko.SSHException, e:
print ('WORK' + WKSid, WKSip, "Invalid Password")
# set up processing pool
pool = multiprocessing.Pool()
with open('WKSIPS.txt') as infile:
pool.map(worker, infile)
pool.close()
pool.join()
注意:
pool.map()
将为每个worker提供文件迭代器的一行,并且它们将独立处理它。它与原始代码的功能相同,但工作分为多个进程,这些进程等于计算机上的内核数。paramikio.SSHClient()
对象可能会产生一些隐藏的副作用。如果您看到来自ssh
对象的奇怪错误,请尝试将其实例化移动到辅助函数中。readlines()
更改为使用Python文件迭代器。将整个文件读入内存是一项耗时的操作,应该避免使用。为了清楚起见,此代码段不会处理文件运行时发生的更改。我做了两个很大的假设:
答案 1 :(得分:0)
这非常昂贵,但我认为这是看看这种方法是否适合您的第一步:
import re
import paramiko
def verify_service(ssh, work, ip):
print("Verifying workstation %d at %s" % (work, ip))
ssh.connect(ip, username='user', password='password', timeout='3')
stdin, stdout, stderr = ssh.exec_command('service crond status')
print ("WORK " + work, stdout.readlines())
ssh.close()
IP_LIST = 'WKSIPS.txt'
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# Get number of lines in WKSIPS -- if you know this, you can just define NUM_LINES
NUM_LINES = None
with open(IP_LIST) as f:
NUM_LINES = len(f.readlines())
for i in xrange(NUM_LINES):
with open(IP_LIST) as f:
#line = f.readlines()[i]
line = next(islice(f, i, None))
mat = re.match(r'WORK\s*(\d+)\s*Cell IP: (.*)', line)
if mat:
verify_service(ssh, int(mat.group(1)), mat.group(2))
代码首先打开您的文件并计算行数,并将其存储在NUM_LINES
中。如果您知道这个号码,就可以摆脱NUM_LINES = None
行及其下面的两行,只需将其替换为NUM_LINES = <number of lines>
。
然后,对于0和i
之间的每个行号NUM_LINES
(不包括),它会打开文件, 将整个文件读入列表,拉动对应于行号的行重复行直到它到达i
i
行,解析它并将其传递给verify_service()
函数 - 你和#39;我必须使用您的paramiko代码进行更新。
如果这样做,你应该考虑更好的方法来做到这一点。也许您不必每次迭代都重新读取文件,也许每个 n 迭代都可以正常工作。也许您在重新读取之前对文件进行散列并检查散列是否已更改。也许您检查文件的修改时间等。也许您使用子进程并尝试同时处理多个连接而不是连续处理。
在任何情况下,如果这样做,你应该考虑优化它 - 因为它目前的编写非常昂贵,但它会做你所说的你想要的。