Linux中的日志插件詳解
一、日志文件的重要性
- 故障排查與問題定位
快速發(fā)現(xiàn)問題:日志能夠?qū)崟r記錄系統(tǒng)運行過程中的各種事件和狀態(tài)信息,當(dāng)系統(tǒng)出現(xiàn)故障或異常時,通過查看日志可以快速察覺到問題的發(fā)生,例如,服務(wù)器突然崩潰,日志中可能會記錄下崩潰前的錯誤信息、異常堆棧,幫助運維人員第一時間得知系統(tǒng)出現(xiàn)了故障
精準(zhǔn)定位根源:詳細的日志可以提供問題發(fā)生時的上下文信息,如函數(shù)調(diào)用順序、變量值等,以數(shù)據(jù)庫連接失敗為例,日志可能會記錄下數(shù)據(jù)庫的連接地址、端口、用戶名、密碼驗證情況等,幫助開發(fā)人員精準(zhǔn)定位是配置問題、網(wǎng)絡(luò)問題還是數(shù)據(jù)庫本身的問題
- 系統(tǒng)監(jiān)控與性能分析
監(jiān)控系統(tǒng)狀態(tài):通過對日志的實時分析,可以監(jiān)控系統(tǒng)的運行狀態(tài),例如,記錄系統(tǒng)的 CPU 使用率、內(nèi)存占用情況、網(wǎng)絡(luò)流量等信息,一旦這些指標(biāo)超出正常范圍,日志會及時反映出來,以便管理員采取相應(yīng)的措施,如增加服務(wù)器資源、優(yōu)化代碼等
性能瓶頸分析:日志可以記錄每個操作的執(zhí)行時間,通過對這些時間數(shù)據(jù)的分析,可以找出系統(tǒng)的性能瓶頸,比如,在一個 Web 應(yīng)用中,通過日志可以發(fā)現(xiàn)某個 API 接口的響應(yīng)時間過長,進而對該接口的代碼進行優(yōu)化,提高系統(tǒng)的整體性能
- 安全審計與合規(guī)性
安全事件追蹤:日志能夠記錄用戶的操作行為,包括登錄、數(shù)據(jù)訪問、權(quán)限變更等,當(dāng)發(fā)生安全事件,如數(shù)據(jù)泄露、非法登錄時,可以通過查看日志追蹤事件的源頭和過程,確定是否存在內(nèi)部人員違規(guī)操作或外部攻擊
滿足合規(guī)要求:許多行業(yè)和地區(qū)都有相關(guān)的法規(guī)和標(biāo)準(zhǔn)要求企業(yè)對系統(tǒng)操作和數(shù)據(jù)進行記錄和審計,例如,金融行業(yè)的 PCI-DSS 標(biāo)準(zhǔn)、醫(yī)療行業(yè)的 HIPAA 法規(guī)等,詳細的日志記錄可以幫助企業(yè)滿足這些合規(guī)要求,避免因違規(guī)而面臨的法律風(fēng)險
二、日志文件的簡單實現(xiàn)
1、comm.hpp
comm.hpp用來建立信道,Init類用于建立命名管道和退出時自動銷毀命名管道
#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
//命名管道文件路徑
#define FIFO_FILE "./myfifo"
//文件權(quán)限
#define MODE 0664
//枚舉命名管道錯誤
enum
{
FIFO_CREATE_ERR = 1,
FIFO_DELETE_ERR,
FIFO_OPEN_ERR
};
class Init
{
public:
Init()
{
// 創(chuàng)建命名管道
int n = mkfifo(FIFO_FILE, MODE);
if (n == -1)
{
perror("mkfifo");
exit(FIFO_CREATE_ERR);
}
}
~Init()
{
//銷毀命名管道
int m = unlink(FIFO_FILE);
if (m == -1)
{
perror("unlink");
exit(FIFO_DELETE_ERR);
}
}
};2、log.hpp
log.hpp中存放的是日志真正的實現(xiàn),將來我們可以在寫代碼的過程中使用這個文件來打印錯誤信息到日志上
#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 //需調(diào)試
#define Warning 2 //警告
#define Error 3 //錯誤
#define Fatal 4 //危險
//打印信息放到哪
#define Screen 1 //屏幕
#define Onefile 2 //一個文件
#define Classfile 3 //多個文件
#define LogFile "log.txt"
class Log
{
public:
Log()
{
//初始狀態(tài)下我們把日志打印到屏幕上
printMethod = Screen;
path = "./log/";
}
//可以通過該函數(shù)對日志打印模式改變
void Enable(int method)
{
printMethod = method;
}
//將上面的錯誤等級轉(zhuǎn)化為字符串
std::string levelToString(int level)
{
switch (level)
{
case Info:
return "Info";
case Debug:
return "Debug";
case Warning:
return "Warning";
case Error:
return "Error";
case Fatal:
return "Fatal";
default:
return "None";
}
}
//日志打印函數(shù)
void printLog(int level, const std::string &logtxt)
{
//選擇打印模式
switch (printMethod)
{
//選擇屏幕就把信息打印出來
case Screen:
std::cout << logtxt << std::endl;
break;
//選擇一個文件就把日志全部打印到一個文件當(dāng)中
case Onefile:
printOneFile(LogFile, logtxt);
break;
//按照等級打印到不同文件中,每個文件對應(yīng)一個等級
case Classfile:
printClassFile(level, logtxt);
break;
default:
break;
}
}
//打印到一個文件中
void printOneFile(const std::string &logname, const std::string &logtxt)
{
//將路徑與文件名稱結(jié)合起來就可以用open打開文件
std::string _logname = path + logname;
int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);
if (fd < 0)
return;
//將日志信息logtxt寫到文件當(dāng)中
write(fd, logtxt.c_str(), logtxt.size());
close(fd);
}
//打印到多個文件中
void printClassFile(int level, const std::string &logtxt)
{
//將文件按照錯誤等級分出來再復(fù)用一個文件的方法寫入每個文件
std::string filename = LogFile;
filename += ".";
filename += levelToString(level);
printOneFile(filename, logtxt);
}
//析構(gòu)函數(shù),全在棧上就不用寫
~Log()
{
}
//運算符重載,可變參數(shù)列表
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用于處理可變參數(shù)列表
va_list s;
//初始化s,使其指向可變參數(shù)列表第一個參數(shù),format是可變參數(shù)列表前面那個參數(shù)
va_start(s, format);
char rightbuffer[SIZE];
//將可變參數(shù)按照format字符串的格式寫入rightbuffer中
vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
//結(jié)束對可變參數(shù)列表的訪問
va_end(s);
// 格式:默認部分+自定義部分
//定義一個數(shù)組logtxt,用于存儲完整的日志信息
char logtxt[SIZE * 2];
//將日志左側(cè)部分也就是時間戳與等級部分(默認部分)
//和右側(cè)部分也就是自定義部分組合成一條完整的日志信息
snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
//將日志信息輸出
printLog(level, logtxt);
}
private:
int printMethod;//打印模式
std::string path;//路徑
};
三、測試用例
#include "log.hpp"
#include <cstdlib>
#include <unistd.h>
int main()
{
Log log;
int cnt = 10;
log.Enable(Onefile);
while (cnt--)
{
log.printOneFile("log","i am super little monster\n");
log.printClassFile(0,"this is 1\n");
log.printClassFile(1,"this is 2\n");
log.printClassFile(2,"this is 3\n");
log.printClassFile(3,"this is 4\n");
log.printClassFile(4,"this is 5\n");
}
return 0;
}




