【Linux】记录错误信息日志的实现

news2024/11/28 22:48:45

文章目录

  • 前言
  • 一、 目录实现(log.hpp)
  • 二、目录的具体使用
    • 1.comm.hpp(管道初始化)
    • 2.sever.cpp(为读端且令其创建命名管道)
    • 3.client.cpp(为写端)


前言

在这里插入图片描述

我们这个设计的日志可以自定以输出的方向,可以向显示器打印错误信息,也可以向指定目录写入,或者是分类写入

一、 目录实现(log.hpp)

#pragma once

#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

#define SIZE 1024

//对错误等级进行分级
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4

//将错误信息打入到什么位置
#define Screen 1
#define Onefile 2
#define Classfile 3

//存储错误信息的文件默认名字
#define LogFile "log.txt"
using namespace std;


class Log{
public:
Log(){
    //默认打印方式往显示屏
    //规定好默认路径
    printMethod=Screen;
    path="./log/";
}


//自己改变默认答应方式
void Enable(int method){
    printMethod=method;
}


//将错误等级转换为字符串的形式
string levelTostring(int level){
    switch(level){
        case Info:
            return "Info";
        case Debug:
            return "Debuf";
        case Warning:
            return "Warning";
        case Error:
            return "Error";
        case Fatal:
            return "Fatal";
        default:
            return "None";
    }
}


//根据传出的信息,生成字符串logtxt,这个字符串中就是错误信息

void operator()(int level, const char *format, ...)
    {
        //报错信息 格式:默认部分+自定义部分
        time_t t = time(nullptr);
        struct tm *ctime = localtime(&t);
        char leftbuffer[SIZE];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelTostring(level).c_str(),
                 ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
                 ctime->tm_hour, ctime->tm_min, ctime->tm_sec);

        va_list s;
        va_start(s, format);
        //leftbuffer为获取的报错时间字符串,为默认部分

        //rightbuffer为我们的自定义部分
        char rightbuffer[SIZE];
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
        va_end(s);

         
         //将leftbuffer 与rightbuffer合并成字符串logtxt
         //这就是我们的报错的错误信息
        char logtxt[SIZE * 2];
        snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);

        
        //将错误信息按指定方式打印到指定地方
        printLog(level, logtxt);
    }

//将错误信息按指定方式打印到指定地方
void printLog(int level,const string &logtxt){
    switch(printMethod){
        case Screen://打印到屏幕
            cout<<logtxt<<endl;
        case Onefile://打印到一个文件
            printOnefile(LogFile,logtxt);
            break;
        case Classfile://分错误信息打印到不同文件
            printClassfile(level,logtxt);
            break;
        default :
            break;
    }
}



void printOnefile(const string logname,const string logtxt){
    // printOnefile(LogFile,logtxt);
    string _logname=path+logname;  // ./log/log.txt
    int fd=open(_logname.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);
    if(fd<0)
        return;
    write(fd,logtxt.c_str(),logtxt.size());
    close(fd);
}

void printClassfile(int level,const string logtxt){
    // printClassfile(level,logtxt);
    string filename=LogFile;
    filename+=".";
    filename+=levelTostring(level);
    //  log.txt. (string)level

    //设置好文件名字后,再用单文件的打印方式写入文件
    printOnefile(filename,logtxt);
}

private:
int printMethod;//打印方法
string path;//打印路径
};

二、目录的具体使用

这里我们以命名管道之间两个进程传递信息为场景使用这个日志功能

1.comm.hpp(管道初始化)

 #pragma once
 #include<iostream>
 #include<string>
 #include<sys/types.h>
 #include<sys/stat.h>
#include<unistd.h>
#include<cerrno>
#include<string.h>
#include<fcntl.h>

//命名管道的名字与路径
 #define FIFO_FILE "./myfifo"
 #define MODE 0664

//返回的错误码
 enum{
    FIFO_CREAT_ERR=1,
    FIFO_DELETE_ERR,
    FIFO_OPEN_ERR
 };

//采用Init类,类似智能指针,我们在析构函数中调用删除命名管道的函数
//程序结束会自动调用析构函数
class Init{
public:
    Init(){
        int n=mkfifo(FIFO_FILE,MODE);
        if(n==-1){
            perror("mkfifo");
            exit(FIFO_CREAT_ERR);
        }

    }

    ~Init(){
        int m=unlink(FIFO_FILE);
        if(m==-1)
        {
            perror("unlink");
            exit(FIFO_DELETE_ERR);
        }
    }


};

2.sever.cpp(为读端且令其创建命名管道)

#include "comm.hpp"
#include "log.hpp"

using namespace std;

