All posted code is only for Python 3.
proc.stdout.read()
blocks until EOF has been reached. This happens, when the process has been closed.
proc.stdout.readline()
blocks until a new line is in the buffer.
It tested it with a shell script. I am not sure if it behaves like your daemon. It's different because the shell forks child processes.
daemon-sim.sh:
#!/bin/bash
sleep 4
echo "Running daemon..."
sleep 1
echo "Deamon is running now."
while true; do sleep 5; echo "`date`"; done
import subprocess
import re
def wait_for_daemon(path, args, ready_line_regex, shell=False):
cmd = [path] + args
proc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline() # returns bytes
if ready_line_regex.search(line):
break
return proc
running_regex = re.compile(rb'Running daemon') # Using raw binary strting for regex
proc = wait_for_daemon('./daemon-sim.sh', [], running_regex, shell=True)
# don't use shell=True in your case, it's unsafe
I think this may solve your problem. But pay attention, if your daemon process is logging to stdout,
it's added to your memory. To prevent huge memory consumption, you should have a task, which is reading proc.stdout.
In most cases logging of daemons happens to stderr. In this case you're not redirecting stderr to somewhere. You'll see them in
your shell or if the daemon has a logging function, it logs to a file.
Good shell citizens are logging errors to stderr and data is written to stdout. A daemon process should not
log errors to stdout. But sometimes they do.
The solution above starts the process and redirect
stdout
to the
PIPE
.
Inside the while loop
proc.stdout.readline()
is called, which blocks until there is a new line.
When the check is True, the while loop is stopped (
break
) and the function returns
proc
.
A solution without regex:
import subprocess
def wait_for_daemon(path, args, ready_string, shell=False):
cmd = [path] + args
proc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE)
while True:
line = proc.stdout.readline() # returns bytes
if ready_string in line:
break
return proc
running_string = b'Running daemon' # Using binary string
proc = wait_for_daemon('./daemon-sim.sh', [], running_string, shell=True)
# don't use shell=True in your case, it's unsafe
You can also set
encoding
in
Popen
to
'utf-8'
or other encoding, which depends on your daemon.
If you set the encoding,
stdout.readline()
returns a
str
and not
bytes
. If you don't set encoding, you'll receive
bytes
.