将 Redis 作为 Windows 服务运行






4.96/5 (22投票s)
一个用于将 Redis 或其他可执行文件作为 Windows 服务运行的实用程序。
引言
在本文中,我将演示如何将 Windows 版本的 Redis Server 或其他可执行文件作为 Windows 服务运行。
在 CodeProject,我们将 Redis 用作分布式缓存。我们存储大量信息,如文章、论坛消息,并从缓存中检索这些项目,而不是从数据库中检索。
Redis 允许我们存储和检索完整的文档,而不是在每次请求时查询 SQL 获取各个部分并进行组合和格式化。这在我们的网站上是可行的,因为大部分信息读取的次数远多于写入的次数,而且一些信息,例如查看次数,可能有点过时。
虽然在生产环境中,我们在 Linux 服务器上运行 Redis,但在我们的开发环境中,我们在 Windows 7 桌面机上运行 Microsoft 移植的 Redis。问题在于 Redis 的设计并非用于作为 Windows 服务运行。这意味着必须有人登录并运行 Redis 可执行文件。当 Chris 是唯一登录服务器的人时,这没问题,但上周,我需要连接来安装一个用于开发目的的搜索服务器副本。不用说,这导致 Chris 被注销,并且 Redis 服务器被终止。我在我的会话下重新启动了它。
回到我的机器上,我正在修复一个微妙的缓存错误,当我开始测试时,代码的行为就像 Redis 服务器连接失败一样。由于我正在更改的代码与检测 Redis 连接问题有关,我在花费大约半小时的时间后才意识到 Chris 已经远程登录到服务器,终止了我的会话和 Redis 服务器。
我和 Chris 都尝试了许多推荐的将 Redis 作为 Windows 服务运行的方法,但都没有成功。我曾编写过几个 Windows 服务来支持各种 CodeProject 进程,因此我决定编写一个实用程序,允许我们安装和运行一个 exe 作为 Windows 服务。这个实用程序名为 Exe2Srvc
。
使用 Exe2Srvc
Exe2Srv 是一个程序,可以作为控制台应用程序运行,也可以安装为 Windows 服务。此应用程序从其 .config 文件中读取可执行文件的路径和命令行参数,然后在新进程中启动该可执行文件。
使用该可执行文件的最简单方法是
- 将 binfiles 下载中的文件,或从编译源代码的 bin/Release 目录中的文件,复制到要作为服务运行的可执行文件所在的目录。
- 编辑 Exe2Srvc.exe.config 中的 "Cmd" 和 "CmdArgs" 值,以包含可执行文件的完整路径和所需的命令行参数。
- 从“以管理员身份运行”命令提示符运行 Install.bat 文件。
- 使用服务管理器
- 将启动模式设置为“自动”
- 设置恢复选项。我通常将它们设置为“重新启动服务”。
- 启动服务。
对于我的测试,我从 Nuget 下载了 Redis,并将解决方案目录下的 /packages/Redis-64.2.6.12.1/tools
中的文件复制到 C:/Redis
。然后,我将 Exe2Srvc\bin\Release
中的文件复制到同一目录。
Exe2Srvc.exe.config 文件包含
<?xml version="1.0" encoding="utf-8" />
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<appSettings>
<!-- set Cmd to the executable file name. -->
<!-- set CmdArg to any command arguments required. -->
<add key="Cmd" value="c:\Redis\redis-server.exe"/>
<add key="CmdArgs" value="c:\Redis\redis.conf --port 6379"/>
</appSettings>
</configuration>
如果可执行文件的路径包含空格,则路径需要用引号括起来。可以通过像下面那样用单引号括起来的双引号字符串来完成此操作。
<?xml version="1.0" encoding="utf-8" />
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
<appSettings>
<!-- set Cmd to the executable file name. -->
<!-- set CmdArg to any command arguments required. -->
<add key="Cmd" value='"c:Program Files\Redis\redis-server.exe"'/>
<add key="CmdArgs" value="c:\Redis\redis.conf --port 6379"/>
</appSettings>
</configuration>
Install.bat
文件必须以管理员身份运行,它使用 SC
命令来安装服务。
sc create Redis binpath= "c:\Redis\Exe2Srvc.exe"
然后,我使用服务管理器配置服务并启动它。

