I have a function which executes a shell command to deploy a server on the machine. This function takes the following parameters:
Now, once the command
is executed from inside the directory path
, the function time.sleep
s until wait time
and then checks for processes which are listening on the server port
.
While this method is effective, it does waste a lot of time for command
s where the time taken for it to start is considerably less than wait time
.
I was planning to creating a waiter, which will wait for a maximum of wait time
, but keep polling the server port
in regular small intervals. If there are processes found before wait time
is over, I want the function to safely return from that point only, and not keep the process blocked until the end.
I have no idea how to proceed with the same. The closest I can think of is creating a poll object (using select.poll
), but an example (or a package, if available) would help me a lot.
My current function does something akin to:
run_local_command(
['nohup', start_command, ">>", logfile, '2>>', errfile, '&'],
explanation="Starting server",
target_dir=target_dir
)
time.sleep(wait_time)
# Get the PIDs listening to the specific port
processes = [
p for p in psutil.net_connections(kind='inet')
if p.laddr[1] == port and p.status == 'LISTEN'
]
logger.debug("Logged following processes for the service port: %s", processes)
pids = [x.pid for x in processes if x.pid is not None]
What I generally use to wait until a condition is satisfied or until a timeout is a small function like this :
def wait_condition(condition, timeout=5.0, granularity=0.3, time_factory=time):
end_time = time.time() + timeout # compute the maximal end time
status = condition() # first condition check, no need to wait if condition already True
while not status and time.time() < end_time: # loop until the condition is false and timeout not exhausted
time.sleep(granularity) # release CPU cycles
status = condition() # check condition
return status # at the end, be nice and return the final condition status : True = condition satisfied, False = timeout occurred.
So, by giving to this method a condition
method that will return True when called and condition is satisfied (and False when not).
This will loop (and make some pause to avoid too much CPU occupation) and go out at the end of the timeout or if condition is True.
In your case, the condition method will probably do something like this :
def port_opened():
return [p for p in psutil.net_connections(kind='inet') if p.laddr[1] == port and p.status == 'LISTEN'] # assuming that an empty list is False in python