// 管理管道文件
int main()
{
    Init init;//创建命名管道
    Log log;
    
    log.Enable(Onefile);//重定向错误信息打入位置

    // 打开管道
    int fd = open(FIFO_FILE, O_RDONLY);  
    if (fd < 0)
    {
        //如果有错就打印错误信息
        log(Fatal, "error string: %s, error code: %d", strerror(errno), errno);
        exit(FIFO_OPEN_ERR);
    }

    log(Info, "server open file done, error string: %s, error code: %d", strerror(errno), errno);
    log(Warning, "server open file done, error string: %s, error code: %d", strerror(errno), errno);
    log(Fatal, "server open file done, error string: %s, error code: %d", strerror(errno), errno);
    log(Debug, "server open file done, error string: %s, error code: %d", strerror(errno), errno);


    // 开始通信
    while (true)
    {
        char buffer[1024] = {0};
        int x = read(fd, buffer, sizeof(buffer));
        if (x > 0)
        {
            buffer[x] = 0;
            cout << "client say# " << buffer << endl;
        }
        else if (x == 0)
        {
            log(Debug, "client quit, me too!, error string: %s, error code: %d", strerror(errno), errno);
            break;
        }
        else
            break;
    }

    close(fd);
    return 0;
}

3.client.cpp(为写端)

 #include <iostream>
#include "comm.hpp"

using namespace std;

int main()
{
    int fd = open(FIFO_FILE, O_WRONLY);//打开管道
    if(fd < 0)
    {
        perror("open");
        exit(FIFO_OPEN_ERR);
    }

    cout << "client open file done" << endl;

    string line;
    while(true)
    {
        cout << "Please Enter@ ";
        getline(cin, line);//因为可能有空格,cin不读入空格

        write(fd, line.c_str(), line.size());
    }

    close(fd);
    return 0;
}

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

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

相关文章

echart一键生成迁徙图

echart_move 介绍 echart迁徙图&#xff0c;选择起点和目的地生成迁徙图 软件架构 html echarts js 使用说明 将文件放到同一目录下打开index.html即可 默认是小飞机图标&#xff0c;如果想修改图标&#xff0c;将图片放到同一目录&#xff0c;如1.svg 代码修改为对应位…

windows本地dockr的clickhouse链接本地mysql服务,连接不上

不想看过成的&#xff0c;解决办法在最后面 报错信息&#xff1a; SQL 错误 [1000] [08000]: Poco::Exception. Code: 1000, e.code() 0, Exception: Connections to all replicas failed: test1localhost:3306 as user root (version 21.12.3.32 (official build)) , serve…

使用Selenium、Python和图鉴打码平台实现B站登录

selenium实战之模拟登录b站 基础知识铺垫&#xff1a; 利用selenium进行截图&#xff1a; driver.save_screenshot() 注意图片文件名要用png结尾. 关于移动&#xff1a; ActionChains(bro).move_to_element_with_offset()# 对于某个图像ActionChains(bro).move_by_offset(…

敢做敢当——歌手荆涛与歌曲《敢做敢当》的精神内核

在人生的道路上&#xff0c;多少次我们渴望前方&#xff0c;梦想在远方熠熠生辉&#xff0c;然而等待我们的&#xff0c;却往往是昨日的辉煌。面对这样的境遇&#xff0c;我们应该如何选择&#xff1f;荆涛的歌曲《敢做敢当》给出了我们一个明确的答案。 一、风中伫立&#xff…

LeetCode198.打家劫舍

打家劫舍和背包问题一样是一道非常经典的动态规划问题&#xff0c;只要做过几道动态规划的题&#xff0c;这道题简直就非常容易做出来。我应该花了10来分钟左右就写出来了&#xff0c;动态规划问题最重要的就是建立状态转移方程&#xff0c;就是说如何从上一个状态转移到下一个…

Matlab数学建模算法详解之混合整数线性规划 (MILP) 算法(附完整实现代码)

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

Python 进阶(十一):高精度计算(decimal 模块)

《Python入门核心技术》专栏总目录・点这里 文章目录 1. 导入decimal模块2. 设置精度3. 创建Decimal对象4. 基本运算5. 比较运算6. 其他常用函数7. 注意事项8. 总结 大家好&#xff0c;我是水滴~~ 在进行数值计算时&#xff0c;浮点数的精度问题可能会导致结果的不准确性。为了…

【研究中】sql server权限用户设置23.11.26

--更新时间2023.11.26 21&#xff1a;30 负责人&#xff1a;jerrysuse DBAliCMSIF EXISTS (select * from sysobjects where namehkcms_user)--判断是否存在此表DROP TABLE hkcms_user CREATE TABLE hkcms_user (id int primary key identity(1, 1),username char(32) NOT N…

