在Windows平台上运行后台进程需要运行Windows服务。而要运行Windows服务,你就必须有能够感知Windows服务的程序。Bash脚本无法感知Windows服务,许多控制台程序同样也不能。而且,将这些程序转变为Windows服务也不可行。
没有附加的程序,想把控制台程序作为服务来运行是非常复杂的。Microsoft在其Resource Toolkit产品中提供了一个程序,可以将控制台程序转变为Windows服务。但遗憾的是,Resource Toolkit并不是免费的午餐。
但是,开源程序XYNTService却为我们提供了一个免费的方案,借助该程序,治理员可以定义执行控制台程序和及其设置。XYNTService程序是一个Windows服务,它通过读取设置文件来获悉执行哪些程序。
本文摘自最新出版的“Open Source For Windows Administrators”一书。在Code Project网站可以下载XYNTService程序(用户下载源代码和程序时需要进行注册)。
下载的压缩包内包含一个名为XYNTService.exe的可执行文件。将此文件复制到预备作为XYNTService程序目录的目录内,然后执行XYNTService.exe -i命令即可安装该服务。执行XYNTService.exe –u可移除该服务。
当作为Windows服务安装XYNTService程序时,切记要以特定的用户来运行该服务。因为一些控制台程序可能需要读取用户环境变量或文件,而本地系统帐户不具备这些属性。
在启动XYNTService时,程序会在其所在的目录内查找XYNTService.ini文件。下面是配置文件的一个实例:
[Settings]
ServiceName = XYNTService
ProcCount = 2
CheckProcess = 30
[Process0]
CommandLine =
c:\bin\unison.exe -socket 8118
WorkingDir = c:PauseStart = 1000
PauseEnd = 1000
UserInterface = No
Restart = Yes
[Process1]
CommandLine = C:\j2sdk1.4.1
05\bin\Java.exe -ms1m -cp . scache
WorkingDir = c:\bin\scache
PauseStart = 1000
PauseEnd = 1000
UserInterface = No
Restart = Yes
在上面的配置文件实例中,有两个主要的类型区域:Settings和其它区域(Process0和Process1)。Settings区域涵盖有关XYNTService程序的所有主要的全局定义。其它区域则定义XYNTService运行时启动的每个进程。Settings区域设置项目如下:
ServiceName:用来设置XYNTService服务的名称。通过修改此名称,治理员可以安装多个XYNTService服务。
ProcCount:设定启动进程的数目。该项设置主要针对XYNTService程序,依据该值来确定处理ProcessX部分的最大进程数。在本例中,该值为2,表示Process0和Process1部分必然存在。
CheckProcess:该值指定XYNTService检查启动进程是否处于活动状态的时间间隔。假如该值为0,则表示不检查;为其它值时,进程会被重启。假如该值有效并且ProcessX区域的Restart项设置为答应重启,当发生进程死亡时,XYNTService将重新启动该进程。请谨慎设置该选项,因为假如设置不正确,进程将不停的死亡和重启,从而可能导致计算机根本无法工作。
每个进程都对应着一个Process[n]区域,在本例中包括Process0和Process1两个区域。每个进程设置区域包含如下定义项:
CommandLine:定义启动该进程所执行的命令行。切记要使用完整路径。
WorkingDir:定义启动进程的工作目录。
PauseStart:指定XYNTService服务在启动当前进程后暂停的时间(以毫秒为单位)。对于XYNTService服务来说,所有的动作就是等待设定的时间长度,然后才开始启动下一个进程。
PauseEnd:指定强制终止进程前的等待时间(以毫秒为单位)。当XYNTService关闭时,它会向进程发送退出消息,而PauseEnd值就是设定XYNTService在发送退出消息之后所等待的时间。在等待时间结束后,进程会被强行关闭。
UserInterface:指定XYNTService创建的进程是否可与登陆用户互动。而这仅在本地系统帐户下时才起作用。请注重,当使用本地系统帐户时,My Documents目录是不存在的,对于一些假定My Documents目录存在的控制台程序,这将导致一些问题。
Restart:指定在进程死亡时是否重启该进程。
重启进程
当在XYNTService中运行脚本时,你可能会碰到问题。例如,一个脚本运行了另外一个进程,它在等待结束该进程。当SYNTService关闭时,它会发送WM QUIT消息。Cygwin Bash shell无法捕捉该WM QUIT消息,所以该shell将会被强行终止。
当XYNTService再次启动时,老进程却已经在运行了。无法捕捉WM QUIT消息的问题不仅存在于Bash shell中,Windows批处理进程也同样有类似的问题。
解决方法是修改脚本,以便在启动新进程前停止所有已运行的老进程。下面的脚本说明如何发现老进程,并且使用PSTools来停止它们:
#!/bin/bash
pslist grep $procIdentifier
awk '{print $2}' > /tmp/pids.txt
exec 3<&0
exec < /tmp/pids.txt
while read line
do
pskill $line
done
exec <&3
exec 3<&-
rm /tmp/pids.txt
该脚本通过pslist命令列出所有正在运行的进程。进而在结果集合中,使用grep命令搜索$procIdentifier变量所标识的进程ID。搜索到的结果随后被awk命令处理,进而得到进程ID。
得到的进程ID被保存在pids.txt文件中,该文件随后会被加载和重写。每次重写都包含所发现的、需要使用pskill命令停止的、进程的ID。最后,pids.txt文件被删除。
上面的脚本代码可以确保停止老进程。你还可以使用kill命令发送一个特定的信号。请注重,PauseStart项应该指定停止已有进程所需的时间。
重启服务和XYNTService
XYNTService可执行程序不仅是一个可执行的Windows服务,它还是一个可以本地启动和停止服务,以及重启特定XYNTService服务的控制程序。要重启本例中ProcessX区域中的第二个进程,可执行如下命令:
XYNTService.exe -b 2
执行以下命令可以停止名为Apache的服务:
XYNTService -k Apache
执行以下命令可以运行名为Apache的服务:
XYNTService -r Apache