Fabric: 初始化脚本经常无法启动其守护程序

创建于 2011-08-19  ·  19评论  ·  资料来源: fabric/fabric

描述

我已经在IRC上收到了许多有关此问题的报告,并对#350进行了评论,现在是一个邮件列表线程

尚无明确的原因,尽管已被多次报道,但我不希望这是一个持续存在的问题,否则我们会听到更多有关此问题的信息。 到目前为止,在一些非常有限的测试中,我可能会在30-50%的时间内重现该问题-但它是可重现的。

症状很简单,负责启动守护程序然后立即返回的init样式脚本将返回OK,返回0的代码,并向stdout打印“成功”状态消息-但实际上不会启动有问题的守护程序。

我的个人测试是通过针对Ubuntu 10.04(Lucid)VM以及最新的Apache2软件包的init脚本的最新大师完成的。


最初由Jeff Forcierbitprophet )在EDT 2011-07-23 07:25 pm提交

关系

  • 与#350相关:结构挂断一些远程命令(用于守护程序)
Bug Docs Wart

最有用的评论

只是面临这个问题。
我遇到无法使用tty = False的情况,因为我使用sudo运行命令。
添加>& /dev/null < /dev/null &执行得很好,但进程尚未启动。

我通过在命令执行行后添加睡眠来解决问题: nohup java -jar text.jar & sleep 5; exit 0

所有19条评论

Jeff Forcierbitprophet )发表:


安装了我正在测试的初始化脚本,并且一切似乎都以相同的方式运行(即真实成功或假成功方案),这表明问题出在脚本本身进行的apachectl调用之内。

开始考虑到底是什么原因造成的:

  • 由于它是半随机的,这使我想起了受竞争条件困扰的IO子系统的过去问题。 但是,我真的无法考虑这种方式可能如何影响远程端的某些内容,而且比赛条件无论如何都是基于本地的。

    • 一种测试方法是查看Fab 0.9.x和pty = True是否与该问题有关(以匹配1.x中的当前默认值)。

  • 它也可能与pty有关-我不记得这是1.0之前的问题,将pty设置为True是默认行为的主要变化之一。 再次说明,我看不到为什么使用SSH的request-a-pty子系统会导致初始化脚本以这种方式运行。

    • 这里的测试将是使用ssh -t <hostname> <command> ,看看是否还会重现该问题。


2011-07-23上在下午7时45 EDT

Jeff Forcierbitprophet )发表:


apache2ctl本身也只是一个名为/usr/sbin/apache2的包装Bash脚本,它是指向Apache mpm-worker安装位置中的实际二进制可执行文件的符号链接。 具体来说,在正常的start用法中,它调用/usr/sbin/apache2 -k start 。 和以前一样, apache2ctl在两种不同的情况下似乎没有什么不同,例如:返回值或执行了哪些部分。

/usr/sbin/apache2的文档相对有限(即使在Apache的网站上也是如此),仅说明您应该使用apachectl来设置env var(这是正确的-仅运行apache2本身就可以解决问题显然有关于未设置这些var的错误。)

检查的输出env之前,为了apache2ctl的的调用apache2收率只有几个项目:用户,组,位置了pidfile和语言。 这些在成功和失败情况之间不会改变。 我很希望包装中的各种资源和环境设置中的某些内容有时会更改,但不会更改。


到目前为止,这没有任何用处。 现在该测试上述想法(pty,ssh),看看那里有什么变化。


美国东部时间2011-07-23 08:46 pm

Jeff Forcierbitprophet )发表:


