![制作关机钩子的最佳方法是什么?](https://linux22.com/image/848879/%E5%88%B6%E4%BD%9C%E5%85%B3%E6%9C%BA%E9%92%A9%E5%AD%90%E7%9A%84%E6%9C%80%E4%BD%B3%E6%96%B9%E6%B3%95%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F.png)
由于 Ubuntu 现在已经依赖 upstart 一段时间了,我想使用 upstart 任务在系统关闭或重启时正常关闭某些应用程序。在这些应用程序关闭之前,系统关闭或重启必须暂停。
应用程序有时会手动启动,系统关闭时应通过脚本自动结束(我已经有了)。由于应用程序无法在没有(几乎所有)其他服务运行的情况下可靠地结束,因此必须在其余关机开始之前结束应用程序。
我认为我可以通过关机时触发的 upstart 作业来解决这个问题,但我不确定应该以何种方式使用哪些事件。到目前为止,我已阅读以下(部分矛盾的)陈述:
- Upstart 中没有常规关闭事件
start on starting shutdown
使用类似于作业定义中的节start on runlevel [06S]
使用类似于作业定义中的节start on starting runlevel [06S]
使用类似于作业定义中的节start on stopping runlevel [!06S]
使用类似于作业定义中的节
从这些建议中,出现了以下问题:
- Ubuntu 新贵中是否存在常规关机事件?
- 实现“关闭钩子”的推荐方法是什么?
- 运行级别 [x] 事件何时触发;是在进入运行级别时还是在进入运行级别时?
- 我们可以使用类似
start on starting runlevel [x]
或 之类的东西吗start on stopping runlevel [x]
? - 解决我的问题的最佳方案是什么?
非常感谢
答案1
starting
和runlevel
是独立事件,因此无法有意义地说starting runlevel N
。
事件runlevel N
在开始进入运行级别时发出。如果您进入运行级别,start on runlevel N
则任务将在进入时运行。进入运行级别完成后运行的方式是run on started rc RUNLEVEL=N
。
据我了解,您需要一个start on runlevel [06S]
来执行您想要的操作;理论上它应该在其他任何操作停止之前运行。为了进行更精细的控制,您可以使用它,start on stopping apache or stopping mysql or ...
这样您的任务在允许关闭任何任务之前运行。
编辑以将运行级别 5 更改为 S。
答案2
为了在您的工作停止时阻止关机继续进行,您将需要使用以下命令:
stop on starting rc RUNLEVEL=[016]
这会起作用,因为当您输入“shutdown”时发生的第一件事就是发出 tunlevel 0。rc 在运行级别启动,从停止 -> 启动的转换将完全阻止,直到任何也必须改变状态的作业完成该状态。
您需要确保您的进程能够快速响应 SIGTERM。如果它在 5 秒内没有响应,upstart 将向其发送 SIGKILL。您可以使用“kill timeout X”来引发该问题。
顺便说一下,这里的 1 有点棘手,你需要确保你的启动项包含一些在运行级别 [2345] 上启动的内容,这样用户在进行单用户模式维护时就可以重新启动他们的工作。幸运的是,我们做了很多工作来使其成为建议的通常启动项
start on runlevel [2345]
此外,在某些情况下,你需要某些东西一直运行直到网络关闭(例如 dbus/network-manager)。为此,你需要
stop on deconfiguring-networking
这是在关闭过程中稍后发出的事件,它也将被阻止,直到任何使用它的作业完全完成其状态转换。
答案3
Geekosaur,非常感谢你的帮助。
与此同时,我尝试了这个start on runlevel [016]
方法,但没有效果,我想我明白原因了:
作业确实已启动,但关闭进程直到作业任务完成才被阻止。我现在非常确定事件starting
和stopping
是唯一可以在作业定义中用来阻止其他作业的事件,我认为这就是 Upstart 手册试图告诉我们的。因此,使用运行级别事件永远不会导致阻止其他作业或关闭进程;因此,它对我的目的毫无用处。
相反,我似乎有两种可能性:
按照您的一个主张,找出各个应用程序所需的所有作业,并将它们全部包含在脚本的启动事件中,如下所示:
start on stopping job1 or stopping job2 or ...
这是如此繁重的工作,以至于我认真考虑转储作业列表并通过 sed 运行它以自动为我的作业生成一个开始节,其中包括全部系统上正常运行的作业。
优点是,即使有人手动停止其中一个先决条件,相应的应用程序也会关闭(而不是通过运行级别更改/关闭/重启来停止它们)。
找到重新启动/关闭系统时首先停止的一项作业(我们称该作业为“FirstJob”),并在如下节中使用该作业:
start on stopping FirstJob
主要的缺点是,我不知道这样的工作是否存在,也不知道这份工作是否真的取决于全部相应应用程序实际上所依赖的其他作业(在这种情况下,“依赖于其他作业”意味着“在其他作业开始停止之前将完全停止”)。
我不确定这两种可能性哪一种更好......