0

I have the following shell script:

#!/bin/sh
exec 2>&1
echo "Starting ..."
python /home/services/example.py

The python script consists just of a print command. The above script is a daemontools daemon and also a simple log mechanism is enabled (multilog). However, in the main/log/current I see the line "Starting ..." but not the printed commands from the python script.

Am I doing something wrong with the call or did I forget something?

EDIT The python script I am trying to run is:

from time import sleep
import sys

sys.stdout.write("Hello World")
print "Hello World"

while 1:
    sys.stdout.write("Hello world")
    sleep(10)
Freddy
  • 856
  • 2
  • 16
  • 31
  • If you write a Python script that, say, writes to `sys.stdout` or `sys.stderr` every 10 seconds, does it reproduce the problem? If not, you might have something more interesting -- like a script that checks whether stderr is a tty before deciding whether to log to it. This would require looking into the specifics of the program run to reproduce or solve, if so. – Charles Duffy May 24 '16 at 21:57
  • [...as another aside, not really essential to the issue at hand, you'd be well-advised to make it `exec python /home/services/example.py` -- that way any signals will go straight to the Python service, not to the shell that's running it]. – Charles Duffy May 24 '16 at 21:59
  • (Another possibility is that output isn't being line-buffered or otherwise flushed, but that would be a bit surprising if true; still depends on the details of the program being run, so results of an attempt to build a minimal reproducer would be helpful). – Charles Duffy May 24 '16 at 22:01
  • I added the python script and removed the not need `2>&1` – Freddy May 24 '16 at 22:04
  • Thank you -- those details are sufficient to make this answerable. (If you'd just put `print "Hello World"` inside the loop's body, that would have worked; the switch to `sys.stdout` creates a need for more care). – Charles Duffy May 24 '16 at 22:08

2 Answers2

1

Repeatedly running

sys.stdout.write("Hello world")

...just creates a single huge line of the form Hello worldHello worldHello world, with no guarantee that it ever flushes.

Put newlines on any content you write that doesn't have them implicitly (as through print), and flush your buffers when directly using sys.stdout.write():

while 1:
    sys.stdout.write("Hello world\n")  # add a newline
    sys.stdout.flush()                 # flush the buffer
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thank you so far. I also observed something interesting. Only with the linebreak `\n` at the end, it really adds it immediately to the stdout. Otherwise it is only added, when I send the `-d` signal since it is one line. – Freddy May 24 '16 at 22:13
  • That means you're configured for line buffering. Not particularly surprising as a default. – Charles Duffy Sep 09 '19 at 12:19
0

I faced the same issue too.

The solution is to disable output buffering. See Disable output buffering

In your case, update your daemontools run script to:

python -u /home/services/example.py

The -u flag disables Python output buffering.

Community
  • 1
  • 1
Ming C
  • 205
  • 1
  • 9