`cygrunsrv`:如何控制我的服务何时向 SCM 报告成功启动?

问题描述 投票:0回答:1

我有大约十几个基于 cygwin 的 Windows 服务,它们依赖于 Windows 启动期间启动的应用程序的状态(不是作为服务,因为它需要与用户交互)。在应用程序达到特定的所需状态之前,这些服务不应启动。

我编写了一个小程序(我们称之为

app-ready
),它定期检查应用程序的状态。现在我希望这个程序作为上述服务所依赖的服务运行,以便Windows在这个
app-ready
服务表明应用程序已达到所需状态之前不会启动依赖的服务。

执行此操作的一般方法是,只要我们等待应用程序达到所需状态,就将

app-ready
服务保持在
SERVICE_START_PENDING
状态 - 当这种情况发生时,
app-ready
服务应该从
 转换SERVICE_START_PENDING
SERVICE_RUNNING
。这向 SCM 表明相关服务现在可以启动。

但是,

cygrunsrv
在单独的线程中执行所需的应用程序,并自行处理所有SCM回调和状态报告——我们的应用程序
app-ready
没有机会挂钩这些,因此无法显式控制服务状态.

有没有办法使用

cygrunsrv
来管理基于cygwin的Windows服务,以便我们可以控制服务何时报告为
SERVICE_RUNNING

windows-services cygwin
1个回答
0
投票

事实证明,有一种巧妙的方法可以滥用

cygrunsrv
的功能来完成我们想要的事情。

cygrunsrv
支持此选项:

-x, --pidfile <file>      Optional path for .pid file written by application
                          after fork().
                          Default is that application must not fork().

cygrunsrv
来源的帮助下可以看出,使用此选项,
cygrunsrv
切换到特殊模式,等待实际启动的程序终止,并等待
pidfile
更新其内容(或被创建)。然后,这个新进程将作为基于 cygwin 的 Windows 服务背后的实际进程进行监视。

在最初启动的程序(使用

--pidfile
选项)仍在运行的时间段内,
cygrunsrv
通过
syslog
记录此信息:

...app-ready: PID 5000: service `app-ready': waiting for fork of 5001 (#1)
...app-ready: PID 5000: service `app-ready': waiting for fork of 5001 (#2)
...

并在启动的程序终止后切换到以下内容:

...app-ready: PID 5000: service `app-ready': waiting for file /tmp/app-ready.pid (#6)
...app-ready: PID 5000: service `app-ready': waiting for file /tmp/app-ready.pid (#7)
...

直到pid文件写入,然后报告:

...app-ready: PID 5000: service `app-ready' started, pid 5002 read from /tmp/app-ready.pid

此行为可以(误)用于在守护子进程(然后必须无限期运行)之前简单地等待满足任意条件,这将实现我们想要的行为。


可用作

app-ready
服务的示例脚本:

#!/bin/bash -eu
sleep 5 # wait for some condition to become fulfilled
(
    echo $BASHPID > /tmp/app-ready.pid # do this when finally ready (NB: $$ is the top-level PID)
    tail -f /dev/null # run forever -- or periodically check the condition and terminate
) & # background the long-running child process
# top-level exits normally immediately

像这样安装:

cygrunsrv --install app-ready \
          --user $USER \
          --passwd $PASSWD \
          --path /bin/bash \
          --args '-c ~/bin/app-ready' \
          --type auto \
          --pidfile /tmp/app-ready.pid \
          --timeout 600 \
          --neverexits

现在,服务将在 5 秒睡眠期间显示为“正在启动”,并在 PID 写入 pidfile 后显示为已启动。这允许我们在启动服务之后但在它显示为已启动之前执行任意工作/等待。

--timeout 600
选项允许我们延长默认的最长30秒,
cygrunsrv
等待fork和写入pidfile。

如果没有

--neverexits
选项,如果我们的服务终止,
cygrunsrv
将向 SCM 报告 预期 服务停止。使用此选项,退出被视为失败,
cygrunsrv
终止而不将
SERVICE_STOPPED
发送到SCM。反过来,SCM 也将此视为故障并触发为服务配置的任何恢复操作 -- 这可能很有用,具体取决于用例。例如,简单的服务重启可能是有意义的,这将使服务再次处于“正在启动”状态,直到第二次满足条件。

© www.soinside.com 2019 - 2024. All rights reserved.