Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,for循环一个文件来搜索另一个文件_Python_Paramiko_Readlines - Fatal编程技术网

在Python中,for循环一个文件来搜索另一个文件

在Python中,for循环一个文件来搜索另一个文件,python,paramiko,readlines,Python,Paramiko,Readlines,如果能提供一些关于如何增强python脚本以解决问题的线索,我将不胜感激。我有一个文件,其中列出了数千个移动工作站和IP地址,每五分钟更新一次。我使用Paramiko将ssh连接到每个工作站,以验证服务是否正在运行(在本例中为crond)。我遇到的问题是,当我启动python脚本时,它会将大文件读入内存,当它读入内存的1/3时,IP地址已经更改,大部分IP地址不再有效。是否有一种方法可以在每次搜索之前让python打开然后关闭文件?这将确保IP为当前IP。我在下面编写的python脚本可以正常工

如果能提供一些关于如何增强python脚本以解决问题的线索,我将不胜感激。我有一个文件,其中列出了数千个移动工作站和IP地址,每五分钟更新一次。我使用Paramiko将ssh连接到每个工作站,以验证服务是否正在运行(在本例中为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")
这是非常昂贵的,但我认为这是检验这种方法是否适用于您的第一步:

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\u行中。如果您知道这个数字,您可以去掉
NUM\u line=None
行和它下面的两行,只需将其替换为
NUM\u line=

然后,对于0到
NUM_LINES
(独占)之间的每个行号
i
,它打开文件,将整个文件读入一个列表,拉出与行号
i
对应的行,在这些行上迭代,直到到达
i
第行,解析它并将其传递给
verify_服务()
函数——您必须使用paramiko代码更新该函数

如果这样做有效,你应该考虑更好的方法。也许你不必每次迭代都重新读取文件,也许每n次迭代都可以。也许您可以对文件进行哈希,并在重新读取之前检查哈希是否已更改。可能检查文件的修改时间等。可能使用子进程并尝试同时处理多个连接,而不是连续处理

在任何情况下,如果这样做有效,您应该寻求对其进行优化——因为它目前的编写成本非常高,但它可以满足您的要求。

我建议使用创建一个工人,可以为您处理文件的每一行,这将允许您更快地完成文件

我使用此代码段的目标是通过使脚本足够快,在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()
    将为每个工作人员提供一行文件迭代器,他们将独立处理它。它所做的工作与您的原始代码相同,但工作被分配到多个进程中,这些进程的数量等于您机器上的内核数量
  • 我没有paramiko模块,也无法在我当前的环境中安装它,因此我无法真正为您测试此代码。如果有任何错误,我将提前道歉
  • 我不熟悉paramiko库,因此在多个进程中同时使用相同的
    paramikio.SSHClient()
    对象可能会产生一些隐藏的副作用。如果从
    ssh
    对象中看到异常错误,请尝试将其实例化移动到worker函数中
  • 我已将
    readlines()
    更改为使用Python文件迭代器。将整个文件读入内存是一项耗时的操作,应该避免
非常清楚的是,此代码段不会处理文件运行时发生的更改。我做了两大假设:

  • 此脚本的执行可以与刷新文件的任何操作同步,以便在刷新文件后立即执行
  • 它可以在5分钟内执行-因为我没有paramiko、ssh目标访问权限或WKSIPS.txt访问权限,所以我无法计时。由于这个问题似乎符合的定义,我认为值得一试。如果不符合时间规格,则由OP进一步优化

  • 如果按照您的建议关闭并重新打开该文件,是否希望从“新”文件的开头重新开始?还是跟你说的一样?从同一行开始是否会导致任何问题(例如,行数发生变化)?您可以使用来并行执行某些工作。至少,您可以让子进程执行ssh工作,这样您就不会阻止文件读取。因为此工作站名称是静态的,并且只有IP地址更改,所以我需要它从中断的地方开始。行的顺序是否更改?行数是否更改?如果在无效IP地址上运行命令,会发生什么情况?这是一个您可以识别并选择忽略的事件吗?多处理池方法似乎是个好主意,但在当前编写代码时不会反映对文件运行中期的更改。这是事实。我假设此脚本的运行可以与文件刷新同步。我将编辑以澄清这一点。我感谢多处理建议,但由于这些工作站中的一些通过无线电连接,因此很难在五分钟内完成。目前,按照我写的方式,由于建立ssh连接的延迟,它需要4个多小时。@gineraso哦。该死的。这是一个好主意。@gineraso不管它值多少钱,我仍然建议您在理顺文件刷新处理之后实现某种并行性。对于处理SSH连接的多个进程,您仍然可以看到运行时间的显著减少。让我给你一个解决方案,看看它是否符合我的需要。非常感谢。