在使用 acl 库编写应用过程中,记录日志是一个非常重要的过程,acl 从几个层面提供了日志的不同记录方式。在 acl 的 C 库部分(lib_acl.a),有三个源文件与日志记录相关:acl_msg.c/acl_msg.h, acl_mylog.c/acl_mylog.h, acl_debug.c/acl_debug.h。其中,acl_mylog.c 是真正记录日志的源文件,acl_msg.c 则是在 acl_mylog.c 基础之上的二次封装,acl_debug.c 是在 acl_msg.c 基础之上的再次封装。下面根据此三个日志源文件从三个层次描述日志记录的过程。
一、ac_mylog.c/acl_mylog.h
打开 acl_mylog.h 头文件,可以看到主要有三个函数:acl_open_log(打开日志文件),acl_write_to_log(写日志)以及acl_close_log(关闭日志)---(这三个函数是最基础的日志记录过程,当然我们不必直接使用)。该库支持两类日志记录方式:1、本地文件记录方式,2、与 syslog-ng 结合的网络日志记录方式。本地文件记录方式是 acl 日志库对外提供的最简单的日志记录方式,此方式不依赖于第三方日志库,但不应用在生产环境中,因为该方式不支持日志回滚等高级特性,为了便于生产上使用,所以产生了第二种方式(与 syslog-ng 结合),查看日志打开接口(如下):
/** * 打开日志文件 * @param recipients {const char*} 日志接收器列表,由 "|" 分隔,接收器 * 可以是本地文件或远程套接口,如: * /tmp/test.log|UDP:127.0.0.1:12345|TCP:127.0.0.1:12345|UNIX:/tmp/test.sock * 该配置要求将所有日志同时发给 /tmp/test.log, UDP:127.0.0.1:12345, * TCP:127.0.0.1:12345 和 UNIX:/tmp/test.sock 四个日志接收器对象 * @param plog_pre {const char*} 日志记录信息前的提示信息,建议用进程 * 名填写此值 */ ACL_API int acl_open_log(const char *recipients, const char *plog_pre);
从上面的函数声明可以看出,acl 的日志记录允许同时输出至多个日志管道中(最简单的方式就是直接写入本地磁盘文件:/tmp/test.log),同时更应看到,其中有三个奇怪的日志文件表达方式:UDP:IP:PORT, TCP:IP:PORT, UNIX:/xxx,其实这三种方式均是与 syslog-ng 相关,即分别表示:
1、以 UDP 方式发送日志至 syslog-ng;
2、以 TCP 方式发送日志至 syslog-ng;
3、以 UNIX 域套接字方式发送日志至 syslog-ng。
因为日志管理是一个非常复杂的过程,所以在 acl 除了提供最简单的日志文件记录外,更建议用户将日志输出至 syslog-ng 中(作者自己的项目也往往是这样做的)。
二、acl_msg.c/acl_msg.h
该日志库提供了更为高级的日志记录方法,不仅提供了灵活的日志记录函数,同时还允许用户注册自己的日志记录函数库,该日志库主要函数接口如下:
/** * 日志打开函数 * @param log_file {const char*} 日志接收者集合,由 "|" 分隔,接收器 * 可以是本地文件或远程套接口,如: * /tmp/test.log|UDP:127.0.0.1:12345|TCP:127.0.0.1:12345|UNIX:/tmp/test.sock * 该配置要求将所有日志同时发给 /tmp/test.log, UDP:127.0.0.1:12345, * TCP:127.0.0.1:12345 和 UNIX:/tmp/test.sock 四个日志接收器对象 * @param plog_pre {const char*} 日志记录信息前的提示信息,建议用进程 * @param info_pre {const char*} 日志记录信息前的提示信息 */ ACL_API void acl_msg_open(const char *log_file, const char *info_pre); /** * 关闭日志函数 */ ACL_API void acl_msg_close(void);
上面是日志打开与关闭的函数,看上去算是相对简单。下面是几个日志记录的函数接口:
/** * 一般级别日志信息记录函数 * @param fmt {const char*} 参数格式 * @param ... 变参序列 */ #ifdef WIN32 ACL_API void acl_msg_info(const char *fmt,...); #else ACL_API void __attribute__((format(printf,1,2))) acl_msg_info(const char *fmt,...); #endif /** * 警告级别日志信息记录函数 * @param fmt {const char*} 参数格式 * @param ... 变参序列 */ #ifdef WIN32 ACL_API void acl_msg_warn(const char *fmt,...); #else ACL_API void __attribute__((format(printf,1,2))) acl_msg_warn(const char *fmt,...); #endif /** * 错误级别日志信息记录函数 * @param fmt {const char*} 参数格式 * @param ... 变参序列 */ #ifdef WIN32 ACL_API void acl_msg_error(const char *fmt,...); #else ACL_API void __attribute__((format(printf,1,2))) acl_msg_error(const char *fmt,...); #endif /** * 致命级别日志信息记录函数 * @param fmt {const char*} 参数格式 * @param ... 变参序列 */ #ifdef WIN32 ACL_API void acl_msg_fatal(const char *fmt,...); #else ACL_API void __attribute__((format(printf,1,2))) acl_msg_fatal(const char *fmt,...); #endif /** * 恐慌级别日志信息记录函数 * @param fmt {const char*} 参数格式 * @param ... 变参序列 */ #ifdef WIN32 ACL_API void acl_msg_panic(const char *fmt,...); #else ACL_API void __attribute__((format(printf,1,2))) acl_msg_panic(const char *fmt,...); #endif
可以看到,这些函数的使用方式与 printf 类似,另外,在 UNIX 下使用 GCC 编译时前面还有一个修饰符:__attribute__((format(printf,m,n))),这主要是方便 gcc 编译器针对变参进行语法检查(大家应该知道变参是如此方便灵活而又如此容易出错)。
为了方便程序开发过程中的调试,下面的函数当用户未调用 acl_msg_open 打开日志而直接使用 acl_msg_xxx 写日志时,决定是否将日志信息输出至屏幕(这个函数应该在程序初始化时调用):
/** * 当未调用 acl_msg_open 方式打开日志时,调用了 acl_msg_info/error/fatal/warn * 的操作,是否允许信息输出至标准输出屏幕上,通过此函数来设置该开关,该开关 * 仅影响是否需要将信息输出至终端屏幕而不影响是否输出至文件中 * @param onoff {int} 非 0 表示允许输出至屏幕 */ ACL_API void acl_msg_stdout_enable(int onoff);
前面曾说过,acl 的日志库还允许用户使用自己的日志记录过程,但要求用户必须在程序初始化时注册自己的日志处理函数,如下:
/** * 在打开日志前调用此函数注册应用自己的日志打开函数、日志关闭函数、日志记录函数 * @param open_fn {ACL_MSG_OPEN_FN} 自定义日志打开函数 * @param close_fn {ACL_MSG_CLOSE_FN} 自定义日志关闭函数 * @param write_fn {ACL_MSG_WRITE_FN} 自定义日志记录函数 * @param ctx {void*} 自定义参数 */ ACL_API void acl_msg_register(ACL_MSG_OPEN_FN open_fn, ACL_MSG_CLOSE_FN close_fn, ACL_MSG_WRITE_FN write_fn, void *ctx);
调用此函数后,以后的日志记录过程(即当用户调用:acl_msg_xxx 相关过程时)的内容便输出便由用户的日志库控制。
除了以上主要的日志函数接口,在 acl_msg 中还提供了以下几个函数,便于用户知晓程序出错原因:
/** * 获得上次系统调用出错时的错误描述信息,该函数内部采用了线程局部变量,所以是线程 * 安全的,但使用起来更简单些 * @return {const char *} 返回错误提示信息 */ ACL_API const char *acl_last_serror(void); /** * 获得上次系统调用出错时的错误号 * @return {int} 错误号 */ ACL_API int acl_last_error(void);
三、acl_debug.c/acl_debug.h
该日志函数库是在 acl_msg 之上的再一次封装,该库的思想来源于 squid 的日志记录方式,可以将日志分成不同的类别,每一个类别又分成不同的级别,这样用户就可以非常方便地通过配置文件来记录不同类别的不同级别的日志信息了。在程序初始化时需先调用如此函数:
/** * 初始化日志调试调用接口 * @param pStr {const char*} 调试类别(建议值在100至1000之间)标签及级别字符串, * 格式: 1,1; 2,10; 3,8... or 1:1; 2:10; 3:8... */ ACL_API void acl_debug_init(const char *pStr); /** * 初始化日志调试调用接口 * @param pStr {const char*} 调试标签及级别字符串, * 格式: 1,1; 2,10; 3,8... or 1:1; 2:10; 3:8... * @param max_debug_level {int} 最大调试标签值 */ ACL_API void acl_debug_init2(const char *pStr, int max_debug_level);
其中,第一个参数是一个由日志记录类别与级别组成的字符串,格式为:类别1:最大记录级别, 类别2:最大记录级别, ...。例如:100:2; 102:3; 103:4,其含义是日志将会记录类别为 100 的所有级别值小于2、类别为 101 的所有级别值小于 3 以及类别为 103 的所有级别值小于 4 的日志信息。关于记录类别需要注意:类别值最好是 >= 100,且 < 1000(当使用 acl_debug_init2 初始化时只要类别值 >= 100 即可,因为第二个参数指定了最大类别值),这是因为 acl 库内部一些保留的类别值都在 0 -- 100 之间。
那么具体的使用这些类别与级别记录日志的接口是什么呢?如下所示:
/** * 日志调试宏接口 * @param SECTION {int} 调试标签值 * @param LEVEL {int} 对应于SECTION调试标签的级别 */ #define acl_debug(SECTION, LEVEL) \ !acl_do_debug((SECTION), (LEVEL)) ? (void) 0 : acl_msg_info
看到了吧,用户其实只需要调用一个宏即可,如下面的例子:
/* 初始化日志类别记录 */ const char *str = "101:2; 103:4; 105:3"; /* 记录所有类别值为 101 级别小于等于 2、类别值为 102 级别小于等于 4、类别值为 105 级别小于等于 3 的日志内容 */ acl_debug_init(str); ...... /* 下面的日志因符合类别值 101 级别值 <= 2 而被记录 */ acl_debug(101, 2)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); /* 下面日志符合类别 105 的记录级别 */ acl_debug(105, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); /* 下面的日志因不符合类别值 103 的记录级别条件而被忽略 */ acl_debug(103, 5)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); /* 下面日志的类别值 102 因不存在而被忽略 */ acl_debug(102, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL));
此外,为了方便,还可以传给 acl_debug_init 的参数写为:"all:1",意思是所有类别的级别值 <= 1 的日志都将被记录,如下面的内容都会被记录:
acl_debug_init("all:1"); ...... acl_debug(100, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(101, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(101, 0)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(102, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(103, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(104, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); acl_debug(105, 1)("%s(%d): log time: %ld", __FILE__, __LINE__, time(NULL)); ......
ok,有关日志 acl 日志记录函数就先写这些,使用者可以根据项目需要采用不同的日志记录方式。
参考:
本文地址:http://zsxxsz.iteye.com/blog/1893115
github 地址:https://github.com/acl-dev/acl
下载:http://sourceforge.net/projects/acl/
svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code
QQ 群:242722074
相关推荐
### Linux的Syslog服务来记录Cisco路由器的日志(基本配置) #### Syslog服务概述 Syslog(系统日志协议)是一种工业标准的轻量级协议,用于在计算机间传输事件日志信息。它广泛应用于网络设备、服务器以及操作系统...
7. **日志记录**:启用ACL日志功能可以帮助管理员跟踪和分析网络流量,从而优化和调整策略。日志可以记录匹配规则的流量信息,为故障排查提供依据。 通过深入理解以上知识点并熟练掌握相关配置命令,我们可以有效地...
7. **日志记录**:启用ACL的日志功能可以帮助跟踪和分析流量行为,有助于识别潜在的攻击或异常活动。 华为ACL配置是确保网络安全和资源管理的重要手段,正确的配置和管理能够有效地保护网络资源,防止未经授权的...
3. 异步日志记录:为了保证系统性能,日志记录往往采用异步方式进行,避免阻塞主线程。日志信息会被放入队列,由后台线程负责写入磁盘或发送到远程服务器。 4. 日志审计:日志记录模块还应具备审计功能,记录关键...
4. **计数与日志**:ACL规则可以开启计数功能,记录匹配到该规则的数据包数量,便于监控和分析。同时,也可以配置日志,记录匹配到规则的事件。 ### 五、使用实例 1. **保护内部网络**:通过ACL阻止外部对内部...
- **日志与审计**:ACL可配合日志功能,记录被拒绝的流量,便于网络监控和问题排查。 ### 6. ACL.ppt文件 提供的"ACL.ppt"文件可能包含关于访问控制列表的详细讲解,包括如何配置、使用示例以及最佳实践。建议仔细...
《JSPSmart系统-权限管理与日志记录模块的设计与开发》是一份深入探讨Web应用程序中关键组件构建的资源包,包含源代码和相关论文。这个项目主要关注两个核心方面:权限管理和日志记录,这对于任何大型企业级系统来说...
- **日志记录**:通过启用ACL的日志功能,可以记录下被拒绝的数据包信息,这对于后续的安全审计非常有用。 #### 四、案例分析 假设一家公司希望在周一至周五的工作时间(09:00-18:00)内阻止员工访问社交网站...
配置完成后,可以通过`display acl 3000`命令来查看ACL的详细信息,以及`display traffic-filter applied-record`来检查接口应用的ACL记录,确保配置正确生效。 **故障处理与优化** 在实际应用中,可能会遇到扩展...
4. **监控日志**:定期审查ACL的日志记录,以便发现异常访问模式并采取相应措施。 综上所述,通过合理配置和使用ACL,可以有效地提升校园网等复杂网络环境的安全性,减少病毒的威胁。然而,值得注意的是,ACL只是...
5. **日志记录**:记录用户的数据库操作和权限检查结果,便于审计和故障排查。 在实际应用中,`mysql_util`这个子文件可能是这个库的核心实现,包含了一系列与MySQL交互的类和函数。开发者可以通过这个库轻松地集成...
同时,登录验证记录还可以用于审计和日志分析,帮助追踪异常登录行为,及时发现潜在的安全风险。 文件名"rocketmq-console-master"表明这是一个RocketMQ Console的源码仓库,可能包含了实现这些新特性的代码。...
本文将详细介绍华为日志服务器的基本配置方式。 一、基本配置 要使用华为日志服务器,需要在防火墙上启用日志服务器的配置方式。首先,需要定义防火墙的ACL(Access Control List),以过滤需要的日志。例如,使用...
5. **网络审计**:ACL可以配合日志系统,记录通过规则的数据包,便于事后审计和问题排查。 6. **隔离网络区域**:在校园网中可能存在多个子网或部门,通过ACL可以实现子网间的访问隔离,保护各个区域的安全性。 在...
本文将详细介绍在MongoDB 3.6版本中如何增加分片集群的ACL(访问控制列表)权限,以及在搭建分片集群过程中可能遇到的一些问题及其解决方案。 ### MongoDB分片集群简介 MongoDB分片集群是一种分布式数据存储结构,...
4. **日志和审计**:记录和跟踪权限相关的活动,帮助管理员监控和分析系统的访问模式。 5. **动态更新**:在运行时修改权限设置,无需重启服务。 使用ACL库可以有效地提升软件的安全性,确保只有合法的用户和进程...
7. **监控与记录**:在问题解决后,持续监控网络流量和日志,以确保新的ACL配置有效且无副作用。 ### ACL故障排除案例 - **无法访问外部服务**:检查出站ACL是否允许到特定端口(如HTTP的80端口或HTTPS的443端口)...
《JSP毕业设计:JSPSmart系统的权限管理与日志记录模块》 在现代Web应用程序开发中,权限管理和日志记录是两个至关重要的模块。本项目以JSP(JavaServer Pages)技术为核心,结合Java语言,实现了JSPSmart系统的...
例如,通过设置筛选条件,可以找出早上操作、中午不签退、下午继续操作的可疑日志记录,或者针对预算单位零余额账户的使用情况进行审计。 #### 3. ACL的高级功能 ACL提供了诸多高级功能,如新建表达式和执行数据...
- **日志页面**:记录ACL的变更历史,有助于审计和追踪权限的调整情况,确保安全策略的透明度和可追溯性。 - **高级页面**:提供更精细的权限控制选项,如对特定文档或视图的访问控制,允许管理员根据实际需求定制...