linux守护程序

概述

周末还要加班写代码,偷个懒发个刚刚写的守护进程,有一个小bug懒得处理,急着要用,发出来记录一下成果。

守护程序

网上很多介绍的,大家有兴趣自己去查查

上酸菜

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

#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>

#define MAX_FILE_LEL 1024
#define MAX_FILE_SIZE 30

#define MAXFILE 65535
volatile sig_atomic_t _running = 1;

#define WATCH_PROCESS_NAME "IPSound"
#define DEAMON_NAME "IPSDeamon"

char *Primary_Program = "./IPSound &";

int logMsgFD;
void writeLogger(const char* msg){
    if (logMsgFD <= 0){
        return ;
    }

    write(logMsgFD, msg, strlen(msg));
    write(logMsgFD, "\n",1);
}
// 拦截中断信息,确保程序退出时释放资源
void sigterm_handler(int arg)
{
    _running = 0;
}

void killProcess(char *processName)
{
    FILE *sp = NULL;
    char cmd[128];
    memset(cmd, 0, sizeof(cmd));
    sprintf(cmd, "killall %s ", processName); // task_name 替换为需要结束的进程名称
    sp = popen(cmd, "r");
    if (sp == NULL)
    {
        return;
    }
    pclose(sp);
}

void updateProgram(char *fileNamesrc)
{
    // write(fd, "updateProgram", sizeof("updateProgram"));
    FILE *sp = NULL;
    char cmd[128];
    memset(cmd, 0, sizeof(cmd));
    sprintf(cmd, "mv %s ./ ", fileNamesrc); // task_name 替换为需要结束的进程名称

    sp = popen(cmd, "r");
    if (sp == NULL)
    {
        // write(fd, "update failed", sizeof("update failed"));
        return;
    }
    pclose(sp);
    // write(fd, "update success", sizeof("update success"));
}

int find_files(const char *path, char *dirs)
{
    struct dirent *entry;
    DIR *dp;
    struct stat statbuf;

    dp = opendir(path);
    if (dp == NULL)
    {
        perror("opendir");
        exit(EXIT_FAILURE);
    }
    int index = 0;
    while ((entry = readdir(dp)))
    {
        if (entry->d_type == DT_REG)
        { // 普通文件
            char filename[256];
            snprintf(filename, sizeof(filename), "%s/%s", path, entry->d_name);
            if (stat(filename, &statbuf) == -1)
            {
                perror("stat");
                continue;
            }
            // printf("Found regular file: %s\n", filename);
            dirs += index * MAX_FILE_LEL;
            memcpy(dirs, filename, sizeof(filename));
            index++;
        }
    }
    closedir(dp);

    return index;
}

int get_pid_by_name(const char *process_name)
{
    char cmd[256];
    char buf[1024];
    int pid = -1;
    FILE *fp;

    // 构造命令
    snprintf(cmd, sizeof(cmd), "pidof %s", process_name);

    // 执行命令并打开管道
    fp = popen(cmd, "r");
    if (fp == NULL)
    {
        perror("popen failed:");
        return -1;
    }

    // 读取输出结果
    while (fgets(buf, sizeof(buf), fp) != NULL)
    {
        pid = atoi(buf);
        break; // 假设只有一个进程,所以获取第一个ID即可
    }

    // 关闭管道
    pclose(fp);

    return pid;
}

