㈠ 如何编写一个可靠的linux守护进程
// 守护进程(父进程)
int status;
for ( ; ; ) {
if ( 0 == ( pid = fork()) ) {
// 工作进程(子进程)
run();
}
waitpid(-1, &status, 0);
if (WIFEXITED(status))
if (WEXITSTATUS(status) == 0)
exit(0);
if (WIFSIGNALED(status)) {
switch (WTERMSIG(status)) {
case SIGKILL:
exit(0);
break;
case SIGINT:
case SIGTERM:
exit(1);
default:
break;
}
}
}
㈡ Linux 简单的守护进程 程序源代码是什么怎么写
//根据麦子学院视频改编。。。。 #include #include #include #include #include #include #include int main(int argc,char**argv) { int num=0; //sundy print log char content[128]=""; //1,创建一个子进程,退出父进程 pid_t pid=fork(); if(pid0) { exit(0); } //2,设置新的会话 pid_t ret=setsid(); if(ret0) { sprintf(content, "sundy print log = %d\n", num); write(fd,content,strlen(content)); close(fd); } num++; sleep(3); } return 0; }
㈢ linux下守护进程编写问题
因为终端都没了所以才需要重定向
这三个描述符默认是用终端的, 终端没了之后把它们重定向到文件这样它们就仍然可用
所谓“依靠终端才起作用”那是默认情况
㈣ 如何编写linux daemon进程
守护进程的编程要点 :1. 在后台运行。
为避免挂起控制终端将Daemon放入后台执行。方法是在进程中调用fork使父进程终止,让Daemon在子进程中后台执行。
if(pid=fork())
exit(0);//是父进程,结束父进程,子进程继续
2. 脱离控制终端,登录会话和进程组
有必要先介绍一下Linux中的进程与控制终端,登录会话和进程组之间的关系:进程属于一个进程组,进程组号(GID)就是进程组长的进程号(PID)。登录会话可以包含多个进程组。这些进程组共享一个控制终端。这个控制终端通常是创建进程的登录终端。
控制终端,登录会话和进程组通常是从父进程继承下来的。我们的目的就是要摆脱它们,使之不受它们的影响。方法是在第1点的基础上,调用setsid()使进程成为会话组长:
setsid();
说明:当进程是会话组长时setsid()调用失败。但第一点已经保证进程不是会话组长。setsid()调用成功后,进程成为新的会话组长和新的进程组长,并与原来的登录会话和进程组脱离。由于会话过程对控制终端的独占性,进程同时与控制终端脱离。
3. 禁止进程重新打开控制终端
现在,进程已经成为无终端的会话组长。但它可以重新申请打开一个控制终端。可以通过使进程不再成为会话组长来禁止进程重新打开控制终端:
if(pid=fork())
exit(0);//结束第一子进程,第二子进程继续(第二子进程不再是会话组长)
4. 关闭打开的文件描述符
进程从创建它的父进程那里继承了打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。按如下方法关闭它们:
for(i=0;i 关闭打开的文件描述符close(i);>
5. 改变当前工作目录
进程活动时,其工作目录所在的文件系统不能卸下。一般需要将工作目录改变到根目录。对于需要转储核心,写运行日志的进程将工作目录改变到特定目录如/tmpchdir("/")
6. 重设文件创建掩模
进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除:umask(0);
7. 处理SIGCHLD信号
处理SIGCHLD信号并不是必须的。但对于某些进程,特别是服务器进程往往在请求到来时生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为 僵尸进程(zombie)从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将 SIGCHLD信号的操作设为SIG_IGN。
signal(SIGCHLD,SIG_IGN);
这样,内核在子进程结束时不会产生僵尸进程。这一点与BSD4不同,BSD4下必须显式等待子进程结束才能释放僵尸进程。
㈤ linux 如何实现java守护进程编程开发
可以通过GuardServer实现,具体代码如下;
1publicclassGuardServer{
2privateStringservername;
3
4publicGuardServer(Stringservername){
5this.servername=servername;
6}
7
8publicvoidstartServer(Stringcmd)throwsException{
9System.out.println("StartServer:"+cmd);
10//将命令分开
11//String[]cmds=cmd.split("");
12//ProcessBuilderbuilder=newProcessBuilder(cmds);
13
14//
15ProcessBuilderbuilder=newProcessBuilder(newString[]{"/bin/sh","-c",cmd});
16//将服务器程序的输出定位到/dev/tty
17builder.redirectOutput(newFile("/dev/tty"));
18builder.redirectError(newFile("/dev/tty"));
19builder.start();//throwsIOException
20Thread.sleep(10000);
21}
22
23/**
24*检测服务是否存在
25*
26*@return返回配置的java程序的pid
27*@returnpid>0返回的是pid<=0代表指定java程序未运行
28***/
29publicintcheckServer()throwsException{
30intpid=-1;
31Processprocess=null;
32BufferedReaderreader=null;
33process=Runtime.getRuntime().exec("jps-l");
34reader=newBufferedReader(newInputStreamReader(process.getInputStream()));
35Stringline;
36while((line=reader.readLine())!=null){
37String[]strings=line.split("\s{1,}");
38if(strings.length<2)
39continue;
40if(strings[1].contains(servername)){
41pid=Integer.parseInt(strings[0]);
42break;
43}
44}
45reader.close();
46process.destroy();
47returnpid;
48}
49}
㈥ 如何以守护进程在linux系统下执行
编写守护进程程序的要点:
(1)让程序在后台执行。方法是调用fork()产生一个子进程,然后使父进程退出。
(2)调用setsid()创建一个新对话期。控制终端、登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响,方法是调用setsid()使进程成为一个会话组长。setsid()调用成功后,进程成为新的会话组长和进程组长,并与原来的登录会话、进程组和控制终端脱离。
(3)禁止进程重新打开控制终端。经过以上步骤,进程已经成为一个无终端的会话组长,但是它可以重新申请打开一个终端。为了避免这种情况发生,可以通过使进程不再是会话组长来实现。再一次通过fork()创建新的子进程,使调用fork的进程退出。
(4)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。首先获得最高文件描述符值,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符。
(5)将当前目录更改为根目录。
(6)子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权。为防止这一点,使用unmask(0)将屏蔽字清零。
(7)处理SIGCHLD信号。对于服务器进程,在请求到来时往往生成子进程处理请求。如果父进程不等待子进程结束,子进程将成为僵尸进程(zombie),从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。这样,子进程结束时不会产生僵尸进程。
㈦ linux 进程守护程序怎么写
守护进程及其特性
(1)守护进程最重要的特性是后台运行。在这一点上DOS下的常驻内存程序TSR与之相似。
(2)其次,守护进程必须与其运行前的环境隔离开来。这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建掩模等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的。
(3)最后,守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(通常是 shell)执行。
总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。
因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。
㈧ linux守护进程的几个关键地方
创建一个守护进程,有几个关键的步骤,也有几个地方需要注意,
几个关键的步骤有:
1:清除文件创建权限
2:调用fork,然后使父进程退出
3:调用setsid以创建一个新的会话,有三个目的使调用进程 a:成为新会话的首进程,b:成为新进程的组长进程,c:没有控制终端
4:切换工作目录
5:关闭不需要的文件描述符
㈨ linux编写一个程序,要求运行后成为守护进程,每隔3秒修改一个本机的IP地址,并在屏幕上显示IP地址信息。
守护进程与终端已经脱离关系,无法把输出打印到屏幕上,一下代码可以帮你实现这个功能,需要在终端上使用ifconfig命令查看ip的变化
执行的时候需要使用超级用户权限,因为修改ip需要超级用户权限才能修改
需要有一个/tmp/ip_list.txt文件,每行存储一个需要改变的ip地址,例如:
192.168.1.2
192.168.1.3
192.168.1.4
192.168.1.5
192.168.1.6
192.168.1.7
192.168.1.8
192.168.1.9
192.168.1.10
代码如下:
#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <signal.h>void sigterm_handler(int arg){exit(1);}int main(int argc, char * argv[]){pid_t pid;FILE *fp;char line[128];char cmd[128];pid = fork();if (pid < 0) {perror("fork error");exit(-1);} else if (pid > 0) {/* father */printf("father die\n");exit(-1);}/* child */if (setsid() == -1)perror("setsid() error");if (chdir("/") == -1)perror("chdir error");printf("child: pid = %d\n", getpid());signal(SIGTERM, sigterm_handler);fp = fopen("/tmp/ip_list.txt", "r");if (fp == NULL) {perror("fopen");exit(-1);}umask(0);close(STDIN_FILENO);close(STDOUT_FILENO);close(STDERR_FILENO);while (1) {memset(line, 0, sizeof(line));if (NULL == fgets(line, sizeof(line) - 1, fp)) {rewind(fp);continue;}/* check ip format here if nessesary *//* ... */memset(cmd, 0, sizeof(cmd));snprintf(cmd, sizeof(cmd) - 1, "ifconfig eth0 %s", line);system(cmd);sleep(3);}fclose(fp);return 0;}
㈩ 写一个linux下写个关于c语言的双守护进程,就是监视一个进程,当其死掉,马上将其重启
可以分三步来做:
做两个简单的守护进程,并能正常运行
监控进程是否在运行
启动进程
综合起来就可以了,代码如下:
被监控进程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=0;i<NOFILE;i++)
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 ",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=0;i<NOFILE;i++)
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 ",asctime(localtime(&t)), count); //转换为本地时间输出
else
{
fprintf(fp,"current time is:%s and the process does not exist, restart it! ",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 -- 查看日志