總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Linux查看、設(shè)置與取消環(huán)境變量詳解
Linux是一個多用戶的操作系統(tǒng),多用戶意味著每個用戶登錄系統(tǒng)后,都有自己專用的運行環(huán)境,而這個環(huán)境是由一組變量所定義,這組變量被稱為環(huán)境變量,本文給大家詳細介紹了Linux查看、設(shè)置與取消環(huán)境變量操作指南,需要的朋友可以參考下2025-07-07
Linux中使用selenium截圖的文字變?yōu)榉娇虻慕鉀Q方案
本文講述了在Linux中使用Selenium截圖時遇到的文字顯示為方框的問題,原因在于缺少中文字體,作者詳細介紹了在CentOs上安裝宋體字體并配置字體環(huán)境的步驟,確保截圖恢復(fù)正常顯示,需要的朋友可以參考下2025-11-11
在 Ubuntu Linux 上安裝 Oracle Java 14的方法
最近,Oracle 宣布 Java 14(或 Oracle JDK 14)公開可用。如果你想進行最新的實驗或者開發(fā)的話,那么你可以試試在 Linux 系統(tǒng)上安裝 Java 14,感興趣的朋友可以參考下本文2020-04-04
Kali Linux下安裝python dev時依賴出錯的問題解決
在使用Kali Linux進行滲透測試或開發(fā)時,有時會遇到需要安裝??python-dev??包的情況,在安裝過程中可能會遇到依賴問題,下面小編就來和大家詳細講講具體解決方法吧2025-09-09

