2017-02-17 4 views
2

を呼び出して、私は次のスクリプトがあります。os.systemは(「ピング」)非常に遅い

#!/usr/bin/env python3 
import os 

i = 1 
while i != 255: 
    Test = os.system("ping -c 1 10.0.0." + str(i) + " > /dev/null") 
    if Test == 0: 
     print("Host: 10.0.0." + str(i) + " is up!"); 
     i = i + 1 
    else: 
     i = i + 1 

をそれは私が退屈していたとすることに決めていること、nmapのようなPythonスクリプトです。

とにかく、私はそれを実行すると、それは非常に遅いですが、Ctrl + Cキーを押していると、もっと速くなります。

私はこのスクリプトをもっと速くする方法がありますか?

+2

'multiprocessing'は開始する場所です。あなたの 'i'は数値であることが保証されているのでここでは安全ですが、一般的に*文字列連結を使用してシェルコマンドを形成することは非常に安全ではありません。 'stdout = open( '/ dev/null'、 'wb')'のように '>/dev/null'リダイレクションを非シェル依存のものに置き換えた' subprocess.Popen'に配列を渡します)はるかに良い形です。 –

+0

もちろん、それは '極度に遅い'でしょう - 潜在的なホストにpingをしてから応答を待つのに時間がかかり、それを255回行います。 'nmap -sP --max-retries = 1 --host-timeout = 500ms 10.0.0。{}>/dev/null"あなたのシステムに 'nmap 'があるなら、 .format(i)) 'を使って500ms後にはあきらめますが、他にも示唆されているように、すべてを並行して実行したい場合はマルチプロセッシングを使わなければなりません。 – zwer

+1

@jersten、... GILがここで問題になることは確かではありません。作業はサブプロセスを待っているからです。待機はロックの外になければなりません。 SIGCHLDが来たときに結果を処理するだけでは、厳密にロックを保持する必要があります。 –

答えて

3

デフォルトでは、pingはパケットが到着するまで10秒間待機します。多くのアドレスは使用されていないか、またはこれらのアドレスを持つコンピュータはICMPエコー(ping)パケットに応答しませんので、最大2550秒間待機します。

あなたははCtrl +Cを入力すると、あなたは待機を中止SIGTERM信号を送ります。 ICMPエコー応答を受信する前にpingを中止すると、誤った結果が得られます。ローカルネットワークはかなり速いので、これに遭遇する可能性は低いです。

これをスピードアップするには、次の2つの方法であなたのアプローチを変更することができます応答が来ていないとき

  1. が早くあきらめます。 -Wパラメータを渡します。たとえば、ping -c 1 -W 1 ...を実行すると、pingは1秒間待機するため、プログラム全体では約250秒かかることになります。
  2. pingを並行して実行します。手動で行うことができます。通常は、スレッド/プロセスのPool(またはpingごとに1つのスレッド/プロセス)を使用します。ご使用のオペレーティングシステムでは、1秒あたりのping数が制限される場合があります。たとえば、タイムアウトを10秒にして、すべてのpingを同時に実行すると、プログラムはわずか10秒しかかかりません。あなたの周りいじるていない場合は、プールを使用して

適切なコードが

import multiprocessing 
import subprocess 


TIMEOUT = 5 # in seconds 
CONCURRENCY = 100 # how many pings in parallel? 


def ping(ip): 
    """ Returns true iff the host is reachable. """ 
    # print('ping %s' % ip) # uncomment to see progress 
    ret = subprocess.call(
     ['ping', '-W', str(TIMEOUT), '-c', '1', ip], 
     stdout=subprocess.DEVNULL) 
    if ret == 0: 
     print('%s is reachable' % ip) 

ips = ('10.0.0.%d' % i for i in range(1, 255)) 

with multiprocessing.Pool(CONCURRENCY) as p: 
    p.map(ping, ips) 

ようになり、あなたはまた、並行して実行んプログラムの代わりにpingを使用することをお勧めします。すべてのポートスキャナ(nmapなど)は正常に動作するはずです。

+0

私はPythonにはかなり新しいです、どうすればPoolを使いますか? –

+0

@Python [ドキュメントへのリンク](https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool)に従ってください。プールの使用方法について説明しています。ドキュメントを読んだ後にご質問がありましたら、[stackoverflowでお気軽にお問い合わせください](http://stackoverflow.com/questions/ask)。 – phihag

+0

私はドキュメンテーションへのリンクのコードを持っていますが、どこにコードを記述しますか?私は非常に混乱していますXD –

0

scapyを使用してください。 pingコマンドをPythonスレッドで生成する必要はありません。

+0

実際には、pingできますが、scapyを実行するにはスーパーユーザー権限が必要です。 – phihag

+0

Linuxでは、** CAP_NET_RAW **機能のみが必要です。 –