使用pty=False ,它看起来确实好得多(如#350中Max的评论所暗示)。 使用默认的True设置,我看到的故障大约是5/10次,有时甚至更多或更少。 使用False,我已经连续运行了15次,零故障。 不是统计学家,但这对我来说似乎很好。

手动运行ssh产生类似的结果: ssh -t <host> sudo /etc/init.d/apache2 start将在大约50%的时间内默默地无法启动Apache。 与-T (强制没有pty),它的启动时间为100%。

因此,这不是Fabric的错。 当使用SSH风格的伪tty时,这些初始化脚本的行为会更糟。


为了好奇起见,我们将进行更深入的研究,但看起来“解决方案”是一个新的常见问题解答,说明在遇到此问题时使用pty=False


美国东部时间2011-07-23 08:59 pm

Jeff Forcierbitprophet )发表:


是的,很遗憾,没有找到任何能解释这种现象的信息。 鉴于以上发现,我认为常见问题解答绝对是解决之道。


美国东部时间2011-07-23下午10:35

雨果·加扎


嗯,我昨天刚遇到这个问题,希望我会看到这个错误,幸运的是,我尝试设置pty = False,它也能正常工作。 感谢您的解释,至少这不是织物故障。 现在您真的让我想知道为什么这失败了。


美国东部时间2011-08-02下午01:27

您确定这不仅是bash脚本问题吗? 我的意思是我的邮件列表线程。 它们只是启动Java和Weblogic的bash脚本。

FWIW,我在EC2上启动的几乎每台Ubuntu计算机上都出现这种可怕的行为。

通过通过独立屏幕screen -d -m someBackgroundTask启动的任务也可以重现。

我应该提到通常pty=False可以解决问题,但是我看到的情况并非如此。

@yuvadm-在pty = False不能解决问题的情况下,是否仍可以使用常规ssh命令重新创建问题(如上所述)? 据我所知,这是一个SSH问题,而不是Fabric问题,但是最好知道是否有任何情况与之不符。

这是一个有趣的角度,我会在那一个方面与您联系...

我转载了这个问题。 客户端是Ubuntu 10.04.3 LTS,服务器是“ Ubuntu 8.04.4 LTS(服务器)”。
SSH客户端是“ OpenSSH_5.3p1 Debian-3ubuntu7,OpenSSL 0.9.8k,2009年3月25日”,ssh服务器是“ OpenSSH_4.7p1 Debian-8ubuntu1,OpenSSL 0.9.8g,2007年10月19日”。 结构是“ 1.3.3最终版本”。

问题是pty = True时为100%,而pty = False时便消失了。

连接到其他服务器时,当pty = True时,此问题并不总是存在。

就我而言,为了进行测试,我正在运行一个非常简单的命令:“ nohup sleep 100> / tmp / xxx 2>&1

我一直只在EC2上被这个问题所困扰(我在Linode上还没有看到它,但是我不确定100%)。 设置pty = False似乎可以解决此问题。

只是面临这个问题。
我遇到无法使用tty = False的情况,因为我使用sudo运行命令。
添加>& /dev/null < /dev/null &执行得很好,但进程尚未启动。

我通过在命令执行行后添加睡眠来解决问题: nohup java -jar text.jar & sleep 5; exit 0

感谢spodgruskiy,

您的提示对我有用。
我试过用以下命令编写fab tp启动strom集群。

  1. 运行('nohup ./bin/storm nimbus>&/ dev / null </ dev / null&',pty = False)
  2. 运行('nohup ./bin/storm nimbus>&/ dev / null </ dev / null&')
  3. run(“ screen -d -m'./bin/storm nimbus'”,pty = False)
  4. run(“ || screen -d -m'./bin/storm nimbus'”)

但是它们都不起作用,灵气根本没有开始。 我不明白发生了什么事。
总之感谢。

+1的睡眠技巧

需要在具有requiretty的系统上工作

sudo('start service; sleep .5')一切都很好!

在使用“ sudo()”并且远程系统启用了RequireTty进行sudo访问的地方,可以使用“ set -m;”。 服务“开始”以防止将SIGHUP发送到由初始化脚本启动的进程。

有关bash交互式与非交互式以及如何影响作业控制的详细说明,请参见http://stackoverflow.com/a/14866774

