【网络入侵检测】基于源码分析Suricata的引擎日志配置解析
【作者主页】只道当时是寻常
【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。
1. 概要
👋 Suricata 的引擎日志记录系统主要记录该引擎在启动、运行以及关闭期间应用程序的相关信息,如错误信息和其他诊断信息,但不包含 Suricata 自身生成的警报和事件。该系统设有多个日志级别,包括错误、警告、通知、信息、性能、配置和调试。
2. 配置格式
下面是Suricata配置文件中对于引擎日志默认配置:
logging:default-log-level: notice#default-log-format: "[%i] %t [%S] - (%f:%l) <%d> (%n) -- "default-output-filter:#stacktrace-on-signal: onoutputs:- console:enabled: yes# type: json- file:enabled: yeslevel: infofilename: suricata.log# format: "[%i - %m] %z %d: %S: %M"# type: json- syslog:enabled: nofacility: local5format: "[%i] <%d> -- "# type: json
-
default-log-level:此选项可以设置 Suricata 引擎日志输出级别。
-
日志等级主要分为erro、warning、notice、info、perf、config 和 debug。注意,只有当 Suricata 使用 --enable-debug 配置选项进行编译时,才会发出调试级别的日志记录。
-
注意,默认日志级别的值会被环境变量 “SC_LOG_LEVEL” 所覆盖。
-
-
default-log-format:自定义引擎日志输出格式。注意,默认日志级别的值会被环境变量 “SC_LOG_FORMAT” 所覆盖。日志格式详细介绍见3.4章节内容。
-
default-output-filter:自定义正则表达式,用于过滤引擎日志输出。
-
outputs:自定义Suricata 引擎日志输出类型。
-
console,输出到终端;file,输出到文件;syslog,输出到syslog。
-
enabled:(yes/no)开关选项,用于控制输出方式的开关。
-
level:用于控制日志输出等级,支持的等级为erro、warning、notice、info、perf、config 和 debug。
-
type:(regular/json)控制引擎日志输出格式。
-
format:引擎日志格式。
-
filename:引擎日志输出类型为 file 时有效,用于指定引擎日志文件名。
-
facility:引擎日志输出类型为 syslog 时有效,此字段能够对日志消息的来源进行分类,也就是说这里定义 Suricata 通过 syslog 发送的日志类型。Suricata 支持此字段配置值分别为 auth,authpriv,cron,daemon,ftp,kern,lpr,mail,news,security,syslog,user,uucp,local0,local1,local2,local3,local4,local5,local6,local7。
-
3. 源码解析
3.1 配置解析
Suricata 启动后,通过调用 SCLogLoadConfig 函数解析配置文件中引擎日志模块的相关信息。在该函数执行过程中,会依次读取、解析引擎日志的各类参数,并完成初始化操作,为后续引擎日志的输出提供配置支持。
引擎日志的配置信息存储在下面数据结构中:
typedef struct SCLogInitData_ {/* startup message */const char *startup_message;/* the log level */SCLogLevel global_log_level;/* the log format */const char *global_log_format;/* output filter */const char *op_filter;/* list of output interfaces to be used */SCLogOPIfaceCtx *op_ifaces;/* no of op ifaces */uint8_t op_ifaces_cnt;
} SCLogInitData;
SCLogLoadConfig 函数实现代码如下所示:
void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid)
{ConfNode *outputs;SCLogInitData *sc_lid;int have_logging = 0;int max_level = 0;SCLogLevel min_level = 0;/* If verbose logging was requested, set the minimum as* SC_LOG_NOTICE plus the extra verbosity. */if (verbose) {min_level = SC_LOG_NOTICE + verbose;}outputs = ConfGetNode("logging.outputs");if (outputs == NULL) {SCLogDebug("No logging.output configuration section found.");return;}sc_lid = SCLogAllocLogInitData();if (sc_lid == NULL) {SCLogDebug("Could not allocate memory for log init data");return;}/* Get default log level and format. */const char *default_log_level_s = NULL;if (ConfGet("logging.default-log-level", &default_log_level_s) == 1) {SCLogLevel default_log_level =SCMapEnumNameToValue(default_log_level_s, sc_log_level_map);if (default_log_level == -1) {SCLogError("Invalid default log level: %s", default_log_level_s);exit(EXIT_FAILURE);}sc_lid->global_log_level = MAX(min_level, default_log_level);}else {sc_lid->global_log_level = MAX(min_level, SC_LOG_NOTICE);}if (ConfGet("logging.default-log-format", &sc_lid->global_log_format) != 1)sc_lid->global_log_format = SCLogGetDefaultLogFormat(sc_lid->global_log_level);(void)ConfGet("logging.default-output-filter", &sc_lid->op_filter);ConfNode *seq_node, *output;TAILQ_FOREACH(seq_node, &outputs->head, next) {SCLogLevel level = sc_lid->global_log_level;SCLogOPIfaceCtx *op_iface_ctx = NULL;const char *format;const char *level_s;output = ConfNodeLookupChild(seq_node, seq_node->val);if (output == NULL)continue;/* By default an output is enabled. */const char *enabled = ConfNodeLookupChildValue(output, "enabled");if (enabled != NULL && ConfValIsFalse(enabled))continue;SCLogOPType type = SC_LOG_OP_TYPE_REGULAR;const char *type_s = ConfNodeLookupChildValue(output, "type");if (type_s != NULL) {if (strcmp(type_s, "regular") == 0)type = SC_LOG_OP_TYPE_REGULAR;else if (strcmp(type_s, "json") == 0) {type = SC_LOG_OP_TYPE_JSON;}}format = ConfNodeLookupChildValue(output, "format");level_s = ConfNodeLookupChildValue(output, "level");if (level_s != NULL) {level = SCMapEnumNameToValue(level_s, sc_log_level_map);if (level == -1) {SCLogError("Invalid log level: %s", level_s);exit(EXIT_FAILURE);}max_level = MAX(max_level, level);}/* Increase the level of extra verbosity was requested. */level = MAX(min_level, level);if (strcmp(output->name, "console") == 0) {op_iface_ctx = SCLogInitConsoleOPIface(format, level, type);}else if (strcmp(output->name, "file") == 0) {if (format == NULL) {format = SC_LOG_DEF_FILE_FORMAT;}const char *filename = ConfNodeLookupChildValue(output, "filename");if (filename == NULL) {FatalError("Logging to file requires a filename");}char *path = NULL;if (!(PathIsAbsolute(filename))) {path = SCLogGetLogFilename(filename);} else {path = SCStrdup(filename);}if (path == NULL)FatalError("failed to setup output to file");have_logging = 1;op_iface_ctx = SCLogInitFileOPIface(path, userid, groupid, format, level, type);SCFree(path);}else if (strcmp(output->name, "syslog") == 0) {int facility = SC_LOG_DEF_SYSLOG_FACILITY;const char *facility_s = ConfNodeLookupChildValue(output,"facility");if (facility_s != NULL) {facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());if (facility == -1) {SCLogWarning("Invalid syslog ""facility: \"%s\", now using \"%s\" as syslog ""facility",facility_s, SC_LOG_DEF_SYSLOG_FACILITY_STR);facility = SC_LOG_DEF_SYSLOG_FACILITY;}}SCLogDebug("Initializing syslog logging with format \"%s\"", format);have_logging = 1;op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level, type);}else {SCLogWarning("invalid logging method: %s, ignoring", output->name);}if (op_iface_ctx != NULL) {SCLogAppendOPIfaceCtx(op_iface_ctx, sc_lid);}}if (daemon && (have_logging == 0)) {SCLogWarning("no logging compatible with daemon mode selected,"" suricata won't be able to log. Please update "" 'logging.outputs' in the YAML.");}/* Set the global log level to that of the max level used. */sc_lid->global_log_level = MAX(sc_lid->global_log_level, max_level);SCLogInitLogModule(sc_lid);SCLogDebug("sc_log_global_log_level: %d", sc_log_global_log_level);SCLogDebug("sc_lc->log_format: %s", sc_log_config->log_format);SCLogDebug("SCLogSetOPFilter: filter: %s", sc_log_config->op_filter);if (sc_lid != NULL)SCFree(sc_lid);
}
3.2 日志等级
在 Suricata 中,对于引擎告警日志默认日志等级为 notice。其支持的日志等级定义在 default_log_level_s 这个结构体中,其格式如下所示:
typedef struct SCEnumCharMap_ {const char *enum_name;int enum_value;
} SCEnumCharMap;SCEnumCharMap sc_log_level_map[] = {{ "Not set", SC_LOG_NOTSET },{ "None", SC_LOG_NONE },{ "Error", SC_LOG_ERROR },{ "Warning", SC_LOG_WARNING },{ "Notice", SC_LOG_NOTICE },{ "Info", SC_LOG_INFO },{ "Perf", SC_LOG_PERF },{ "Config", SC_LOG_CONFIG },{ "Debug", SC_LOG_DEBUG },{ NULL, -1 }
};
3.3 日志过滤
在 Suricata 中,引擎日志具备正则表达式过滤功能。SCLogMessageGetBuffer 函数承担着依据指定的日志格式和内容,生成最终日志消息字符串的任务。当该函数完成字符串的组装工作后,若系统配置了日志过滤规则,便会调用 pcre2_match 函数,将生成的日志消息字符串与过滤规则进行精确匹配。只有当字符串命中过滤规则时,相应的日志才会被输出;若未命中,则不会进行输出操作。(注意,如果字符串是JSON格式则过滤条件不生效)
SCLogMessageGetBuffer 函数进行正则匹配部分的实现如下所示:
/*** \brief Adds the global log_format to the outgoing buffer** \param log_level log_level of the message that has to be logged* \param msg Buffer containing the outgoing message* \param file File_name from where the message originated* \param function Function_name from where the message originated* \param line Line_no from where the messaged originated** \retval 0 on success; else a negative value on error*/
static SCError SCLogMessageGetBuffer(SCTime_t tval, int color, SCLogOPType type, char *buffer,size_t buffer_size, const char *log_format, const SCLogLevel log_level, const char *file,const unsigned int line, const char *function, const char *module, const char *message)
{if (type == SC_LOG_OP_TYPE_JSON)return SCLogMessageJSON(tval, buffer, buffer_size, log_level, file, line, function, module, message);... ... // 省略部分代码实现if (sc_log_config->op_filter_regex != NULL) {if (pcre2_match(sc_log_config->op_filter_regex, (PCRE2_SPTR8)buffer, strlen(buffer), 0, 0,sc_log_config->op_filter_regex_match, NULL) < 0) {return -1; // bit hacky, but just return !0}}return 0;
}
3.4 日志格式
在 Suricata 中,默认状态下,不同告警等级对应着差异化的告警格式。若未配置 default-log-format 日志格式,系统将通过 SCLogGetDefaultLogFormat 函数,依据具体的日志等级,从预定义的日志格式集合中选取适配的格式进行应用。SCLogGetDefaultLogFormat 函数实现如下所示:
/* The default log_format, if it is not supplied by the user */
#define SC_LOG_DEF_FILE_FORMAT "[%i - %m] %z %d: %S: %M"
#define SC_LOG_DEF_LOG_FORMAT_REL_NOTICE "%D: %S: %M"
#define SC_LOG_DEF_LOG_FORMAT_REL_INFO "%d: %S: %M"
#define SC_LOG_DEF_LOG_FORMAT_REL_CONFIG "[%i] %d: %S: %M"
#define SC_LOG_DEF_LOG_FORMAT_DEBUG "%d: %S: %M [%n:%f:%l]"static inline const char *SCLogGetDefaultLogFormat(const SCLogLevel lvl)
{const char *prog_ver = GetProgramVersion();if (strstr(prog_ver, "RELEASE") != NULL) {if (lvl <= SC_LOG_NOTICE)return SC_LOG_DEF_LOG_FORMAT_REL_NOTICE;else if (lvl <= SC_LOG_INFO)return SC_LOG_DEF_LOG_FORMAT_REL_INFO;else if (lvl <= SC_LOG_CONFIG)return SC_LOG_DEF_LOG_FORMAT_REL_CONFIG;}return SC_LOG_DEF_LOG_FORMAT_DEBUG;
}
日志格式定义中包含诸如 % D、% S、% M 等特殊字符,其具体含义如下:
/* The different log format specifiers supported by the API */
#define SC_LOG_FMT_TIME 'z' /* Timestamp in RFC3339 like format */
#define SC_LOG_FMT_TIME_LEGACY 't' /* Timestamp in legacy format */
#define SC_LOG_FMT_PID 'p' /* PID */
#define SC_LOG_FMT_TID 'i' /* Thread ID */
#define SC_LOG_FMT_TM 'm' /* Thread module name */
#define SC_LOG_FMT_LOG_LEVEL 'd' /* Log level */
#define SC_LOG_FMT_LOG_SLEVEL 'D' /* Log level */
#define SC_LOG_FMT_FILE_NAME 'f' /* File name */
#define SC_LOG_FMT_LINE 'l' /* Line number */
#define SC_LOG_FMT_FUNCTION 'n' /* Function */
#define SC_LOG_FMT_SUBSYSTEM 'S' /* Subsystem name */
#define SC_LOG_FMT_THREAD_NAME 'T' /* thread name */
#define SC_LOG_FMT_MESSAGE 'M' /* log message body *//* The log format prefix for the format specifiers */
#define SC_LOG_FMT_PREFIX '%'
%z | 符合 RFC3339 格式的时间戳 |
%t | 旧格式的时间戳 |
%p | 进程 ID(PID) |
%i | 线程 ID(TID) |
%m | 线程模块名称 |
%d | 日志级别 |
%D | 日志级别 |
%f | 文件名 |
%l | 行号 |
%n | 函数名 |
%S | 子系统名称 |
%T | 线程名称 |
%M | 日志消息主体 |
3.5 syslog-facility
在 Suricata 中,SCLogLoadConfig 函数负责解析日志输出类型。当检测到开启 console 输出时,会调用 SCLogInitConsoleOPIface 函数进行初始化;若开启 file 输出,则调用 SCLogInitFileOPIface 函数;而当 syslog 输出开启时,会调用 SCLogInitSyslogOPIface 函数。其中,console 和 file 输出类型的初始化函数,其功能正如我们所预期,主要是完成文件描述符的打开操作。接下来,我们着重探讨 syslog 输出模式。
Suricata在使用syslog作为输出时支持facility类型的配置,其所支持的类型存储在
sc_syslog_facility_map结构体中,其定义如下所示:
SCEnumCharMap sc_syslog_facility_map[] = {{ "auth", LOG_AUTH },{ "authpriv", LOG_AUTHPRIV },{ "cron", LOG_CRON },{ "daemon", LOG_DAEMON },{ "ftp", LOG_FTP },{ "kern", LOG_KERN },{ "lpr", LOG_LPR },{ "mail", LOG_MAIL },{ "news", LOG_NEWS },{ "security", LOG_AUTH },{ "syslog", LOG_SYSLOG },{ "user", LOG_USER },{ "uucp", LOG_UUCP },{ "local0", LOG_LOCAL0 },{ "local1", LOG_LOCAL1 },{ "local2", LOG_LOCAL2 },{ "local3", LOG_LOCAL3 },{ "local4", LOG_LOCAL4 },{ "local5", LOG_LOCAL5 },{ "local6", LOG_LOCAL6 },{ "local7", LOG_LOCAL7 },{ NULL, -1 }
};
在 SCLogInitSyslogOPIface 函数中通过调用openlog函数打开 syslog,并将facility 属性赋值。该函数实现如下所示:
/*** \brief Initializes the syslog output interface** \param facility The facility code for syslog* \param log_format Pointer to the log_format for this op interface, that* overrides the global_log_format* \param log_level Override of the global_log_level by this interface** \retval iface_ctx Pointer to the syslog output interface context created*/
static inline SCLogOPIfaceCtx *SCLogInitSyslogOPIface(int facility,const char *log_format,SCLogLevel log_level,SCLogOPType type)
{SCLogOPIfaceCtx *iface_ctx = SCLogAllocLogOPIfaceCtx();if ( iface_ctx == NULL) {FatalError("Fatal error encountered in SCLogInitSyslogOPIface. Exiting...");}iface_ctx->iface = SC_LOG_OP_IFACE_SYSLOG;iface_ctx->type = type;if (facility == -1)facility = SC_LOG_DEF_SYSLOG_FACILITY;iface_ctx->facility = facility;if (log_format != NULL &&(iface_ctx->log_format = SCStrdup(log_format)) == NULL) {printf("Error allocating memory\n");exit(EXIT_FAILURE);}iface_ctx->log_level = log_level;openlog(NULL, LOG_NDELAY, iface_ctx->facility);return iface_ctx;
}
相关文章:
【网络入侵检测】基于源码分析Suricata的引擎日志配置解析
【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 Suricata 的引擎日志记录系统主要记录该引擎在启动、运行以及关闭期间应用程序的相关信息,如错误信息和其他诊断信息,…...
Attention层的FLOPs计算
前置知识 设矩阵 A 的维度为 mn,矩阵 B 的维度为 np,则它们相乘后得到矩阵 C 的维度为 mp。其中,C 中每个元素的计算需要进行 n 次乘法和 n−1 次加法。也就是说,总的浮点运算次数(FLOPs)约为 m p (2n) …...
支付APP如何做好网络安全防护
支付APP的网络安全防护需要从技术、管理、用户行为等多层面综合施策,以下为核心措施: 一、技术防御:构建安全底层 数据加密 传输加密:使用最新协议(如TLS 1.3)对交易数据加密&…...
Missashe考研日记-day31
Missashe考研日记-day31 0 写在前面 芜湖,五一前最后一天学习圆满结束,又到了最喜欢的放假环节,回来再努力了。 1 专业课408 学习时间:2h学习内容: OK啊,今天把文件系统前两节的内容全部学完了…...
二叉树的路径总和问题(递归遍历,回溯算法)
112. 路径总和 - 力扣(LeetCode) class Solution { private: bool traversal(TreeNode*cur,int count){if(!cur->left&&!cur->right&&count0){return true;}if(!cur->left&&!cur->right){return false;}if(cur-…...
Java学习计划与资源推荐(入门到进阶、高阶、实战)
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息文章目录 Java学习计划与资源推荐**一、筑基阶段(2-3个月)****二、进阶开发阶段(2个月)****三、高级突破阶段(2-3个月)****四、项目实战与竞…...
动态规划 -- 子数组问题
本篇文章中主要讲解动态规划系列中的几个经典的子数组问题。 1 最大子数组和 53. 最大子数组和 - 力扣(LeetCode) 解析题目: 子数组是一个数组中的连续部分,也就是说,如果一个数组以 nums[i]结尾,那么有两…...
Sehll编程的函数于数组
目录 一、函数 1.1、定义函数 1.2、查看、删除函数 1.3、函数的返回值 1.4、函数的参数传递 1.5、函数的作用范围 1.6、函数递归 二、数组 2.1、声明数组 2.2、数组格式定义 2.3、数组调用 2.4、删除数组 一、函数 shell编程中,函数用于封装一段可以重…...
flutter 专题 六十四 在原生项目中集成Flutter
概述 使用Flutter从零开始开发App是一件轻松惬意的事情,但对于一些成熟的产品来说,完全摒弃原有App的历史沉淀,全面转向Flutter是不现实的。因此使用Flutter去统一Android、iOS技术栈,把它作为已有原生App的扩展能力,…...
AI生成Flutter UI代码实践(一)
之前的杂谈中有提到目前的一些主流AI编程工具,比如Cursor,Copilot,Trea等。因为我是Android 开发,日常使用Android Studio,所以日常使用最多的还是Copilot,毕竟Github月月送我会员,白嫖还是挺香…...
spring boot中@Validated
在 Spring Boot 中,Validated 是用于触发参数校验的注解,通常与 JSR-303/JSR-380(Bean Validation)提供的校验注解一起使用。以下是常见的校验注解及其用法: 1. 基本校验注解 这些注解可以直接用于字段…...
VBA代码解决方案第二十四讲:EXCEL中,如何删除重复数据行
《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程,目前已经是第三版修订了。这套教程定位于入门后的提高,在学习这套教程过程中,侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…...
SpringBoot+EasyExcel+Mybatis+H2实现导入
文章目录 SpringBootEasyExcelMybatisH2实现导入1.准备工作1.1 依赖管理1.2 配置信息properties1.3 H2数据库1.4 Spring Boot 基础概念1.5 Mybatis核心概念 1.6 EasyExcel核心概念 2.生成Excel数据工具类-随机字符串编写生成Excel的java文件 3.导入功能并且存入数据库3.1 返回结…...
算法四 习题 1.3
数组实现栈 #include <iostream> #include <vector> #include <stdexcept> using namespace std;class MyStack { private:vector<int> data; // 用于存储栈元素的数组public:// 构造函数MyStack() {}// 入栈操作void push(int val) {data.push_back…...
el-tabs与table样式冲突导致高度失效问题解决(vue2+elementui)
背景 正常的el-table能根据父容器自动计算剩余高度,并会在列表中判断自适应去放出滚动条。而el-tabs本身就是自适应el-tab-pane内容的高度来进行自适应调节,这样就会导致el-table计算不了当前剩余的高度,所以当el-tabs里面包含el-table时&am…...
Access开发:轻松一键将 Access 全库表格导出为 Excel
hi,大家好呀! 在日常工作中,Access 常常是我们忠实的数据管家,默默守护着项目信息、客户列表或是库存记录。它结构清晰,录入便捷,对于许多中小型应用场景来说,无疑是个得力助手。然而ÿ…...
合并多个Excel文件到一个文件,并保留格式
合并多个Excel文件到一个文件,并保留格式 需求介绍第一步:创建目标文件第二步:创建任务列表第三步:合并文件第四步:处理合并后的文件之调用程序打开并保存一次之前生成的Excel文件第五步:处理合并后的文件之…...
使用ZYNQ芯片和LVGL框架实现用户高刷新UI设计系列教程(第十讲)
这一期我们讲解demo中登录、ok按键的回调函数以及界面的美化,以下是上期界面的图片如图所示: 首先点击界面在右侧的工具栏中调配颜色渐变色,具体设置如下图所示: 然后是关于界面内框也就是容器的美化,具体如下图所示…...
论文笔记(八十二)Transformers without Normalization
Transformers without Normalization 文章概括Abstract1 引言2 背景:归一化层3 归一化层做什么?4 动态 Tanh (Dynamic Tanh (DyT))5 实验6 分析6.1 DyT \text{DyT} DyT 的效率6.2 tanh \text{tanh} tanh 和 α α α 的消融实验…...
Mysql之数据库基础
🌟 各位看官好,我是maomi_9526! 🌍 种一棵树最好是十年前,其次是现在! 🚀 今天来学习Mysql的相关知识。 👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更…...
shell(5)
位置参数变量 1.介绍 当我们执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量. 比如:./myshell.sh100 200,这就是一个执行shell的命令行,可以在myshell脚本中获取到参数信息. 2.基本语法 $n(功能描述:n为数字,$0代表命令…...
VARIAN安捷伦真空泵维修清洁保养操作SOP换油操作流程内部转子图文并茂内部培训手侧
VARIAN安捷伦真空泵维修清洁保养操作SOP换油操作流程内部转子图文并茂内部培训手侧...
动画震动效果
项目场景: 提示:这里简述项目相关背景: 在有的相关目中特别是在C端一般都要求做的炫酷一些,这就需要一些简易的动画效果,这里就弄了一个简易的震动的效果如下视频所示 让图标一大一小的震动视频 分析: 提…...
DB-GPT V0.7.1 版本更新:支持多模态模型、支持 Qwen3 系列,GLM4 系列模型 、支持Oracle数据库等
V0.7.1版本主要新增、增强了以下核心特性 🍀DB-GPT支持多模态模型。 🍀DB-GPT支持 Qwen3 系列,GLM4 系列模型。 🍀 MCP支持 SSE 权限认证和 SSL/TLS 安全通信。 🍀 支持Oracle数据库。 🍀 支持 Infini…...
C++23 std::invoke_r:调用可调用 (Callable) 对象 (P2136R3)
文章目录 引言背景知识回顾可调用对象C17的std::invoke std::invoke_r的诞生提案背景std::invoke_r的定义参数和返回值异常说明 std::invoke_r的使用场景指定返回类型丢弃返回值 std::invoke_r与std::invoke的对比功能差异使用场景差异 结论 引言 在C的发展历程中,…...
pymysql
参数(会导致SQL注入) import pymysql# 创建数据库连接 conn pymysql.connect(user "root",password "root",host "127.0.0.1",port 3306,database "test" )# 创建游标对象 cur conn.cursor(cursorpymysql.…...
基于Spring Boot + Vue 项目中引入deepseek方法
准备工作 在开始调用 DeepSeek API 之前,你需要完成以下准备工作: 1.访问 DeepSeek 官网,注册一个账号。 2.获取 API 密钥:登录 DeepSeek 平台,进入 API 管理 页面。创建一个新的 API 密钥(API Key&#x…...
Spring Boot集成Kafka并使用多个死信队列的完整示例
以下是Spring Boot集成Kafka并使用多个死信队列的完整示例,包含代码和配置说明。 1. 添加依赖 (pom.xml) <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId&…...
全面了解CSS语法 ! ! !
CSS(层叠样式表)是网页设计的灵魂之一,它赋予了网页活力与美感。无论是为一个简单的个人博客增添色彩,还是为复杂的企业网站设计布局,CSS都是不可或缺的工具。那么,CSS语法到底是什么样的呢?它背…...
Springboot使用ThreadLocal提供线程局部变量,传递登录用户名
文章目录 概述使用创建ThreadLocalUtil工具类在登录拦截器中使用ThreadLocal存储登录用户名在/userInfo接口中获取登录用户名 注意事项参考视频 概述 使用 创建ThreadLocalUtil工具类 utils/ThreadLocalUtil.java package org.example.utils;/*** ThreadLocal 工具类*/ Supp…...
排序算法——选择排序
一、介绍 「排序算法sortingalgorithm」用于对一组数据按照特定顺序进行排列。排序算法有着广泛的应用,因为有序数据通常能够被更有效地查找、分析和处理。 如图所示,排序算法中的数据类型可以是整数、浮点数、字符或字符串等。排序的判断规则可根据需求…...
AlphaFold蛋白质结构数据库介绍
AlphaFold Protein Structure Database (AlphaFold DB) 是 DeepMind + EMBL-EBI 合作开发的公开蛋白质结构预测数据库,是利用 AlphaFold2/AlphaFold3 AI模型 预测的全基因组级蛋白质三维结构库。 网址: https://alphafold.ebi.ac.uk 项目内容主办单位DeepMind + EMBL-EBI上线…...
Roboflow标注数据集
使用Roboflow进行标注 关键点标注目标检测标注图像分类标注分割标注 Roboflow是一款易于使用的在线 图像标注。 关键点标注 每个图像的标注包括: 1、边界框坐标(每个物品应该有一个边界框,用*[x1,y1,x2,y2]*格式即左上角和右下角点描述&…...
大厂经验:第三方包Paramunittest参数化 VS Unittest内置参数化文本管理器subtest
大厂经验:第三方包Paramunittest参数化 VS Unittest内置参数化文本管理器subtest 代码解析 Paramunittest 核心逻辑 paramunittest.parametrized((Testerr, test, Invalid Login or Password., test_login_admin is passed),(Sam, test, Invalid Login or Passwo…...
[特殊字符]适合五四青年节的SVG模版[特殊字符]
宝藏模版 往期推荐(点击阅读): 趣味效果|高大上|可爱风|年终总结I|年终总结II|循环特效|情人节I|情人节II|情人节IIII|妇女节I&…...
当插入排序遇上“凌波微步“——希尔排序的奇幻漂流
文章目录 一、排序江湖的隐藏高手二、分而治之的魔法1. 核心思想拆解2. 动态演示(脑补版) 三、C语言实现大揭秘代码要点解析: 四、性能分析与实战技巧1. 时间复杂度迷思2. 实测性能对比 五、为什么说它永不过时?六、进阶思考题 一…...
【Hot 100】 148. 排序链表
目录 引言十大排序算法1. 冒泡排序 (Bubble Sort)2. 选择排序 (Selection Sort)3. 插入排序 (Insertion Sort)4. 希尔排序 (Shell Sort)简单代码说明关键特点 5. 归并排序 (Merge Sort)6. 快速排序 (Quick Sort)7. 堆排序 (Heap Sort)8. 计数排序 (Counting Sort)9. 桶排序 (Bu…...
大连理工大学选修课——机器学习笔记(9):线性判别式与逻辑回归
线性判别式与逻辑回归 概述 判别式方法 产生式模型需要计算输入、输出的联合概率 需要知道样本的概率分布,定义似然密度的隐式参数也称为基于似然的分类 判别式模型直接构造判别式 g i ( x ∣ θ i ) g_i(x|\theta_i) gi(x∣θi),显式定义判别式…...
[特殊字符] 开发工作高内存占用场景下,Windows 内存压缩机制是否应该启用?实测分析与优化建议
在日常开发中,我们往往需要同时运行多个高占用内存的工具,例如: IntelliJ IDEA VMware 虚拟机 多个 Java 后端程序 这些应用程序非常“吃内存”,轻松就能把 16GB、甚至 24GB 的物理内存用满。那么,Windows 的“内存…...
相机的基础架构
📷 相机相关基础架构学习路径 一、了解手机相机系统架构 Android Camera HAL(如果你是做 Android 平台) 学习 Camera HAL3 架构(基于 camera_device_t, camera3_device_ops 接口) 熟悉 CameraService → CameraProvid…...
C# 类成员的访问:内部与外部
在 C# 编程中,了解如何从类的内部和外部访问成员是非常重要的。本文将详细介绍这两种访问方式,并通过示例代码展示其具体应用。 从类的内部访问成员 类的成员可以在类的内部自由地互相访问,即使这些成员被声明为private。在类的方法中&…...
DAPO:对GRPO的几点改进
DAPO:对GRPO的几点改进 TL; DR:对 GRPO 的几处细节进行了优化,包括去除 KL 约束、解耦 ppo-clip 的上下界,上界设置更高以鼓励探索、超长回答过滤、token level 损失计算等。相比于原始 GRPO,在 AIME24 上提升非常显著…...
从零构建 MCP Server 与 Client:打造你的第一个 AI 工具集成应用
目录 🚀 从零构建 MCP Server 与 Client:打造你的第一个 AI 工具集成应用 🧱 1. 准备工作 🛠️ 2. 构建 MCP Server(服务端) 2.1 初始化服务器 🧩 3. 添加自定义工具(Tools&…...
2025.4.27 Vue.js 基础学习笔记
一、Vue.js 简介 Vue.js(简称 Vue)是一个用于构建用户界面的渐进式 JavaScript 框架。它具有以下特点: 轻量级 :核心库体积小,性能优秀,不占用过多资源,加载速度快,适合各种规模的应…...
基于用户场景的汽车行驶工况构建:数据驱动下的能耗优化革命
行业现状:标准工况与用户场景的割裂 全球汽车行业普遍采用WLTC工况进行能耗测试,但其与真实道路场景差异显著。据研究,WLTC工况下车辆能耗数据比实际道路低10%-30%,导致用户对续航虚标投诉激增(数据来源:东…...
IoTDB集群部署中的网络、存储与负载配置优化
一、引言 在现代计算机系统和应用程序中,网络I/O性能是决定整体系统表现的关键因素之一。特别是在IoTDB集群环境中,网络I/O的重要性尤为突出,特别是在处理大量测点数据、客户端请求以及集群内部通信时。本文将介绍IoTDB数据库集群部署过程中…...
Unity URPShader:实现和PS一样的色相/饱和度调整参数效果(修复)
目录 前言: 一、问题原因 二、算法修复 三、全代码 前言: 在之前的文章我已经实现了标题所述的内容功能:Unity URPShader:实现和PS一样的色相/饱和度调整参数效果-CSDN博客 但在偶然测试的时候,发现当采样的图片为…...
告别手动时代!物联网软件开发让万物自动互联
清晨,智能窗帘随着阳光自动拉开;运动时,手表精准记录着健康数据;回到家,室温早已调节至最舒适状态...这些场景的实现,都离不开物联网软件开发的技术支撑。在智能家居软件开发、智能穿戴软件开发、医疗器械软…...
Vue ui初始化项目并使用iview写一个菜单导航
winR 输入命令 vue ui浏览器会自动打开http://localhost:8000/ 找到创建 image.png 选择一个目录创建vue项目 image.png 点击再此创建新项目 image.png 我一般都是再已经有git仓库的目录进行项目创建,所以这个勾去掉 点击下一步 image.png 这里可以选择默认&#x…...
函数调用及Chain——SQL+GLM
Langchainchain数据库操作_langchain 操作数据库-CSDN博客 本文和基于上述链接 进一步。 初始化数据库&模型 # temperature0,此处仅需要SQL语句,不需要多样化返回。 from langchain.chains.sql_database.query import create_sql_query_chain from …...