【问题标题】:I suspect Popen to timeout without saying我怀疑 Popen 不用说就超时了
【发布时间】:2011-06-28 11:30:25
【问题描述】:

我在编写脚本时遇到了一些困难。目的是启动一个或多个 OpenVZ 容器来执行一些测试。这些测试可能会很长(通常大约 3 小时)。

第一个脚本是这样的,在对要启动的队列成员进行排序之后,它会:

subprocess.Popen(QUEUE_EXECUTER % queue['queue_id'], shell=True)

其中“QUEUE_EXECUTER % queue['queue_id']”是要运行的完整命令。在 queue_execute 脚本中它是这样的:

# Launching install
cmd = queue['cmd_install']
report_install = open(queue['report_install'], 'a')
process_install = subprocess.Popen(cmd, shell=True, stdout=report_install, stderr=subprocess.STDOUT)
process_install.wait()

# Launching test
logger.debug('Launching test')
report_test = open(queue['report_test'], 'a')
cmd = queue['cmd_test']
process_test = subprocess.Popen(cmd, shell=True, stdout=report_test, stderr=subprocess.STDOUT)
process_test.wait()

它工作得很好,但有一段时间,最近,大部分时间,执行都停止了。日志中没有错误或任何内容。报告文件显示它在一行写入的中间停止(我相信这是因为文件在 python 端没有正确关闭)。 在主机方面,OOM 杀手似乎没有做任何事情,我已经搜索了主机的日志,也没有找到任何东西。

上面启动的两个“cmd”是shell脚本,基本上是设置一个vz,并在上面执行一个测试程序。

所以我的大问题是:我是否遗漏了一些会导致脚本在 python 端停止的东西?

谢谢。

编辑:一些补充信息。

失败的命令总是第二个。以下是我尝试执行的命令的两个示例值:/path/vzspawncluster.sh /tmp/file web --tarball /services/pkgs/etch/releases/archive.tar.gz --create/path/vzlaunch.sh 172 -b trunk --args "-a -v -s --time --cluster --sql=qa3 --queue=223 --html --mail=adress@mail.com"

vzlaunch 脚本在带有vzctl enter ID /path/script.py 的 OpenVZ 容器上启动 python 脚本,其中 ID 是容器 ID,/path/script.py 是容器上的脚本。

机器 report_install 和 report_test 是位于通过 NFS 共享访问的不同机器上的文件。没关系,但由于我真的不知道失败时会发生什么,所以我还是记下了。

当它失败时,容器上的进程就会死掉。它不会保持任何僵尸状态或任何东西,它只是死了。虽然容器上的进程失败了,但主进程(启动它们的进程)继续运行,好像一切都很好。

更多信息: 我尝试了 smci 指向的buffer-flushing approach,但我的日志文件的写入一直在一行的中间被剪切:

[18:55:27][Scripteo]       Create process '/QA/valideo.trunk/tests/756/test.py -i 10.1.11.122 --report --verbose --name 756 --...
[18:56:35][Scripteo]       Create process '/QA/valideo.trunk/tests/762/test.py -i 10.1.11.122 --report --verbose --name 762 --...
[18:57:56][Scripteo]       Create process '/QA/valideo.trunk/tests/764/test.py -i 10.1.11.122 --report --verbose --name 764 --...
[18:59:27][Scripteo]       Create process '/QA/valideo.trunk/tests/789/test.py -i 10.1.11.122 --report --verbose --name 789 --...
[19:00:44][Scripteo]       Create process '/QA/valideo.trunk/tests/866/test.py -i 10.1.11.122 --report --verbose --name 866 --...
[19:02:27][Scripteo]       Create process '/QA/valideo.trunk/tests/867/test.py -i 10.1.11.122 --report --verbose --name 867 --...
[19:04:13][Scripteo]       Create process '/QA/valideo.trunk/tests/874/t

【问题讨论】:

  • 你所说的是什么意思'机器report_install和report_test是位于通过NFS共享访问的不同机器上的文件。'你的意思是文件 i> 在不同的机器上,或 jobs,或两者兼而有之?你的意思是这两个作业在不同的机器上并行运行?为什么不在已知良好的机器上运行这两个作业?还是先尝试运行失败的?我不清楚这两个容器是否相互依赖。
  • 我的脚本不是唯一生成此类报告的脚本,这就是为什么它们通过 NFS 共享集中在远程机器上的原因。 (只有文件在那里,作业在本地机器上运行,通过网络在远程机器上写入)。我将所有日志移动到本地目录,它似乎不再崩溃。我有一种感觉,虽然我只治愈了症状,但问题仍然存在。无论如何,感谢您的帮助!
  • 好的,我鼓励你在这个问题上向 OpenVZ 提交一个错误。

标签: python subprocess stdout stderr openvz


【解决方案1】:

您的意图是首先运行process_install 直到它完成,然后运行process_wait? (顺序,不是多处理,对吗?)您怀疑哪个命令超时?

请粘贴queue['cmd_install'], queue['cmd_test']的实际值

(这些命令中的任何一个是否有尾随“&”或重定向?)

这是我的调试建议:

  • (我不知道 OpenVZ,但我假设您已经检查了日志以及它是否允许运行退出命令)

  • 您是否在 UNIX 上运行?如果是这样,您可以使用命令在后台运行 cmd 并运行循环以生成输出,例如一段时间(1)触摸一个哨兵文件,然后休眠 10 秒。或者你可以cmd; touch donesentinel

  • 尝试在每个间隔添加一个轮询循环来 poll() 每个 Popen 对象,而不是 wait()。

  • 或者,在 Popen.pid 启动后打印它,然后从外部检查或轮询该进程是否仍处于活动状态(例如,使用 UNIX top -p)。

  • 如果你的进程产生了很多输出,你注意到the caveat on Popen.wait()了吗? Warning: This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

  • 如果您怀疑这种情况正在发生,请重定向stdout, stderr to os.devnull 中的一个/两个,看看您的结果是否不同。或查看此buffer-flushing approach

【讨论】:

  • 您好,感谢您的回答。我将在我的主要帖子中添加信息,但在这里我已经可以说我在容器和主机上搜索了所有类型的日志,但一无所获。我研究了启动的脚本可能会使文件描述符保持打开状态或以导致脚本停止的方式填充缓冲区的所有方式,但又一次,什么也没找到。在同事的建议下,我尝试使用“python -u”执行脚本,这将禁止 python 缓冲任何内容,但也没有任何改变。我会按照你的建议改变等待脚本结束的方式。
猜你喜欢
  • 2011-12-12
  • 2011-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 2018-10-04
  • 2017-10-01
相关资源
最近更新 更多