1

I have a script stored in /etc/init.d that works ok when executed at boot time. Since I do not export USER, it should execute everything as root (if I'm not wrong).

Then, it executes python3 script.py In this script, everything works fine until it reaches

espeak_process = Popen(["espeak", "-ves", "-s100", msg, "--stdout"], stdout=subprocess.PIPE)
aplay_process = Popen(["aplay", "-D", "sysdefault"], stdin=espeak_process.stdout, stdout=subprocess.PIPE)

EDIT: changed for this code, but the created file is empty

def log_uncaught_exceptions(ex_cls, ex, tb):
    f = open('/home/pi/debug_err.txt', 'w')
    f.write('hi ')
    f.write(ex_cls+' '+ex+' '+tb)
    f.close()

sys.excepthook = log_uncaught_exceptions
espeak_process = Popen(["espeak", "-ves", "-s100", msg, "--stdout"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

/EDIT

At which point it stops. I can tell that since it writes a debug file before and after this step, and the 2nd one is never written.

The thing though is that if I execute in a terminal

sudo sh /etc/init.d/begin start

Then the "python3 script.py" is executed entirely ok, including the Popen part.

Why is that happening? Thx

(init.d script)

#! /bin/sh
# /etc/init.d/begin 

#USER=pi
HOME=/home/pi

#export USER HOME
export HOME

case "$1" in
 start)
  if [ -f "/home/pi/begin.pid" ];
  then
    kill -9 $(cat /home/pi/begin.pid)
    rm -f /home/pi/begin.pid
  fi
  python3 /home/pi/script.py &
  ;;

 stop)
  kill -9 $(cat /home/pi/begin.pid)
  rm -f /home/pi/begin.pid
  ;;

 *)
  echo "Usage: /etc/init.d/begin {start|stop}"
  exit 1
  ;;
esac

exit 0
GWorking
  • 4,011
  • 10
  • 49
  • 90
  • Can you try reading `stderr` and perhaps log the output? – Reut Sharabani Jan 13 '15 at 08:49
  • Read this answer: http://stackoverflow.com/a/10683323/948550 – Reut Sharabani Jan 13 '15 at 08:52
  • Thanks. Based on your link I've tried to recover the error message with communicate() but the python script stops when it executes it, so it never reaches this code. Is there a way that I can handle this? – GWorking Jan 13 '15 at 09:51
  • [The python script exits before executing the "communicate()" command, so I cannot read any error message] – GWorking Jan 13 '15 at 10:08
  • unrelated: you should add `close_fds=True` (it is default on POSIX since some Python 3 version) and set all (stdin/stdout/stderr) unused streams to `DEVNULL` e.g., `stdin=DEVNULL`. Call `espeak_process.stdout.close()` after `Popen(["aplay...` Either read from `aplay_process.stdout` or set `stdout=DEVNULL`. – jfs Jan 13 '15 at 10:30

1 Answers1

1

Popen() returns as soon as the child process is started. It does not wait for it to finish. It is very unlikely that your scripts blocks for long on Popen().

A possible explanation is that your script raises an exception and terminates while trying to start espeak or aplay processes -- that is why you don't see the 2nd record in the log file. Catch and log all errors e.g., set sys.excepthook.

You don't see the error when running manually because the environment is different: disks are mounted, audio service is running, X is started, etc -- I don't know what espeak, aplay require to run.

As an alternative save all output to a file:

# python3 /home/pi/script.py </dev/null >/home/pi/script.out 2>/home/pi/script.err &

I can see what's the problem, and it was to pass an argument with accentuated words (strange that it wasn't the case when I executed the script from the shell). I've eliminated the accents and now it works ok.

Try to specify a utf-8 locale. The default is C locale that uses ascii encoding that can't represent accentuated words directly:

# LANG=C.UTF-8 python3 ...

If there is no C.UTF-8 locale in the output of locale -a command then choose any other utf-8 locale from the list.

jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • I have added the code (see edited question), and the log file is written but it is empty, any idea? – GWorking Jan 13 '15 at 14:09
  • @Gerard: I see errors in `log_uncaught_exceptions()`. You should test it first on a simple script that intentionally raises an exception. I've update the answer. You could redirect the output of the script as an alternative – jfs Jan 13 '15 at 14:16
  • The problem is that when I execute the script (and I can see any message on the shell) everything runs ok (or at least I hear sound and the script does what he has to do). – GWorking Jan 13 '15 at 14:34
  • But when it runs from the init.d script, then it fails, and then I cannot see any error message – GWorking Jan 13 '15 at 14:35
  • Actually, I can see that it writes "hi" (see edited question), but it doesn't write anything else. How is that possible? How can I know why the script is stopping there? – GWorking Jan 13 '15 at 15:29
  • @Gerard: Have you tried your `excepthook` with a dead simple script to make sure it works as I suggested? Have you tried to redirect the output to a file as I suggested? – jfs Jan 13 '15 at 15:51
  • Ah, you meant to test the excepthook, not the script, I didn't get that. I'll try asap. But related to the output redirection, now I see that I can do that in the init.d script as well, again I didn't get it. I'll try asap too – GWorking Jan 13 '15 at 16:08
  • Yes, by redirecting the output as you say (I have not tested excepthook) I can see what's the problem, and it was to pass an argument with accentuated words (strange that it wasn't the case when I executed the script from the shell). I've eliminated the accents and now it works ok. Thanks! – GWorking Jan 13 '15 at 16:31
  • @Gerard: your `excepthook` tries to add string with non strings, use formatting instead or: `f.write(" ".join(map(repr, [ex_cls, ex, tb])))` I've updated the answer to show how to enable support for accentuated words. – jfs Jan 13 '15 at 16:38