概述
周末还要加班写代码,偷个懒发个刚刚写的守护进程,有一个小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应用开发。欢迎合作。