int is_daemon_running(const char *daemon_name) {
    FILE *fp;
    char buffer[256];
    int daemon_running = 0;
 
    // 使用ps命令列出所有进程
    fp = popen("ps aux", "r");
    if (fp == NULL) {
        printf("Failed to run ps command.\n");
        return 0;
    }
 
    // 读取ps命令的输出
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
        // 查找守护进程名称
        if (strstr(buffer, daemon_name) != NULL) {
            daemon_running = 1;
            break;
        }
    }
 
    pclose(fp);
    return daemon_running;
}
 
 
int main()
{
    const char *process_name = "IPSDeamon";
    pid_t currentPID = getpid();
    //判断守护进程是否已经运行
    int pidDeamonPID = get_pid_by_name(process_name);
    if (pidDeamonPID > 0 && pidDeamonPID != currentPID){
        printf("已经启动了守护程序: %d",currentPID);
        return;
    }

    // 初始化日志
    if ((logMsgFD = open("/tmp/ipsound.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0)
    {
        printf("日志文件打开失败 \n");
        exit(1);
    }

    writeLogger("启动守护程序");

    pid_t pc;
    int i, len;
    pc = fork();

    

    // 出错退出
    if (pc < 0)
    {
        writeLogger("守护创建失败");
        exit(1);
    }
    else if (pc > 0) // 主进程退出
        exit(0);

    // 脱离终端控制
    setsid();

    char cwd[256];
    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        writeLogger("当前工作目录为");
        writeLogger(cwd);
        writeLogger("\n");
    }
    chdir(cwd);
    umask(0);
    // 关闭标准输出
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);

    // 注册中断信息
    signal(SIGTERM, sigterm_handler);

    writeLogger("守护进程创建成功");

    while (_running)
    {
        writeLogger("检查是否有升级文件");
        // 查找 Update目录是否有升级文件
        char files[MAX_FILE_SIZE][MAX_FILE_LEL] = {{0}};
        int count = find_files("./update", files);
        if (count > 0)
        {
            writeLogger("... ...发现升级文件---准备升级");
            //printf("-----------------> 重新启动进程 <--------------------------");

            writeLogger("... ...终止当前业务程序IPSound");
            // 终止当前程序
            killProcess(WATCH_PROCESS_NAME);

            writeLogger("... ...执行升级");
            for (int i = 0; i < count; i++)
            {
                printf(files[i]);
                printf("\n");
                // 将升级程序拷贝到当前目录
                updateProgram(files[i]);
            }

            // 重新启动进程
            writeLogger("重新启动业务程序");
            int val = system(Primary_Program); 

            writeLogger("升级完毕");
        }
        else
        {
            writeLogger("检查业务程序是否退出");

            // 检查进程是否正常工作
            int pid = get_pid_by_name(WATCH_PROCESS_NAME);
            printf("enter sub process 10 = %d\n", pid);
            if (pid == -1)
            {
                writeLogger("... ...业务程序已退出,启动业务程序");
                int val = system(Primary_Program); 
                writeLogger("... ...异常处理结束");
            }
            else
            {
                
            }
        }

        // 循环等待
        usleep(1000*1000*10);
    }
    printf("exit .....");
    close(logMsgFD);
}

我公司承接各类技术服务,主要聚焦于:stm32、单片机、嵌入式、QT应用开发、Web+Python+Django应用开发。欢迎合作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/444202.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录刷题笔记-Day32

1. 最大子序和 53. 最大子数组和https://leetcode.cn/problems/maximum-subarray/ 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组&#xff1a;是数组中的一个连续…

Java学习笔记NO.18

T1.理工超市 &#xff08;1&#xff09;题目描述 编写一个程序&#xff0c;设计理工超市功能菜单并完成注册和登录功能的实现。显示完菜单后&#xff0c;提示用户输入菜单项序号。当用户输入<注册>和<登录>菜单序号时模拟完成注册和登录功能&#xff0c;最后提示…

多态的原理

通过监视可以发现&#xff0c;基类和子类的虚表指针指向的是不同的虚表&#xff08;监视窗口可以证实&#xff09;&#xff0c;而且虚表里面的函数地址也是不一样的。这就符合我们的预期了&#xff0c;因为多态的调用的时候&#xff0c;就是通过虚表指针去找到对应虚表里面的虚…

蓝桥杯练习系统(算法训练)ALGO-981 过河马

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 在那个过河卒逃过了马的控制以超级超级多的走法走到了终点之后&#xff0c;这匹马表示它不开心了……   于是&#xff0c…

[2024-03-09 19:55:01] [42000][1067] Invalid default value for ‘create_time‘【报错】

这个错误可能是因为你的 MySQL 数据库版本不支持 CURRENT_TIMESTAMP 作为默认值。在一些早期版本中&#xff0c;MySQL 对 TIMESTAMP 类型字段的默认值设置有限制&#xff0c;只允许使用特定的常量值&#xff08;如 0000-00-00 00:00:00 或 CURRENT_TIMESTAMP()&#xff09;。如…

王道机试C++第 4 章 字符串:字符串内容续写几个小程序 Day30

统计字符 习题描述 统计一个给定字符串中指定的字符出现的次数。 输入描述&#xff1a; 测试输入包含若干测试用例&#xff0c;每个测试用例包含2行&#xff0c;第1行为一个长度不超过5的字符串&#xff0c;第2行为一个长度不超过80的字符串。注意这里的字符串包含空格&…

浅述字典攻击

一、前言 字典攻击是一种常见的密码破解方法&#xff0c;它使用预先编制的字典文件作为攻击字典&#xff0c;通过尝试猜测密码的方式来破解密码。下面是一个关于字典攻击的博客&#xff0c;希望能够为您了解字典攻击提供帮助。 二、字典攻击概述 字典攻击是一种密码破解方法&…

poetry库:依赖管理和打包工具

这个工具是在群里看见别人说好用的&#xff0c;所以了解一下。 1.poetry初始 官网&#xff1a;https://python-poetry.org/ 项目仓库&#xff1a;https://github.com/python-poetry 或 https://github.com/python-poetry/poetry 教程&#xff1a;https://python-poetry.org/…

为什么网络安全人才缺口这么大,但还是有很多人找不到工作?

为什么央视说到2027年我国网络安全人员缺口达327万&#xff0c;但是还是有很多人找不到工作。 今年大家听到“就业大环境很差”、“工作不好找”之类的太多了。如今大环境已经逐渐好转&#xff0c;虽然不需要太过焦虑&#xff0c;但是也要持续的提升自己。 最近有听华为的渗透…

杨辉三角(C语言)

杨辉三角 一.什么是杨辉三角 一.什么是杨辉三角 每个数等于它上方两数之和。 每行数字左右对称&#xff0c;由1开始逐渐变大。 第n行的数字有n项。 前n行共[(1n)n]/2 个数。 … 当前行的数上一行的数上一行的前一列的数 void yanghuisanjian(int arr[][20], int n) {for (int i…

SpringBoot源码

SpringBoot核心前置内容 1.Spring注解编程的发展过程 1.1 Spring 1.x 2004年3月24日&#xff0c;Spring1.0 正式发布&#xff0c;提供了IoC&#xff0c;AOP及XML配置的方式。 在Spring1.x版本中提供的是纯XML配置的方式&#xff0c;也就是在该版本中必须要提供xml的配置文件…

夏泽网注册码

夏泽网注册码申请法:1.打开注册码申请页&#xff0c;http://nianjian.xiaze.com/getcode.php 上面会显示你的注册码链接 (是个红色的链接,不同的时间不同的人这个链接不一样)。 2.将注册码链接以超链接的方式发布在各大网站、论坛、博客&#xff08;支持各大论坛、百度空间、 网…

117.龙芯2k1000-pmon(16)- linux下升级pmon

pmon的升级总是有些不方便&#xff0c;至少是要借助串口和串口工具 如果现场不方便连接串口&#xff0c;是不是可以使用网线升级pmon呢&#xff1f; 答案当然是可行的。 环境&#xff1a;2k1000linux3.10麒麟的文件系统 如今我已经把这个工具开发出来了。 GitHub - zhaozhi…

如何开通 GitHub Sponsors

Github Sponsors 是什么&#xff1f; 简单来说&#xff0c;GitHub Sponsors 是一个赞助服务&#xff0c;它允许个人和组织直接向开源贡献者和项目提供财务赞助&#xff0c;以便于有更多的时间和资源来专注于自己的开源工作。 这对于开源贡献者来说是非常棒&#x1f389;的&…

Swift 入门学习:集合(Collection)类型趣谈-下

概览 集合的概念在任何编程语言中都占有重要的位置&#xff0c;正所谓&#xff1a;“古来聚散地&#xff0c;宿昔长荆棘&#xff1b;游人聚散中&#xff0c;一片湖光里”。把那一片片、一瓣瓣、一粒粒“可耐”的小精灵全部收拢、吸纳的井然有序、条条有理&#xff0c;怎能不让…

008-slot插槽

slot插槽 1、插槽 slot 的简单使用2、插槽分类2.1 默认插槽2.2 具名插槽2.3 作用域插槽 插槽就是子组件中的提供给父组件使用的一个占位符&#xff0c;用<slot></slot> 表示&#xff0c;父组件可以在这个占位符中填充任何模板代码&#xff0c;如 HTML、组件等&…

【Docker】容器的生态系统

Docker提供了一整套技术支持&#xff0c;包括核心技术、平台技术、支持技术。 核心技术 容器核心技术是指能让Container&#xff08;容器&#xff09;在host&#xff08;集群、主机&#xff09;上运行起来的那些技术。 1&#xff09;容器规范&#xff1a;OCI&#xff08;runt…

round四舍五入在python2与python3版本间区别

round()方法返回数值的小数点四舍五入到n个数字。 语法 以下是round()方法的语法&#xff1a; round( x ,n) 参数 x --这是一个数值&#xff0c;表示需要格式化的数值 n --这也是一个数值,表示小数点后保留多少位 返回值 该方法返回 数值x 的小数点四舍五入到n个数字 …

计算机设计大赛 疲劳驾驶检测系统 python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…

图|dfs bfs|最小生成树|最短路|一篇搞定图的所有知识点

文章目录 图前言项目代码仓库图的基本概念图的表示方法邻接矩阵邻接表图的一些相关概念 图的遍历bfsdfs如果给的图不是连通图&#xff1f; 最小生成树Kruskal算法Prim算法 最短路径单源最短路径--Dijkstra算法单源最短路径--Bellman-Ford算法多源最短路径--Floyd-Warshall算法 …