I have two processes running
exeAPI
(running in the background with nohup
)tail -f server.log
to output the remote server logI am able to successfully see the output flush to my python client console like this:
@bp.route('/executeAPI', methods=['GET', 'POST'])
def executeAPI():
...
(ssh set up params)
print('started...')
data_buffer = ""
stdin_run, stdout_run, stderr_run = client.exec_command('nohup echo source "exeAPI" | nc 127.0.0.1 40000 &')
stdin, stdout, stderr = client.exec_command('tail -n 1 -f /home/server.log', get_pty=True)
for line in iter(lambda: stdout.readline(1024), ""):
data_buffer += line
print(line, end="")
if not data_buffer: # never hits this if statement
print('No more data')
break
print('finished.')
client.close()
return data_buffer
However, it never exits the for loop
after the output is complete.
How can I break out of the for loop
when there are no newlines?
By design tail -f
doesn't exit when a process is done writing to the log file (it doesn't really know the difference between the log being done and the process just taking a really long time to write its next line). What you probably want is tail -f --pid=PID
if you can obtain the pid of your background process (for example by using ps
). According to the documentation this should terminate tail
after the process with process ID PID dies.
Furthermore, the if not data_buffer
check does not indicate No more data
. The if condition will only be true, if tail
returns without a single byte written to stdout, as data_buffer
will be non-empty after the first non-empty line is read and appended. You could check line
instead, but since you are using iter()
with a sentinel value, this would be redundant.