2016-04-08 24 views
1

Haritalamayı, ping_all işlevini ana makine listesine eşlemek için kullanmaya çalışıyorum. Kullanmakta olduğum sorun, ping_all işlevinin içinde, başarısız olan tüm ana bilgisayarları bir listeye eklemeye çalışıyorum. Normalde ping_all işlevini çağırır, boş listede bir argüman olarak geçip değiştirilmiş listeyi döndürürüm, ancak haritayı burada kullandığımdan, bunu nasıl başaracağımı bilmiyorum. Harita işlevini kullanarak bir listeye nasıl eklenir?

import os 
import argparse 
from subprocess import check_output 
from multiprocessing import Pool 


parser = argparse.ArgumentParser(description='test') 

args = parser.parse_args() 

dead_hosts = [] 


def gather_hosts(): 
    """ Returns all environments from opsnode and puts them in a dict """ 
    host_list = [] 
    url = 'http://test.com/hosts.json' 
    opsnode = requests.get(url) 
    content = json.loads(opsnode.text) 
    for server in content["host"]: 
     if server.startswith("ip-10-12") and server.endswith(".va.test.com"): 
      host_list.append(str(server)) 
    return host_list 


def try_ping(hostnames): 
    try: 
     hoststatus = check_output(["ping", "-c 1", hostnames]) 
     print "Success:", hostnames 
    except: 
     print "\033[1;31mPing Failed:\033[1;m", hostnames 
     global dead_hosts 
     dead_hosts.append(hostnames) 

def show_dead_hosts(dead_hosts): 
    print '\033[1;31m******************* Following Hosts are Unreachable ******************* \n\n\033[1;m' 
    for i in dead_hosts: 
     print '\033[1;31m{0} \033[1;m'.format(i) 

if __name__ == '__main__': 
    hostnames = gather_hosts() 
    pool = Pool(processes=30)    # process per core 
    pool.map(try_ping, hostnames, dead_hosts) 
    show_dead_hosts(dead_hosts) 

Haritaya ikinci argüman olarak dead_hosts geçen çalıştı, ancak, o görünmüyor bu komut dosyası çalıştırdıktan sonra, dead_hosts barındıran listesine ekleme olduğu boş bir liste kalır.

Neyi yanlış yapıyorum?

cevap

1

sizin koduyla birkaç sorunu vardır:

  1. Pool.map üçüncü argüman böylece dead_hosts (bir liste) geçen chunksize olduğunu kesinlikle yanlıştır.
  2. Havuzdaki görevler ayrı işlemlerde çalıştığı için çok işlemcili Pool kullanırken globals'a erişemezsiniz. Daha fazla bilgi için bkz. Python multiprocessing global variable updates not returned to parent.
  3. Bir önceki noktaya ilişkin olarak, Pool.map bir sonuç listesi döndürmelidir (çünkü genel yan etkiler çoğunlukla görünmez olacaktır). Şu an sadece diyorsun ve sonucu atıyorsun. İşte

Güncellenmiş ve test edilmiş-ben istediğini yapar düşünüyorum olduğunuz bir versiyonu ...

  • Kişisel biçim kodları doğru benim terminalde temizleyerek değildi, bu yüzden her şey kırmızı kalın + dönüm idi: yaptığım

    import os 
    import argparse 
    from subprocess import check_output 
    from multiprocessing import Pool 
    
    
    parser = argparse.ArgumentParser(description='test') 
    
    args = parser.parse_args() 
    
    def gather_hosts(): 
        """ Returns all environments from opsnode and puts them in a dict """ 
        host_list = [] 
        url = 'http://test.com/hosts.json' 
        opsnode = requests.get(url) 
        content = json.loads(opsnode.text) 
        for server in content["host"]: 
         if server.startswith("ip-10-12") and server.endswith(".va.test.com"): 
          host_list.append(str(server)) 
        return host_list 
    
    
    def try_ping(host): 
        try: 
         hoststatus = check_output(["ping", "-c 1", "-t 1", host]) 
         print "Success:", host 
         return None 
        except: 
         print "\033[1;31mPing Failed:\033[0m", host 
         return host 
    
    def show_dead_hosts(dead_hosts): 
        print '\033[1;31m******************* Following Hosts are Unreachable ******************* \n\n\033[0m' 
        for x in dead_hosts: 
         print '\033[1;31m{0} \033[0m'.format(x) 
    
    def main(): 
        hostnames = gather_hosts() 
        pool = Pool(processes=30)    # process per core 
        identity = lambda x: x 
        dead_hosts = filter(identity, pool.map(try_ping, hostnames)) 
        show_dead_hosts(dead_hosts) 
    
    if __name__ == '__main__': 
        main() 
    

    ana değişiklik olduğunu try_ping ya başarısına None döner, aksi takdirde host 'adı. Ping'ler, görev havuzunuz tarafından paralel olarak yapılır ve sonuçlar yeni bir listeye toplanır. Listede filter'u çalıştırarak tüm None değerlerinden (None Python'da "falsey") kurtularak, yalnızca ping testi başarısız olan ana bilgisayar adlarını bırakıyorum.

    try_ping adresindeki print ifadelerinden kurtulmak isteyeceksiniz. Sadece hata ayıklama için bunları yaptınız varsayarak varsayalım.

    Daha fazla eşzamansa ihtiyacınız varsa imap ve ifilter kullanmayı da düşünebilirsiniz.

  • +0

    Kimlik = lambda çizgisinin amacı nedir? – david

    +0

    Sadece lambda kimliğini doğrudan filtre çağrısına koymaktan daha okunaklı olduğunu düşündüm. İsterseniz tabii ki satır içi yapabilirsiniz. – DaoWen

    +0

    ama demek istediğim, bu satırın neden gerekli olduğunu anlamıyorum – david

    0

    try_ping işleviniz aslında hiçbir şey döndürmez. Eğer ben olsaydım, fonksiyonun dışında dead_hosts'un olmasıyla uğraşmazdım ama try_ping fonksiyonunun içinde. Ve sonra bu listeyi return yapmalısınız.

    Kullandığınız modülleri bilmiyorum, bu yüzden pool.map listelerini alabilir mi bilmiyorum.

    İlgili konular