为什么stdout在连接到使用supervisord运行的进程时不会刷新?

Roc*_*man 4 python unix terminal supervisord

我正在使用Supervisor(用python编写的进程控制器)来启动和控制我的Web服务器和相关服务.我发现有时需要在服务器运行时进入pdb(或ipdb)进行调试.我在通过主管这样做时遇到了麻烦.

Supervisor允许使用名为supervisord的守护进程启动和控制进程,并通过名为supervisorctl的客户端提供访问.此客户端允许您附加到使用"fg"命令启动的其中一个前台进程.像这样:

supervisor> fg webserver
Run Code Online (Sandbox Code Playgroud)

所有日志记录数据都将发送到终端.但我没有从pdb调试器获得任何文本.它确实接受了我的输入,因此stdin似乎正在工作.

作为调查的一部分,我能够确认既不发送print也不raw_input发送; 但在raw_inputstdin确实有效的情况下.

我还能够确认这是有效的:

sys.stdout.write('message')
sys.flush()
Run Code Online (Sandbox Code Playgroud)

我发布fg命令的时候就好像我已经在标准终端的前台运行了进程......但是看起来supervisorctl正在做更多的事情.例如,定期打印不会刷新.有任何想法吗?

当使用fgsupervisorctl中的命令连接到前台终端时,如何使pdb,标准打印等正常工作?

(可能有用的参考:http://supervisord.org/subprocess.html#nondaemonizing-of-subprocesses)

Roc*_*man 7

事实证明,python默认缓冲其输出流.在某些情况下(例如这个) - 会导致输出被扣留.

像这样的习语存在:

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
Run Code Online (Sandbox Code Playgroud)

强制缓冲区为零.

但我认为更好的选择是使用-u标志以无缓冲状态启动基本python进程.在supervisord.conf文件中,它简单地变为:

command=python -u script.py
Run Code Online (Sandbox Code Playgroud)

参考:http://docs.python.org/2/using/cmdline.html#envvar-PYTHONUNBUFFERED

另请注意,这会弄脏您的日志文件 - 特别是如果您使用的是带有ANSI着色的ipdb之类的东西.但由于它是一个开发环境,因此这不太重要.

如果这是一个问题 - 另一个解决方案是停止在supervisorctl中调试该进程,然后在另一个终端中临时运行该进程以进行调试.如果需要,这将保持日志文件清洁.


shx*_*hx2 0

可能是您的网络服务器将其自己的标准输出(内部)重定向到日志文件(即它忽略了supervisord的stdout重定向),并且阻止了supervisord控制其stdout的去向。

要检查情况是否如此,您可以查看tail -f日志,并查看您期望在终端中看到的输出是否在那里。

如果是这种情况,看看是否可以找到一种方法来配置您的网络服务器不这样做,或者,如果所有其他方法都失败,请尝试使用两个终端...(一个用于输入,一个用于输出)