探究WinSW封装Nginx服务及日志清理

如前述,我们项目中目前还在Win32平台,切换到了Nginx架构的RTMP服务器。当然也是长时间不规范的直接双击运行的,虽说Nginx的架构保证进程活着问题不大,但是无法应对突然的停电,停电之后无人去操作启动,造成了无人觉察的故障,这也是一个极大的风险。

技术选型

当然我们的目标是把nginx做成一个服务,不像Linux下那么方便。基本上就两种方法,自己写一个监控服务,另外一种就是使用第三方工具做成系统服务,这其中第三方服务基本不太会监控Nginx的死活,只会保证系统开机自启Nginx(当然也有直接放到启动菜单或者注册表中的办法,我们暂还是用比较规范的方法)。

自己开发的话有一定工作量,况且Nginx的稳定性问题不大,因此不太有必要自研。网络上比较流行的方法是采用Windows Service Wrapper工具(WinSW)进行包装,也有很多其他软件,不过这个软件相对简单易用,而且普遍反映相对其他软件功能没有问题。

此开源项目的地址是:https://github.com/kohsuke/winsw

2.0之后的版本提供了.net 2.0和.net 4.0两个版本的下载,根据实际情况下载。

WinSW配置

WinSW的使用相对比较简单,基本步骤如下

  1. 首先建议将下载的exe改名,比如我们给Nginx包装的服务,那改名为nginx-service.exe

  2. 然后创建同名的xml配置文件,如nginx-service.xml,比如Nginx可配置如下

    <?xml version="1.0" encoding="UTF-8" ?>
    <service>
    <id>nginx</id>
    <name>Nginx Media Service</name>
    <description>Nginx Based Media Streaming Server</description>
    <executable>nginx.exe</executable>
    <logpath>./logs</logpath>
    <logmode>roll</logmode>
    <stopexecutable>nginx.exe</stopexecutable>
    <stopargument>-s</stopargument>
    <stopargument>stop</stopargument>
    </service>

    XML文件的详细配置教程见官方文档 xmlConfigFile.md

  3. 安装,使用管理员权限的CMD,输入安装命令

    nginx-service.exe install
  4. 启动,在CMD输入启动命令,或者在系统services.msc图形界面启动

    nginx-service.exe start

其中,该命令可使用 start | stop | install | uninstall 等,对应启动、停止、安装、卸载等

Nginx日志清理

不说Linux下很方便的清理方式,只谈Windows。如果你仔细观察,会发现Nginx生成的日志文件不会自动分割,比如按时间或者按大小,这样长此以往,文件会非常大。观察现网的日志已经五百多兆了,急需清理,通过 /stat 统计页面查看,长期都有五六十个推流端在推流,当然总推流时长不会很长。

大部分网上的办法都是重启Nginx服务,我觉得不可接收,有些更好的方案是转移文件,然后reload。

我们来试试reload的效果,修改配置文件中比如日志的名称,然后nginx -s reload,你会发现没有权限!为什么没有权限,通过任务管理器可以看到Nginx的权限是SYSTEM,可以想到系统服务都是SYSTEM权限的,想操作还得用这个权限,正常情况下我们是不能获取到SYSTEM权限,根据网上办法也不靠谱,但是既然WInSW搞出来了SYSTEM权限, 类似的,我们再制作个NginxReloadService,就执行reload操作即可解决权限,简单暴力,那么再探究下日志问题。

如前,然后再测试,基本OK,如果你运气好点,你会发现更严重的问题,Nignx的进程有三个,而且通过 /stat 查不到正在进行的推流统计,当然也没办法播放了。应该是Nginx在reload的时候,Nginx重新创建了一个新的worker进程来提供服务并采用了新配置,老的worker进程在现有服务完成后会退出,为了验证,停止了推流,这个进程很快关闭。

这么看来,reload方式的主要问题是不实时,在rtmp这种长连接的情况下不太可用。重启大法好啊,难道就只剩这一个办法了么。

完美的方案

观察和思考良久,发现网上比较好的博客在介绍Linux下日志分割的时候,并不是重启进程啥的,用的是信号SIGUSR1,也就是让Nignx重新打开日志文件。这给了我们启示,说明Nginx是支持受命令控制重新打开日志文件的,当然Windows下是没有这个信号的,仔细查阅下发现这个信号其实等同与nginx -s reopen,对就是reopen这个一直被忽略的命令。再来试试效果,手动Move文件之后,然后reopen,文件生成了,进程PID根本就没变,看来reopen是个完美的方案。

结合前述问题,最终通过WinSW再封装一个reopen的操作的服务(可以保证SYSTEM权限),剩下的就是定时任务了(注意运行账户改为SYSTEM),基本上完美解决日志分割问题,并且没有特别的副作用。

Nginx Logrote Service 配置样例

<?xml version="1.0" encoding="UTF-8" ?>
<service>
<id>nginx-logrote</id>
<name>Nginx Logrote Service</name>
<description>Logrote Service for Nginx Based Media Streaming Server</description>
<executable>nginx-logrote-service.bat</executable>
<startmode>Manual</startmode>
<logpath>./logs</logpath>
<logmode>roll</logmode>
</service>

Nginx Logrote Service 批处理文件样例

@ECHO OFF
CD logs

FOR /f "delims=" %%i IN ('DIR /a-d /b access.log') DO (
IF %%~zi gtr 10485760 (
MOVE /Y %%i %%i.bak
)
)

FOR /f "delims=" %%i IN ('DIR /a-d /b error.log') DO (
IF %%~zi gtr 10485760 (
MOVE /Y %%i %%i.bak
)
)

CD ..
nginx -s reopen

PS:网上的方法真是误人子弟啊,一个高质量的博客显得是多么重要!

最近的文章

通过28181与WebRTC直播摄像头

前文描述了WebRTC视频直播技术,后续应用到系统中,版本已经做出来了并封装了JS的SDK,实时性效果还是非常令人惊喜的,针对部分调整和问题进行记录。 视频源项目使用的是海康摄像头,我打算取消本地服务器,直接让摄像头通过GB28181协议进行推流。为了让所有用户可以观看,将服务部署在公网,当然这里需 …

技术 继续阅读
更早的文章

SetConsoleCtrlHandler实现资源释放

今天决定对程序产生的不完整的临时文件进行下优化,当然这些临时文件是非预期的,在程序中都进行了处理,但是在某些情况下确实是发生了。 现象分析首先可以确认的是这些临时文件都是程序在退出时候未处理生成的。当然程序全部是正常退出的,并没有异常崩溃,但是退出的方法有多种,比如Ctrl+C按键,比如直接点击控制 …

技术 继续阅读