我很好奇,这里的ssh问题是什么?

pty = false对我有用

这并不是一个真正的SSH问题,更多的是围绕BASH非交互/交互模式以及信号向进程组的传播的微妙行为。

以下内容基于http://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshel​​ls-without-t-and-kill-them-with-t/14866774#14866774http: //www.itp.uzh.ch/~dpotter/howto/daemonize ,其中一些假设尚未得到充分验证,但有关此工作原理的测试似乎可以证实。

pty / tty =假

启动的bash shell连接到已启动进程的stdout / stderr / stdin,并保持运行状态,直到套接字上没有任何连接并且子进程退出为止。 一个好的守护进程将确保它不会等待其子进程退出,派生一个子进程然后退出。 在这种模式下,不会通过SSH将SIGHUP发送到子进程。 我相信这对于执行处理自我妖化过程的大多数脚本来说是正确的,不需要后台处理。 如果初始化脚本使用'&'来使进程后台运行,则主要问题可能是后台进程是否曾经尝试从stdin读取数据,因为如果会话已终止,这将触发SIGHUP。

pty / tty = true *

如果init脚本在后台启动了进程,则父BASH shell将向SSH连接返回退出代码,这将导致立即退出,因为它不等待子进程终止并且在stdout上未被阻止/ stderr / stdin。 这将导致将SIGHUP发送到父bash shell进程组,由于在bash中以非交互模式禁用了作业控制,因此该组将包括刚刚启动的子进程。 守护进程在分叉时或在分叉的进程中显式启动新的进程会话时,它或它的子进程将不会从退出的BASH父进程收到SIGHUP。 请注意,这与将看到SIGTERM的挂起作业不同。

我怀疑围绕此问题的问题有时仅与轻微的比赛条件有关。 如果您查看标准的除妖方法-http: //www.itp.uzh.ch/~dpotter/howto/daemonize ,您会发现在代码中,新会话是由分支过程创建的,可能不会在父级退出之前运行,因此导致了上面提到的随机成功/失败行为。 sleep语句将为分支过程创建新的会话留出足够的时间,这就是为什么它在某些情况下有效的原因。

pty / tty = true,作业控制已在bash中明确启用

SSH不会连接到bash shell的stdout / stderr / stdin或任何启动的子进程,这意味着它将在父bash shell开始执行完所请求的命令后立即退出。 在这种情况下,在显式启用作业控制的情况下,由bash shell启动并带有“&”作为背景的所有进程将立即置于一个单独的会话中,并且当BASH会话的父进程退出时将不会收到SIGHUP信号( SSH连接(在这种情况下)。

需要解决什么

我认为解决方案只需要在运行/ sudo操作文档中明确提及,作为使用后台进程/服务时的特殊情况。 基本上要么使用'pty = false',要么在不可能的地方使用显式启用作业控制作为第一个命令,并且该行为将是正确的。

链接更新: http :

正如我在这里提到的fabrickit(织物库的包装) https://github.com/HyukjinKwon/fabrickit/commit/cceb8bfb8f960a3ac41b24c64b8358bd6e7a0366

您可以完全轻松地将程序作为守护程序启动,而无需进行特定的配置或设置。
无论如何,这是Shell的一种执行方式,因此应该有一种方法可以执行Shell可以执行的操作。

试试这个:

run("sh -c '((nohup %s > /dev/null 2> /dev/null) & )'" % cmd, pty=False)

我尝试了此方法,即使它没有实现作为守护程序运行的其他程序(即使只是在while循环中编写“ Hello”的程序也可以正常工作),它也可以正常运行。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

supriyopaul picture supriyopaul  ·  4评论

shadyabhi picture shadyabhi  ·  5评论

peteruhnak picture peteruhnak  ·  6评论

Grazfather picture Grazfather  ·  4评论

jamesob picture jamesob  ·  3评论