linux进程监控,重启进程

main.c

#include "process.h"
int main(int argc, char *const *argv)
{
    /*创建一个守护进程*/
    if(creat_daemon() != 1)
    {
        /*创建失败则直接返回*/
        return 1; 
    } 
    else/*在守护进程里面做自己要做的事情*/
    {
        /*进程监控*/
        run_moniter("init.txt");
        /*sleep*/
        for(;;)
        {      
            /*休息1秒*/ 
            sleep(2);
        }
    }
    return 0;
}
#include "process.h"

int exit_flag = 0;
int must_run_size;
struct proc_struct must_run_proc[SIZE];
/*
 * @file      process.c
 * @function  run_moniter
 * @author    酸菜。
 * @date      2021-05-10
*/
void run_moniter(char *Filename)
{
    /*从配置文件当中读取配置信息,存入到must_run_proc
    结构体数组当中,返回值为要监控的进程个数,其中每个
    进程包括了进程ID以及进程名*/
    must_run_size = get_proc(Filename, "aa", must_run_proc, SIZE);
    /*小于0说明没有要监控的进程*/
    if(must_run_size <= 0)
    {
        return;
    }
#if 0
    /*注册信号处理函数,用来闭守护进程*/
    if(signal(SIGINT, exit_proc) == SIG_ERR)
    {
        printf("无法捕捉SIGUSR1信号!\n");
    }
#endif
    /*检测并启动未启动的进程*/
    while(1)
    {
        moniter_run(must_run_proc, must_run_size);
        sleep(2);
    }
    return;
}
/*
 * @file      main.c
 * @function  creat_daemon
 * @author    酸菜。
 * @date      2021-05-10
*/
int creat_daemon()
{
    int  fd;
    /*创建子进程*/
    switch (fork())
    {
    case -1:
        /*创建子进程失败,这里可以写日志*/
        return -1;
    case 0:
        /*子进程,走到这里,直接break*/
        break;
    default:
        /*父进程(没有用了),直接退出*/
        exit(0);         
    }

    /*只有子进程流程才能走到这里脱离终端,
    终端关闭,将跟此子进程无关,设置子进程
    成为一个守护进程*/
    if (setsid() == -1)  
    {
        /*记录错误日志*/
        return -1;
    }

    /*设置为0,不要让它来限制文件权限,以免引起混乱*/
    umask(0); 

    /*打开黑洞设备,以读写方式打开*/
    fd = open("/dev/null", O_RDWR);
    if (fd == -1) 
    {
        /*记录错误日志*/
        return -1;
    }
    /*先关闭STDIN_FILENO[这是规矩,
    已经打开的描述符,动他之前,先close,
    类似于指针指向null,让/dev/null成为标准输入;*/
    if (dup2(fd, STDIN_FILENO) == -1) 
    {
        /*记录错误日志*/
        return -1;
    }
    /*先关闭STDIN_FILENO,类似于指针指向null,让/dev/null成为标准输出*/
    if (dup2(fd, STDOUT_FILENO) == -1) 
    {
        /*记录错误日志*/
        return -1;
    }
    /*fd应该是3,这个应该成立*/
    if (fd > STDERR_FILENO)  
    {
        /*释放资源这样这个文件描述符就可以被复用;不然这个文件描述会被一直占着*/
        if (close(fd) == -1)
        {
            /*记录错误日志*/
            return -1;
        }
    }
    return 1;
}
/*
 * @file      process.c
 * @function  
 * @author    酸菜。
 * @date      2021-05-10
*/
int proc_find(struct proc_struct* src, struct proc_struct* dest)
{
    char buffer[4096], *p, cmd[20];
    int fd, len;

    /*字符串拼接*/
    sprintf(buffer, "%d/stat", src->pid);
    fd = open(buffer, O_RDONLY);
    if(fd == -1)
    {
        return 0;
    }

    memset(buffer, '\0', sizeof(buffer));
    len = read(fd, buffer, sizeof(buffer) - 1);
    close(fd);

    if(len <= 0)
    {
        return 0;
    }

    p = buffer;

    p = strrchr(p, '(');
    {
        char *q = strrchr(p, ')');
        /*进程名称的长度*/
        int len = q - p - 1;
        /*应该不会超过128*/
        if (len >= sizeof(src->process_name))
        {
            len = sizeof(src->process_name) - 1;
        }
        /*把从proc目录下读到的进程名称写入src->process_name*/
        memcpy(src->process_name, p+1, len);
        /*最后一位记得补'\0'*/
        src->process_name[len]= 0;
        /*现在p指向'('的后一位字符*/
        p = q + 1;
    }
    /*两个进程名称进行比较,相等则说明该进程正在运行*/
    return (strcmp(src->process_name, dest->process_name) == 0) ? 1 :0;
}
/*
 * @file      process.c
 * @function  check_proc
 * @author    酸菜。
 * @date      2021-05-10
*/
int check_proc(struct proc_struct* array)
{
    DIR  *dp;
    char *dir = PROCES;
    struct dirent *dirp;
    struct proc_struct* proc;
    struct proc_struct* tmp;

    /*array为空则直接返回*/
    if(array == NULL)
    {
        return 0;
    }

    /*切换到/proc路径*/
    chdir(dir);

    /*读取/proc目录下所有文件夹和文件的信息,
    dp保存所有这些读取到的信息,如果dir是一个
    文件,则直接返回NULL*/
    if((dp = opendir(dir)) == NULL)
    {
        return 0;
    }
    /*循环读取dp读到的信息*/
    while ((dirp = readdir(dp)) != NULL)
    {
        char data[30];
        /*dirp->d_process_name文件夹名称,即进程ID
        保存到data里*/
        sprintf(data, "%s", dirp->d_name);

        /*判断data的内容是否是纯数字*/
        if((strspn(data, "0123456789") == strlen(data)))
        {
            proc = (struct proc_struct *)(malloc(sizeof(struct proc_struct)));
            tmp = proc;
            proc->pid = atoi(dirp->d_name);
            /*判断配置文件里的进程是否在运行*/
            if(proc_find(proc, array))
            {
                printf("进程正在运行!\n");
                return 1;
            }
            free(tmp);
        }
    }
    /*关闭该目录*/
    closedir(dp);
    return 0;
}
/*
 * @file      process.c
 * @function  get_proc
 * @author    酸菜。
 * @date      2021-05-10
*/
int get_proc(unsigned char *pu1Filename, unsigned char *pu1SearchStr, struct proc_struct* array, int size)
{
    FILE            *pFile;
    static   int     nRet = 0;
    unsigned char    au1Buf[80];
    unsigned char    au1ReadStr[80];
    unsigned char    au1StrValue[80];
    unsigned char    au1TmpValue[80];
    unsigned char    *pu1Temp;

    pFile = fopen ((const char*)pu1Filename, "r");

    if ((pFile == NULL) || (size <= 0) || (array == NULL))
    {
        return 0;
    }

    memset(au1Buf, 0, 80);

    while ((!feof (pFile)) && nRet < size)
    {
        fgets (au1Buf, 80, pFile);
        if ((strstr (au1Buf, pu1SearchStr)) != NULL)
        {
            memset (au1ReadStr, 0, 80);
            memset (au1StrValue, 0, 80);
            memset (au1TmpValue, 0, 80);
            sscanf(au1Buf, "%s%s%s", au1ReadStr, au1StrValue, au1TmpValue);
            /*一行一行读取,不是要读取的字符串就直接下一个*/
            if (strcmp (au1ReadStr, pu1SearchStr) != 0)
            {
                continue;
            }
            /*将读取到的value保存到结构体数组当中*/
            if (strlen (au1TmpValue) != 0)
            {
                strcpy (&array->process_name[nRet], au1TmpValue);
            }
            else
            {
                pu1Temp = au1StrValue;
                pu1Temp++;
                strcpy(&array->process_name[nRet], pu1Temp);
            }
            nRet++;
            break;
        }
    }
    fclose (pFile);
    return nRet;
}
/*
 * @file      process.c
 * @function  startProc
 * @author    酸菜。
 * @date      2021-05-10
*/
int startProc(struct proc_struct* proc, int must_run_size)
{
    if(proc == NULL) 
    {
        return 0;
    }

    int pid = fork();

    if(pid == 0)
    {
        pid = fork();
        if(pid == 0)
        {
            execl("/home/txj/test1", (char *)proc->process_name, NULL);
        }
        else
        {
            exit(0);
        }
        sleep(2);
    }
    else
    {
        /*不用关心子进程的退出状态,这里为了
        避免子进程成为僵死进程直接使用NULL即可*/
        wait(NULL);
        sleep(1);
    }

    return 0;
}
/*
 * @file      process.c
 * @function  moniter_run
 * @author    酸菜。
 * @date      2021-05-10
*/
int moniter_run(struct proc_struct *must_run_proc, int proc_size)
{
    int i4Index = 0;
    for(i4Index = 0; i4Index < must_run_size; i4Index++)
    {
        if(check_proc(&(must_run_proc[i4Index])) <= 0)
        {
            startProc(&(must_run_proc[i4Index]), proc_size);
        }
    }
    return 1;
}
/*
 * @file      process.c
 * @function  exit_proc
 * @author    酸菜。
 * @date      2021-05-10
*/
void exit_proc(int sig)
{
    (void)sig;
    kill(getpid(), SIGTERM); 
    exit(0);
}


#ifndef _PROCESS_H_
#define _PROCESS_H_

#include <memory.h>
#include <signal.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>

#define PROCES             "/proc"
#define SIZE               1024
#define MAX_PROC_NAME      80

/*进程结构体定义,保存从配置文件里读到的信息*/
struct proc_struct
{
    char process_name[MAX_PROC_NAME];
    int  pid; 
};

int creat_daemon();
int check_proc(struct proc_struct* array);
int proc_find(struct proc_struct* procl ,struct proc_struct* proc);
int get_proc(unsigned char *pu1FileName, unsigned char *pu1SearchStr, struct proc_struct* array,int size);
int startProc(struct proc_struct* proc, int must_run_size);
int moniter_run(struct proc_struct *must_run_proc, int proc_size);
void run_moniter(char *filename);
void exit_proc(int sig);
#endif

init.txt

aa =test1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值