【多线程】-- 03 龟兔赛跑案例线程创建方法之三:Callable接口

多线程 2 线程创建 【续】2.2 龟兔赛跑案例 首先需要一个赛道距离&#xff0c;然后会距离终点越来越近判断比赛是否结束打印出胜利者龟兔赛跑开始故事中是乌龟获胜&#xff0c;兔子需要睡觉&#xff0c;所以要模拟兔子睡觉最终&#xff0c;乌龟赢得比赛 package com.duo.de…

【Spring MVC】Filter 过滤器异常处理 HandlerExceptionResolver 分析

文章目录 前言版本说明测试 Demo1、自定义过滤器 DemoFilter2、自定义业务异常 ServiceException3、自定义异常处理类 DemoExceptionHandler4、DemoController5、请求测试 问题分析1、日志打印记录2、Debug 方法 解决方案1、修改自定义过滤器2、请求测试 解决方案分析1、日志打…

Linux uname命令教程:如何打印linux操作系统名称和硬件的基本信息(附实例教程和注意事项)

Linux uname命令介绍 uname命令是一个在Linux中常用的命令行工具&#xff0c;用于打印有关操作系统名称和系统硬件的基本信息。uname这个名字来源于"UNIX name"。它最常用于确定处理器架构&#xff0c;系统主机名和系统上运行的内核版本。 Linux uname命令适用的Li…

Ceph的监控工具Dashboard安装部署,详细实战过程

Ceph的监控工具Dashboard安装部署 还是用之前的集群&#xff0c;老规矩&#xff0c;没有主机名的是所有节点都执行 安装mgr-dashboard&#xff0c;每个节点都要安装 yum install -y ceph-mgr-dashboard开启MGR的功能 ceph mgr module enable dashboard查看开启的模块 [root…

《一个人的朝圣》读后感

最近一周看了一本《一个人的朝圣》&#xff0c;读后汇总些文字&#xff0c;便于后续查阅&#xff01; 65岁的哈罗德&#xff0c;始终过着轨迹类似的人生。在某一天&#xff0c;由于一封信&#xff0c;却使他的内心深处产生了某种信念。他迈开艰难的脚步&#xff0c;强忍住关节的…

U-boot(五):启动内核

本文主要探讨210的uboot启动内核过程。 嵌入式系统状态启动 未上电时bootloader、kernel、rootfs以镜像形式存储在启动介质中(X210为iNand/SD卡),运行时搬运到DDR中 未上电时u-boot.bin,zImage,rootfs在SD卡中各自对应的分区中,启动时去对应分区寻找(分区表一…

PWM(PulseWidthModulation)控制

PWM&#xff08;Pulse Width Modulation&#xff09;控制就是对脉冲的宽度进行调制的技术&#xff0c;即通过对一系列脉冲的宽度进行调制&#xff0c;来等效的获得所需要的波形&#xff08;含形状和幅值&#xff09;&#xff1b;面积等效原理是PWM技术的重要基础理论&#xff1…

HTTP协议发展

HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC) 每一代HTTP解决了什么问题&#xff1f; 下图说明了主要功能。 HTTP 1.0 于 1996 年最终确定并完整记录。对同一服务器的每个请求都需要单独的 TCP 连接。 HTTP 1.1 于 1997 年发布。TCP 连接可以保持打开状态…

漏电流直流互感器正负1-50ua

1/ 互感线圈 01 双绕组800t / 200t 互感线圈 02 单绕组 1120t

PTA-7-53 身份证排序

题目&#xff1a; 输入n&#xff0c;然后连续输入n个身份证号。 将每个身份证的年月日抽取出来&#xff0c;按年-月-日格式组装&#xff0c;然后对组装后的年-月-日升序输出。 根据题目要求&#xff0c;代码实现如下&#xff1a; import java.util.Scanner; import java.uti…

【源码解析】聊聊SpringBoot自动装配如何实现的

Springboot的习惯优于配置&#xff0c;其实就是默认装配一些配置&#xff0c;。对于整体的开发、部署提升了效率。我们直接写一个main类就可以快速开发了。 比如我们引入web的starter-web&#xff0c;那么就引入了web的框架。 <dependency><groupId>org.springfra…

设计模式之十二:复合模式

模式通常被一起使用&#xff0c;并被组合在同一个解决方案中。 复合模式在一个解决方案中结合两个或多个模式&#xff0c;以解决一般或重复发生的问题。 首先重新构建鸭子模拟器&#xff1a; package headfirst.designpatterns.combining.ducks;public interface Quackable …