Search code examples
pythonmultiprocesspyftpdlib

Run multiple FTP server instances on same local machine using multiprocessing and pyftpdlib python


I am trying to run multiple instances of FTP servers on same localhost using the following code:

# "create_multiple_ftp_servers.py"

from multiprocessing import Pool

import sys
sys.path.insert(1, r'C:\Users\Desktop\PythonCodes')

import create_ftp_server

ftp_server_dict = {'ftp1': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1024],
                   'ftp2': ['127.0.0.1', 'test', 'test@123', r'C:\Users\Desktop\ftpdir', 1025]}

for k, v in ftp_server_dict.items():
    with Pool(5) as p:
        server_instance = p.map(create_ftp_server.ftp, [v,])
        p.close()

Then following "create_ftp_server.py" file is used to create and run an instance of FTP server:

import os

from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer


def ftp(data):
    # Instantiate a dummy authorizer for managing 'virtual' users
    authorizer = DummyAuthorizer()

    # Define a new user having full r/w permissions and a read-only
    # anonymous user
    authorizer.add_user(data[1], data[2], data[3], perm='elradfmwMT')
    authorizer.add_anonymous(os.getcwd())

    # Instantiate FTP handler class
    handler = FTPHandler
    handler.authorizer = authorizer

    # Define a customized banner (string returned when client connects)
    handler.banner = "pyftpdlib based ftpd ready."

    # Specify a masquerade address and the range of ports to use for
    # passive connections.  Decomment in case you're behind a NAT.
    # handler.masquerade_address = '151.25.42.11'
    handler.passive_ports = range(60000, 65535)

    # Instantiate FTP server class and listen on 0.0.0.0:2121
    address = (data[0], data[4])
    server = FTPServer(address, handler)

    # set a limit for connections
    server.max_cons = 256
    server.max_cons_per_ip = 5

    # start ftp server
    server.serve_forever()

After running the above codes I expect that there should be 2 instances of FTP servers to run on the localhost or '127.0.0.1" on port number 1024 & 1025 respectively.

But after running the above code only one instance of FTP server is running on the localhost. Can somebody please let me know how to resolve this issue.


Solution

  • The serve_forever() call is what is causing you issues. This call never returns and is running an infinite loop.

    The only way I see you could handle this is to run your FTP servers in background threads, one thread per server or using a concurrency library like GEvent (which would ultimately do the same thing as background threads, albeit a bit lighter).