【问题标题】:How can my process detect if the computer is shutting down?我的进程如何检测计算机是否正在关闭?
【发布时间】:2012-05-21 23:07:20
【问题描述】:

我正在 EC2 现货实例上运行一些应用程序。此类实例可能会在不通知的情况下被 Amazon 杀死。

在关闭过程中,进程按某种顺序被杀死。我们有监控/恢复程序,它们的行为应该根据服务器是关闭还是进程刚刚崩溃而有所不同。 (特别是如果服务器实际上正在关闭,我们不想做任何事情)

如何在恢复过程中(如果它仍然存在)检测到进程因关闭而被终止?

(更多系统细节:我在不修改外部状态的沙箱中运行未知/不受信任/等代码。通常如果沙箱代码崩溃,是不受信任代码的作者的错,我们不会重新运行它.但是如果沙盒代码由于VM关闭或失败而终止,我们需要在另一个实例上重新运行它。我现在遇到的问题是用户的代码首先被终止,所以监控程序错误地认为崩溃了是用户错误。)

【问题讨论】:

  • 监控过程是如何工作的?用户进程是用什么语言编写的?用户进程是否通过初始化脚本启动和停止,您是否可以控制这些脚本?我对如何解决这个问题有一些想法,但如果没有更多细节,很难说什么会奏效。
  • 监控是通过 waitpid 完成的。用户进程在 python 中,但它可以运行用任何语言编写的任意扩展模块。用户进程由处理监控的同一进程启动(我们不使用初始化脚本)。

标签: linux amazon-ec2 shutdown


【解决方案1】:

代理

在生成沙盒子进程的每台机器上运行一个代理。代理运行您的“防崩溃”代码,沙盒代码运行可能崩溃的用户代码。

负责启动具有新沙盒进程的新机器的监控系统检查哪些进程已被杀死(代理和沙盒进程或仅沙盒子进程)。

它通过向查询其子进程的代理打开 TCP 连接 (RMI/RPC/HTTP) 来实现这一点。 如果代理响应 - 机器仍在运行,并且可以询问其子沙箱进程。 如果代理没有响应 - 机器可能被终止。

代理(变体)

代理还负责在同一虚拟机上重新启动子沙盒进程,以防它崩溃。

查找服务

使用查找服务(例如 Zoo Keeper)来跟踪哪些进程发送了心跳保持活动。如果代理还活着,那么机器还在运行,如果代理不活着,那么它就没有运行。

ec2 接口

轮询 EC2 API 以确定机器是处于运行状态还是终止状态。

【讨论】:

  • 旁注:在 Cloudify 中,我们成功地使用了方法组合(代理+查找服务)。它还可以检测到沙箱的 100% CPU 或 Java GC,这会导致沙箱未发送 keep-alive,但报告沙箱的代理正在运行。我计划添加(ec2 api)以检测用户代码请求操作系统重启的场景(通常在安装遗留组件期间发生在 Windows 机器上)
  • 好主意。我将研究使用本地 ec2 api 来查询事物。在代理方面,乍一看,这和我现在遇到的问题一样。在关闭期间,沙盒子可能会在代理之前被杀死,从而导致对子崩溃的错误信念。是否有时间保证所有东西必须被杀死多长时间?
  • 首先,您可以使用 init.d 东西来注册守护程序关闭挂钩,该挂钩将仅关闭代理,而代理将依次关闭其子进程。其次,如果您正在使用查找服务并且进程收到 KILL 信号,则该进程有时间通知查找服务它正在关闭,因此查找服务不需要等待保持活动更新超时。第三,即使没有任何关闭钩子,当管理检测到孩子没有更新保持活动租约并尝试联系代理时,代理已经关闭。
  • 感谢您的帮助。 LnxPrgr3 描述的 init.d、ec2 api 和 waitpid 的组合应该可以让我完成这项工作。
【解决方案2】:

您的恢复过程如何运作?

如果你使用waitpid来监控进程,当它退出时你可以确定:

  • 是否正常退出,如果退出,进程返回什么状态,或者
  • 是否因信号而退出,以及该信号是什么。

根据进程的关闭方式,我希望看到它正常退出或通过SIGTERMSIGKILL 退出。 SIGILLSIGABRTSIGFPESIGBUSSIGSEGVSIGSYS 表示因编程错误而崩溃。

【讨论】:

  • 我们使用waitpid。问题是什么信号意味着(并且仅意味着)机器正在关闭。编程错误也可能导致 SIGTERM 或 SIGKILL。 (在您的代码中调用 sys.exit() 在我们的系统中被视为“错误”)
  • 调用sys.exit() 应该会导致正常退出(WIFEXITED 应该返回true),而系统关闭导致的死亡将是SIGTERM 和/或SIGKILL。你能用它来区分它们吗?
  • 我不能,因为就我所知,程序员可能已经完成了 sys.exit(1)。我希望在 /proc 或其他地方设置了一些东西,我可以用它来告诉系统处于关闭状态。
  • @UsAaR33:执行无效操作并因此被操作系统杀死的程序不会被 SIGTERM 或 SIGKILL 杀死。调用sys.exit(...) 将导致进程正常退出(除非某些atexit/对象销毁代码执行了无效的操作),因此WIFSIGNALED 将是错误的。如果一个进程由于 SIGTERM/SIGKILL 而退出,这意味着某些东西选择了杀死它,在您描述的情况下,这很可能是由于系统关闭。
  • @jamessan 我的错,您是正确的,因为此方法将正确检测另一个程序(例如关闭进程)是否终止了用户的进程。它几乎是完美的,实际上我可能会部分使用它......一个缺点是程序员可以(出于某种原因)用信号杀死自己的进程,将这个测试混为一谈。
【解决方案3】:

这听起来像是一个非常脆弱的计划。不要尝试检测系统的状态:让您的应用程序在“干净”关闭/停止/停止应用程序之后以某种方式写出一个有效性令牌(并同步相关文件!)并使用它。

【讨论】:

  • 适用于通用的应用程序。但是,我们监控的应用程序是由其他用户编写的,并且可能由于该用户的错误而崩溃。事实上,如果它崩溃了,几乎可以肯定是由于该用户的代码存在问题,除了我们的硬件关闭。
  • 那么我认为您需要为问题添加更多细节。从该响应中,我了解到您正在尝试运行不受信任/未经测试/未经验证的代码,并在失败后让它干净地恢复。我不明白这怎么可能。
  • 正确,我在沙箱中运行未知/不信任/等代码。一项要求是代码不修改外部状态。这意味着如果机器出现故障,可以在另一台机器上重新启动。但是,如果代码由于其他原因崩溃,我们认为是代码作者的错,不要重新启动。
【解决方案4】:

我假设当实例关闭时,您的监控进程会收到一个 SIGTERM 信号。

那么是否有可能做类似的事情 - 如果被监控的进程已经退出 && 在接下来的 5 秒内没有收到 SIGTERM 信号 - 假设进程崩溃了。如果收到 SIGTERM,只需退出信号处理程序。

【讨论】:

    猜你喜欢
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多