Search code examples
pythonfunctionmultiprocessingport-scanning

Cannot call python global variable outside of function


I'm having issues calling a variable in Python that I'm setting as "global."

I am setting the variable at the beginning of my script, and then modifying the variable inside of a function, and at end of my script I am then echoing out the variable's value, and the value that I'm setting the variable to in the function does not seem to be carrying out of the function.

Script (Simple port scanner to scan the first 1000 ports of a PC). Also, the reason that I'm setting the script up with processes is because I'm calling multiple port sections at the same time...however I did not include all of the functions, as it is a pretty long script.

#!/usr/bin/env python
import socket
import subprocess
import sys
from datetime import datetime
from multiprocessing import Process
import random
import datetime

# Clear the screen
#subprocess.call('clear', shell=True)

# Ask for input
#remoteServer    = raw_input("Enter a remote host to scan: ")
remoteServer = sys.argv[1]
remoteServerIP  = socket.gethostbyname(remoteServer)

global openports
openports = []

def ports1():
    global openports
    for port in random.sample(range(1,1000), 999):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(.01)
        result = sock.connect_ex((remoteServerIP, port))
        if result == 0:
            openports.append(format(port))
        sock.close()


if __name__ == '__main__':
    p1 = Process(target = ports1)
    p1.start()
    p1.join()
    print openports

I know that the variable is getting set, because if I echo the openports variable from inside of the function it is returning the correct data, however when I echo it after I call the function in the name==main section, it returns as an empty string.


Solution

  • This happens because you are using a separate process to query the ports. The openports variable in that process is updated, not the one in the parent process!

    There are multiple possible solutions.

    You can just call the ports1() function in the original process, since you're just waiting for it anyway.

    If you want to paralellize the scanner, you could use a multiprocessing.Pool to do the port scanning. The function called in the pool could return a port number for an open port, or None for a closed port. For example:

    from multiprocessing import Pool
    import random
    import socket
    import sys
    
    remoteServer = sys.argv[1]
    remoteServerIP  = socket.gethostbyname(remoteServer)
    
    ports = random.sample(range(1,1000), 999)
    
    def testport(num):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(.01)
        result = sock.connect_ex((remoteServerIP, port))
        sock.close()
        if result == 0:
            return num
        return None
    
    p = Pool()
    openports = p.map(testport, ports)
    openports = [prt for prt in openports if prt is not None]