双击 Redis 服务以打开属性编辑器,然后选择“恢复”选项卡。将选项设置为在出现错误时重新启动服务,如图所示。

选择“常规”选项卡。
- 将“启动类型”设置为“自动”,
- 点击“启动”按钮
- 然后点击“确定”按钮。

Redis 现在已安装并作为 Windows 服务运行。使用 redis-cli.exe
测试连接。
Exe2Srvc 的工作原理
创建可作为 Windows 服务运行的控制台应用程序,使用了 Steve Smith 教给我的技术,该技术基于 Einar Egilsson 的文章 “将 Windows 服务作为控制台程序运行”。
基本上,您创建一个控制台应用程序,并将 Program
类更改为继承自 ServiceBase
。在 Main
中,使用 Environment.UserInteractive
属性来确定程序是直接从命令行运行,还是作为服务运行。
所需的命令和命令行参数从 LoadConfiguration
方法读取。
/// <summary>
/// Loads the configuration parameters from the application config file
/// </summary>
private void LoadConfiguration
{
// Load the executable filename and command arguements from config file.
_cmd = ConfigurationManager.AppSettings["Cmd"];
_cmdArgs = ConfigurationManager.AppSettings["CmdArgs"];
if (string.IsNullOrWhiteSpace(_cmd))
throw new Exception("The appsetting 'Cmd' was not defined in the config file.");
}
这从 OnStart
方法调用,OnStart
方法在作为控制台应用程序启动时由 Main
调用,或者在作为服务运行时由 Service
基础结构调用。OnStart 在新 Process
中运行可执行文件,如下所示。
/// <summary>
/// When implemented in a derived class, executes when a Start command is sent to the
/// service by the Service Control Manager (SCM) or when the operating system starts
/// (for a service that starts automatically).
/// Specifies actions to take when the service starts.
/// </summary>
/// <param name="args";>
/// Data passed by the start command.
/// </param>
protected override void OnStart(string[] args)
{
if (Environment.UserInteractive)
{
string message = String.Format"Starting {0} at {1}.", _serviceName, DateTime.Now);
Console.WriteLine(message);
}
// loading the configuration file info here allows the service to be stopped,
// the configuration modified, and the service restarted.
LoadConfiguration();
// Start the executable.
ProcessStartInfo procInfo = new ProcessStartInfo(_cmd);
procInfo.UseShellExecute = false;
if (!string.IsNullOrWhiteSpace(_cmdArgs))
procInfo.Arguments = _cmdArgs;
_process = Process.Start(procInfo);
}
当服务停止时,会调用 OnStop
方法。这会终止 Process
,等待其终止,然后释放 Process
。请确保等待 Process
终止,否则将导致服务停止不当,难以删除和修复。
/// <summary>
/// When implemented in a derived class, executes when a Stop command is sent to the service
/// by the Service Control Manager (SCM). Specifies actions to take when a service stops running.
/// </summary>
/// <remarks>Stops the background tasks.</remarks>
protected override void OnStop()
{
if (Environment.UserInteractive)
{
string message = String.Format("Stopping {0} at {1}.", _serviceName, DateTime.Now);
Console.WriteLine(message);
}
// Kill the process
if (_process != null)
{
_process.Kill();
_process.WaitForExit();
_process.Dispose();
_process = null;
}
}
关注点
我已尽力使其尽可能简单和灵活,但它仅满足我运行 Windows 版 Redis 作为 Windows Server 的原始要求。如果您有其他需求,请随时修改代码以满足您的需求。
历史
这是原始版本。
2014 年 1 月 31 日 - 添加了指定包含空格的可执行文件路径的示例。