
可以分三步来做:
做两个简单的守护进程,并能正常运行
监控进程是否在运行
启动进程
综合起来就可以了,代码如下:
被监控进程thisisatest.c(来自http://www.cnblogs.com/ringwang/p/3528093.html):
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>
void init_daemon()
{
int pid
int i
pid=fork()
if(pid<0)
exit(1) //创建错误,退出
else if(pid>0) //父进程退出
exit(0)
setsid()//使子进程成为组长
pid=fork()
if(pid>0)
exit(0)//再次退出,使进程不是组长,这样进程就不会打开控制终端
else if(pid<0)
exit(1)
//关闭进程打开的文件句柄
for(i=0i<NOFILEi++)
close(i)
chdir("/root/test") //改变目录
umask(0)//重设文件创建的掩码
return
}
void main()
{
FILE *fp
time_t t
init_daemon()
while(1)
{
sleep(60)//等待一分钟再写入
fp=fopen("testfork2.log","a")
if(fp>=0)
{
time(&t)
fprintf(fp,"current time is:%s\n",asctime(localtime(&t))) //转换为本地时间输出
fclose(fp)
}
}
return
}
监控进程monitor.c:
#include<unistd.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/param.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<time.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<limits.h>
#define BUFSZ 150
void init_daemon()
{
int pid
int i
pid=fork()
if(pid<0)
exit(1) //创建错误,退出
else if(pid>0) //父进程退出
exit(0)
setsid()//使子进程成为组长
pid=fork()
if(pid>0)
exit(0)//再次退出,使进程不是组长,这样进程就不会打开控制终端
else if(pid<0)
exit(1)
//关闭进程打开的文件句柄
for(i=0i<NOFILEi++)
close(i)
chdir("/root/test") //改变目录
umask(0)//重设文件创建的掩码
return
}
void err_quit(char *msg)
{
perror(msg)
exit(EXIT_FAILURE)
}
// 判断程序是否在运行
int does_service_work()
{
FILE* fp
int count
char buf[BUFSZ]
char command[150]
sprintf(command, "ps -ef | grep thisisatest | grep -v grep | wc -l" )
if((fp = popen(command,"r")) == NULL)
err_quit("popen")
if( (fgets(buf,BUFSZ,fp))!= NULL )
{
count = atoi(buf)
}
pclose(fp)
return count
// exit(EXIT_SUCCESS)
}
void main()
{
FILE *fp
time_t t
int count
init_daemon()
while(1)
{
sleep(10)//等待一分钟再写入
fp=fopen("testfork3.log","a")
if(fp>=0)
{
count = does_service_work()
time(&t)
if(count>0)
fprintf(fp,"current time is:%s and the process exists, the count is %d\n",asctime(localtime(&t)), count) //转换为本地时间输出
else
{
fprintf(fp,"current time is:%s and the process does not exist, restart it!\n",asctime(localtime(&t))) //转换为本地时间输出
system("/home/user/daemon/thisisatest")//启动服务
}
fclose(fp)
}
}
return
}
具体CMD命令:
cc thisisatest.c -o thisisatest
./thisisatest
cc monitor.c -o monitor
./monitor
tail -f testfork3.log -- 查看日志
正常情况下crond是通过/etc/init.d/crond 脚本启动的,他会检查两个文件如果/var/lock/subsys/crond存在说明之前已经有一个crond在运行,那么它会再检查
/var/run/crond.pid,如果该pid代表的进程正在运行,crond 脚本自行退出
反之如果这两个文件中的任何一个被删除或者pid对应进程已经不存在那么它就认为crond没有运行,crond会正常启动,并且生成新的标示文件,这样可以阻止crond再次运行,以达到只有一个crond运行的目的,当然在它正常关闭的情况下,这两个标志文件会被自动删除。
你的情况应该是在前一个crond运行后,要么有人手动直接运行 daemon crond , 要么是这两个标志文件之一被删除或者改动, 后面运行crond脚本运行时检查不到标志文件就正常开启daemon crond
在Linux服务器实际应用中,经常会有需要长时间执行的任务。这类任务若在前台运行,用户无法进行其他 *** 作或者断开与服务器的连接,否则任务将被中止。此时适合使用守护进程。为了使用守护进程,需要了解Linux前台、后台、守护进程的概念与使用,本文将对此进行讲解。
可以看出,”后台任务”与”前台任务”的重要区别: 是否继承标准输入 。所以,执行后台任务的同时,用户还可以输入其他命令。
为了理解守护任务为何在结束session时也不退出,需要先了解Linux下退出session时发生的 *** 作。
Session退出时,linux系统设计如下:
前台任务会随着session的退出而退出是因为它收到了 SIGHUP信号 。
后台任务是否会受到SIGNUP信号,取决于shell的 huponexit 参数。可以通过 $ shopt | grep huponexit 查看该参数的值。大多数Linux系统,这个参数默认关闭(off)。因此,session退出的时候,不会把SIGHUP信号发给”后台任务”,即此时的后台任务是守护进程,但这显然不够安全。并不保险,因为有的系统的 huponexit 参数可能是打开的(on)状态。
更保险的方法是使用 disown命令。它可以将指定任务从”后台任务”列表(jobs命令的返回结果)之中移除 。一个”后台任务”只要不在这个列表之中,session 就肯定不会向它发出SIGHUP信号。
执行上面的命令以后, server.js 进程就被移出了”后台任务”列表。你可以执行 jobs 命令验证,输出结果里面,不会有这个进程。
但是,这样还存在问题。因为 ”后台任务”的标准 I/O 继承自当前 session, disown 命令并没有改变这一点 。一旦”后台任务”读写标准 I/O,就会发现它已经不存在了,所以就 报错终止执行 。 为了解决这个问题,需要对”后台任务”的 标准 I/O 进行重定向 。
这样基本上就没有问题了。
注:
/dev/null 文件的作用
这是一个无底洞,任何东西都可以定向到这里,但是却无法打开。
所以一般很大的stdou和stderr当你不关心的时候可以利用stdout和stderr定向到这里
nohup命令对server.js进程做了三件事。
阻止SIGHUP信号发到这个进程。
关闭标准输入。该进程不再能够接收任何输入,即使运行在前台。
重定向标准输出和标准错误到文件nohup.out。
也就是说,nohup命令实际上将子进程与它所在的 session 分离了。 注意,nohup命令不会自动把进程变为”后台任务”,所以必须加上&符号
守护进程创建方法:
方法一:
方法二:
方法三:
fg、bg、jobs、&、nohup、ctrl+z、ctrl+c 命令
一、&
加在一个命令的最后,可以把这个命令放到后台执行,如:
二、ctrl + z
可以将一个正在前台执行的命令放到后台,并且处于暂停状态。
CTRL+Z 和 CTRL+C的对比
CTRL+Z 和 CTRL+C 都是中断命令,但是他们的作用却不一样.
CTRL+C 是强制中断程序的执行,而 CTRL+Z 的是将任务中断,但是此任务并没有结束,仍然在进程中,只是维持挂起的状态,用户可以使用 fg/bg *** 作继续前台或后台的任务。
三、jobs
查看当前有多少在后台运行的进程
jobs -l选项可显示所有任务的PID,jobs的状态可以是running, stopped, Terminated。但是如果任务被终止了(kill),shell 从当前的shell环境已知的列表中删除任务的进程标识。
四、fg
将后台中的命令调至前台继续运行。如果后台中有多个命令,可以用 fg %jobnumber (jobnumber是命令编号,不是进程号)将选中的命令调出。
五、bg
将一个在后台暂停的命令,变成在后台继续执行。
如果后台中有多个命令,可以用 bg %jobnumber 将选中的命令调出。
六、kill
方法1:通过jobs命令查看job号(假设为num),然后执行
方法2:通过ps命令查看job的进程号(PID,假设为pid),然后执行
前台进程的终止:Ctrl+c
七、nohup
如果想让程序即使在关闭当前的终端后也始终在后台执行(之前的&做不到),需要使用nohup命令。
nohup命令可以在你退出帐户/关闭终端之后继续运行相应的进程。
关闭终端后,在另一个终端jobs已经无法看到后台跑的程序了,此时利用ps(进程查看命令)查看进程。
http://m.2cto.com/os/201301/185701.html
http://www.cnblogs.com/kaituorensheng/p/3980334.html
http://m.blog.csdn.net/article/details?id=50766752
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)