我们一般在编写服务器的时候都希望能让服务器在后台运行,而且能记录下这个服务器的pid,防止一个进程重复启动。之前我的方案是自己使用fork函数,将服务器运行成后台模式;并且在启动之前去检查配置文件中指定的pid文件中是否能读出pid信息,并且在当前的ps aux中查找这个pid的进程是否还活着。这样来判定服务器是否已经启动了。当正常启动完毕之后,将会把当前进程的pid写入文件。这样就能防止重复启动了。从刚刚的描述中可以看出其实大多的服务器程序可能需要有以下几个需求:
需要后台运行
需要记录pid方便今后服务器信息的读取
需要防止服务器被错误的重复启动
其实在Linux的基础设施中有这样类似的命令来处理:
$daemon
有了这个活宝,可以减少自己去学习Linux那套daemon方式的编程。在写程序的时候直接实现自己的服务器主流程即可。这种减少掉自己代码中的平台相关的东西还是比较好。能让代码更加清晰。
描述
daemonize可以将一个命令运行成Unix的后台。后台程序是不需要借助终端或者登陆的shell运行在服务器上的,并且等待一些时间的出现,或者等待去执行一些规定的任务在一定周期内。一个典型的后台程序江湖:
关闭全部文件描述字(除开标准输出、输出和错误输出)
将工作目录设置成文件系统的root目录,确保它没有挂载任何其他的文件系统,预防它被卸载
重设他的umask
运行在后台(fork)
分离处理组(通常是一个shell),隔绝掉信号(如挂起信号HUP);
忽略掉全部中断的I/O信号
从中断分离控制权
处理任何SIGCLD信号
选项
-a
挂载到输出文件,而不是冲掉默认值。只有应用了-e and/or -o 被指定的情况。
-e
重定向输出标准错误到指定的文件中,替代/dev/null
-o
重定向输出标准到指定的文件中,替代/dev/null
-E name=value
增加环境变量给给后台程序。这个这个参数类型一定要是name=value格式。参数可以设置多次。
-c directory
定制运行命令前的目录。
-p pidfile
定制自己的pid存放位置。
-l lockfile
单实例启动时将会检查这个文件。
-u user
定制程序以谁的身份运行的。
-v
将会触发daemonize将自己程序的运行详细的日志输出到标准输出中。
注意事项
如果宿主操作系统提供了daemon库程序,daemonize 将会使用它。否则 daemonize将使用自己实现的daemon。这个选择是在编译期做的。
FreeBSD 5.0引入了daemon命令类似于这个命令,但是没有提供如此多的功能。
关于
Brian M. Clapper, bmc@clapper.org
daemonize Home Page: http://software.clapper.org/daemonize/
August 2006
实例
测试代码:
#include
#include
int main( int argn, char *argv[] )
{
int loop_count = 0;
while ( true ) {
loop_count ++;
if ( loop_count > 10 ) {
loop_count = 0;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if ( loop_count == 5 ) {
std::cout << "is normalize output " << std::endl;
}
if ( loop_count == 9 ) {
std::cerr << "is error output" << std::endl;
}
}
return 0;
}
启动的shell
daemonize -a -e /home/abel/test_daemonize/error.log -o /home/abel/test_daemonize/output.log -p /home/abel/test_daemonize/daeminze.pid -l /home/ab el/test_daemonize/lockfile /home/abel/test_daemonize/test_daemonize -c mycfg.cfg
文件列表
test_daemonize]$ ls
daeminze.pid error.log launch.sh lockfile main.cpp main.o output.log SConstruct test_daemonize
pid文件内容
$ cat ./daeminze.pid
11520
日志文件
# output.log
is normalize output
is normalize output
# error.log
is error output
is error output