开发者

Python: print doesn't work, script hangs endlessly

Using Python 2.6, I wrote a script in Windows XP.

The script does the following:

Input: Domain name (ie: amazon.com)

The script queries DNS via the dnspython module and returns any A record IP Addresses. The output is in a special format needed for a specific application which utilizes this data.

This works fine in Windows, but when I've placed this on my Linux server, I'm getting some unusual and inconsistent results.

When run for the first time, it completes as expected. If I run it again immediately, the script will just hang and do nothing, no output, and the script won't end either. If I use CTRL-C to exit the process, it prints! (almost as it had been buffered, but no written to the terminal)

I've tried various techniques开发者_运维知识库 to fix this issue, like forcing sys.stdout.flush() after print (though, print should automatically flush anyways) and have had no luck.

If I wait some time (a few minutes), and run the script again, it will work again (once) and then subsequent attempts will continue to fail. I'm not sure what is going on... has anyone else experienced anything like this?

Python 2.6 on both Windows and Linux (Ubuntu).

Here is my script:

from dns.resolver import Resolver
from dns.exception import DNSException
from cStringIO import StringIO
import sys

def maltego_transform(entities, messages = ''):    
    print '''<MaltegoMessage>
<MaltegoTransformResponseMessage>
<Entities>
{0}
</Entities>
<UIMessages>
{1}
</UIMessages>
</MaltegoTransformResponseMessage>
</MaltegoMessage>'''.format(entities, messages)

def domain_to_ip(domain):
    resolver = Resolver()
    results = []
    for type in ['A', 'AAAA']:
        try:
            query = resolver.query(domain, type)
        except DNSException:
            query = []
        results += query

    entities = StringIO()
    for answer in results:
        entities.write('''<Entity Type="IPAddress"><Value>{0}</Value></Entity>'''.format(answer))
    maltego_transform(entities.getvalue())

def domain_to_mxdomain(domain):
    resolver = Resolver()
    try:
        query = resolver.query(domain, 'MX')
    except DNSException:
        query = []

    entities = StringIO()
    for answer in query:
        entities.write('''<Entity Type="Domain"><Value>{0}</Value>
<AdditionalFields><Field Name="DomainType" DisplayName="Domain Type">Mail Exchange</Field></AdditionalFields>
</Entity>'''.format(answer.exchange))
    maltego_transform(entities.getvalue())

def main():
    options = {'domain_to_ip' : domain_to_ip,
               'domain_to_mxdomain' : domain_to_mxdomain}
    if len(sys.argv) > 2:
        func = options.get(sys.argv[1], None)
        if func:
            func(sys.argv[2])

if __name__ == '__main__':
    main()

Use: python myscript.py domain_to_ip amazon.com

2 parameters for this script, the first maps to the function to run, the second specifies the domain.


Apparently dnspython wants 16 bytes of high-quality random numbers at startup. Getting them (from /dev/random) can block.

If you hit Ctrl+C, it actually catches the KeyboardInterupt exception and falls back on less-secure random numbers (taken from the current system time). Then your program finishes running.

The code in question is here: http://www.dnspython.com/docs/1.7.1/html/dns.entropy-pysrc.html

I guess I would consider this a bug in dnspython. It should find a way not to block there, and fall back on /dev/urandom. In any case it shouldn't silence a KeyboardInterrupt.


Have you tried doing

entities = StringIO()
for answer in results:
    entities.write('''<Entity Type="IPAddress"><Value>{0}</Value></Entity>'''.format(answer))
entities.flush()
maltego_transform(entities.getvalue())
entities.close()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