2009-07-20 8 views
1

以前、私はこの質問をした:Pythonでpingまたはtracerouteを実行し、出力が生成されたときにその出力にアクセスするにはどうすればよいですか?

How can I perform a ping or traceroute using native python?

しかし、Pythonはrootとして実行されていないので、それはネイティブのpythonでのping/tracerouteを実行するために必要な生のICMPソケットをオープンする能力を持っているdoens't。

これは、システムのping/tracerouteシェルコマンドの使用に戻ります。この質問はうまく動作するようには思えsubprocessモジュールを使用したカップルの例があります。

Ping a site in Python?

私はまだかかわらず、1以上の要件を持っている:それは(生成されたとして、私は出力にアクセスできるようにする必要があります例えばため。

上記の例はすべてシェルコマンドを実行し、コマンドが完了すると完全な出力にアクセスできるようにします。生成されたコマンド出力にアクセスする方法はありますか?

編集:アレックスマルテッリの答えに基づいて、ここで働いていたものです:

import pexpect 

child = pexpect.spawn('ping -c 5 www.google.com') 

while 1: 
     line = child.readline() 
     if not line: break 
     print line, 

答えて

5

pexpectは、私は、そのようなあなたのようにどのような要件のために、「デフォルト」、のために達するだろうと何である - 他がありますpexpectはほぼ常に最も豊かで、最も安定した、最も成熟したモジュールです。私がWindowsの下で正しく動作しなければならない場合(私はpingとtracerouteがどこかの問題を抱えているかもしれません)、私たちにはそうだとわかります -

+0

これはLinux上でのみ動作するので、pexpectを使用することは問題ではありません。私は今それをチェックしている。 –

+0

Linux(そして私が試した他のすべてのunixoidシステム、MacOSX ;-)では、pexpectが魅力を発揮します。問題があるかどうかは私たちに知らせてください。解決されました - ) –

+0

うわー、pexpectは完璧にそして簡単に(そしてより多くのものを束にすることができます)働いていました。 –

3

subprocessモジュールのドキュメントを読む必要があります。外部プロセスを実行し、その出力にリアルタイムでアクセスする方法について説明しています。

基本的に、あなたが実際に

from subprocess import Popen, PIPE 
p = Popen(['tracert', host], stdout=PIPE) 
while True: 
    line = p.stdout.readline() 
    if not line: 
     break 
    # Do stuff with line 

を行い、SOあなたがにリンクされている問題の答えはあなたが必要なものに非常に近いです。 Corey Goldberg's answerはパイプと readlineを使用しますが、それは -n 1でpingを実行するので、違いが出るほど長くはありません。

+0

パイプはデフォルトでバッファリングされています(ラインバッファではありません)。あなたのtracerouteがsetvbuf()または同様のことをしない限り、出力が生成されたときに出力を得ることはありません。私の答えを見てください。 – Thomas

+0

問題のシステムでは、tracerouteはラインバッファリングされており、pingは動作しません。 –

1

サブプロセスのttyペアを作成し、その内部で実行することができます。 C標準(C99 7.19.3)によれば、stdoutはバッファされた行だけです(完全にバッファリングされていないのは、あなたが望んでいないと言われています)。 (または明らかにsetvbuf()と呼ばれる子)。

os.openpty()を確認してください。

未テストコード:

master, slave = os.openpty() 
pid = os.fork() 
if pid == 0: 
    os.close(master) 
    os.dup2(slave, 0) 
    os.dup2(slave, 1) 
    os.dup2(slave, 2) 
    os.execv("/usr/sbin/traceroute", ("traceroute","4.2.2.1")) 
    # FIXME: log error somewhere 
    os.exit(1) 
os.close(slave) 
while True: 
    d = os.read(master) 
    if len(d) == 0: 
     break 
    print d 
os.waitpid(pid, 0) 

注子プロセスを有する(単にフォーク後())はsetvbuf(呼び出し)ますない作業、はsetvbufので()はlibcの関数としないシステムコールであること。現在のプロセス出力の状態を変更するだけで、新しいバイナリがロードされたときにexec呼び出しで上書きされます。ここ

+0

これは本当にクールなので+1ですが、PopenはUbuntuとXPでうまく動作しました。バッファリングに問題はありません。 – itsadok

+0

あなたのtracerouteプログラムはsetvbuf()またはfflush()を使用しています。しかし、他のものを実行しているときは、これらを使用しないでください。 – Thomas

1

は別のアプローチである:

# const_output.py 
import sys 
from subprocess import Popen 

if len(sys.argv) < 2: 
    print 'Usage: const_output.py "command to watch"' 
    sys.exit(1) 

cmd_line = sys.argv[1:] 

p = Popen(cmd_line) 
p.communicate()[0] 

使用例:

のtraceroute:

> python const_output.py traceroute 10.0.0.38 
traceroute to 10.0.0.38 (10.0.0.38), 30 hops max, 60 byte packets 
1 10.0.0.38 (10.0.0.38) 0.106 ms 0.023 ms 0.021 ms 

ピング:

> python const_output.py ping 10.0.0.38 
PING 10.0.0.38 (10.0.0.38) 56(84) bytes of data. 
64 bytes from 10.0.0.38: icmp_seq=1 ttl=64 time=0.046 ms 
64 bytes from 10.0.0.38: icmp_seq=2 ttl=64 time=0.075 ms 
64 bytes from 10.0.0.38: icmp_seq=3 ttl=64 time=0.076 ms 
64 bytes from 10.0.0.38: icmp_seq=4 ttl=64 time=0.073 ms 

トップ:

> python const_output.py top 
    # you will see the top output 
関連する問題