0

Suppose I have a python script script.py

from time import sleep
for i in range(3):
    print(i)
    sleep(1)
print('done')

which I want to run on a remote server via an ssh command e.g.

ssh me@server "python script.py"

If I do the above verbatim, I get the whole output 0 1 2 done three seconds after I started the script. Instead, I would like to see the output immediately as it is generated by the script, i.e. 0 -one second later- 1 -one second later- 2 -one second later- done.

I've seen similar questions regarding viewing the log file, but is there an easy way to do this (e.g. without intermediate logging to a file on the server)?

dkv
  • 457
  • 1
    "I've seen similar questions regarding viewing the log file, but is there an easy way to do this (e.g. without intermediate logging to a file on the server)?" -- At least some solutions should work in your case as well. Use python -u. – Kamil Maciorowski Jun 25 '21 at 05:11

1 Answers1

1

When programs send output to stdout in uinx, the output is typically buffered to optimize I/O performance. The buffering mode is typically selected based on the context the program is run in.

When you start an interactive session in unix, your session is typically line buffered, meaning that buffers are flushed when a newline is output by the program.

When programs are started in a file context (i.e., stdout is a file), or sometimes a pipe context, they are usually block buffered, meaning that a block is not written until it is full -- typically 8192 bytes.

Programs can internally change this either by flushing stdout when they want to, or directly changing the buffering mode. Unfortunately, python support for this is poor or non-existent.

You can externally change the buffering mode by starting the program with the stdbuf command.

For example:

ssh me@server "stdbuf -oL python script.py"

Should do what you want, forcing it to be line buffered.

user10489
  • 6,740
  • python -u works too, as mentioned by @Kamil Maciorowski – dkv Jun 25 '21 at 14:53
  • Or, not specific to python, you can use ssh -t (in some cases you need ssh -tt) to have the program (here python) run with I/O via a pseudo-terminal (PTY) instead of pipes, and then line-buffering (or possibly less) happens by default. Note this also makes the output linebreaks CRLF not LF (unless you run stty on the remote, it the program does equivalent syscalls) which may be a problem in some cases. – dave_thompson_085 Dec 02 '21 at 03:32