【问题标题】:Python Popen process not working when it is executed from init.d script从 init.d 脚本执行时,Python Popen 进程不起作用
【发布时间】:2015-03-11 03:03:30
【问题描述】:

我有一个脚本存储在 /etc/init.d 中,在启动时执行时可以正常工作。由于我不导出 USER,它应该以 root 身份执行所有操作(如果我没记错的话)。

然后,它执行 python3 script.py 在这个脚本中,一切正常,直到它到达

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

编辑:此代码已更改,但创建的文件为空

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)

/编辑

它在什么时候停止。我可以说,因为它在这一步之前和之后写了一个调试文件,而第二个从来没有写过。

问题是,如果我在终端中执行

sudo sh /etc/init.d/begin start

那么“python3 script.py”就完全没问题了,包括Popen部分。

为什么会这样? 谢谢

(init.d 脚本)

#! /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

【问题讨论】:

  • 您可以尝试阅读stderr 并记录输出吗?
  • 谢谢。根据您的链接,我尝试使用communicate() 恢复错误消息,但是python脚本在执行时停止,因此它永远不会到达此代码。有没有办法解决这个问题?
  • [python脚本在执行“communicate()”命令之前退出,所以我看不到任何错误信息]
  • 不相关的:你应该添加close_fds=True(它在POSIX上是默认的,因为一些Python 3版本)并将所有(stdin/stdout/stderr)未使用的流设置为DEVNULL,例如stdin=DEVNULL。在Popen(["aplay... 之后调用espeak_process.stdout.close()aplay_process.stdout 读取或设置stdout=DEVNULL

标签: python raspberry-pi popen init.d


【解决方案1】:

Popen() 在子进程启动后立即返回。它不会等待它完成。您的脚本不太可能在 Popen() 上长时间阻塞。

一种可能的解释是,您的脚本在尝试启动espeakaplay 进程时引发异常并终止——这就是您在日志文件中看不到第二条记录的原因。捕获并记录所有错误,例如,设置sys.excepthook

手动运行时看不到错误,因为环境不同:磁盘已挂载、音频服务正在运行、X 已启动等 -- 我不知道espeakaplay 需要什么运行。

作为替代方法,将所有输出保存到文件中:

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

我可以看到有什么问题,它是传递一个带有重音字的参数(奇怪的是,当我从 shell 执行脚本时情况并非如此)。我已经消除了口音,现在它可以正常工作了。

尝试指定一个 utf-8 语言环境。默认是使用 ascii 编码的 C 语言环境,不能直接表示重音词:

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

如果locale -a 命令的输出中没有C.UTF-8 语言环境,则从列表中选择任何其他 utf-8 语言环境。

【讨论】:

  • 我已经添加了代码(见编辑过的问题),并且日志文件被写入但它是空的,知道吗?
  • @Gerard:我在log_uncaught_exceptions() 中看到了错误。您应该首先在一个故意引发异常的简单脚本上对其进行测试。我已经更新了答案。您可以重定向脚本的输出作为替代
  • 问题是当我执行脚本时(我可以在 shell 上看到任何消息)一切运行正常(或者至少我听到声音并且脚本执行了他必须做的事情)。
  • 但是当它从 init.d 脚本运行时,它会失败,然后我看不到任何错误消息
  • 实际上,我可以看到它写了“hi”(见编辑过的问题),但它没有写任何其他内容。这怎么可能?我怎么知道脚本为什么停在那里?
猜你喜欢
  • 2021-04-02
  • 1970-01-01
  • 2015-10-28
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
  • 2014-09-14
相关资源
最近更新 更多