当前位置:网站首页>logrotate日志轮转方式create和copytruncate原理
logrotate日志轮转方式create和copytruncate原理
2022-06-12 11:05:00 【edycm】
目的
主要介绍create、copytruncate两种日志轮转的原理
create原理
日志轮转时的处理逻辑:
- 将test.log重命名为test.log.1
- 创建一个新的test.log文件

copytruncate原理
- 将test.log拷贝一份为test.log.1
- 将test.log清空

源码分析
参考代码
rotateSingleLog函数,轮转单个日志文件:
static int rotateSingleLog(const struct logInfo *log, unsigned logNum,
struct logState *state, struct logNames *rotNames)
{
int hasErrors = 0;
struct stat sb;
char *savedContext = NULL;
if (!state->doRotate)
return 0;
if (!hasErrors) {
// create 方式处理:步骤1:重命名文件
if (!(log->flags & (LOG_FLAG_COPYTRUNCATE | LOG_FLAG_COPY))) {
if (setSecCtxByName(log->files[logNum], log, &savedContext) != 0) {
/* error msg already printed */
return 1;
}
#ifdef WITH_ACL
if ((prev_acl = acl_get_file(log->files[logNum], ACL_TYPE_ACCESS)) == NULL) {
if (is_acl_well_supported(errno)) {
message(MESS_ERROR, "getting file ACL %s: %s\n",
log->files[logNum], strerror(errno));
hasErrors = 1;
}
}
#endif /* WITH_ACL */
if (log->flags & LOG_FLAG_TMPFILENAME) {
char *tmpFilename;
if (asprintf(&tmpFilename, "%s%s", log->files[logNum], ".tmp") < 0) {
message_OOM();
restoreSecCtx(&savedContext);
return 1;
}
message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum],
tmpFilename);
if (!debug && !hasErrors && rename(log->files[logNum], tmpFilename)) {
message(MESS_ERROR, "failed to rename %s to %s: %s\n",
log->files[logNum], tmpFilename,
strerror(errno));
hasErrors = 1;
}
free(tmpFilename);
}
else {
message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum],
rotNames->finalName);
if (!debug && !hasErrors &&
rename(log->files[logNum], rotNames->finalName)) {
message(MESS_ERROR, "failed to rename %s to %s: %s\n",
log->files[logNum], rotNames->finalName,
strerror(errno));
hasErrors = 1;
}
}
if (!log->rotateCount) {
const char *ext = "";
if (log->compress_ext
&& (log->flags & LOG_FLAG_COMPRESS)
&& !(log->flags & LOG_FLAG_DELAYCOMPRESS))
ext = log->compress_ext;
free(rotNames->disposeName);
if (asprintf(&rotNames->disposeName, "%s%s", rotNames->finalName, ext) < 0) {
message_OOM();
rotNames->disposeName = NULL;
return 1;
}
message(MESS_DEBUG, "disposeName will be %s\n", rotNames->disposeName);
}
}
// create 方式处理:步骤2:创建一个新文件
if (!hasErrors && (log->flags & LOG_FLAG_CREATE) &&
!(log->flags & (LOG_FLAG_COPYTRUNCATE | LOG_FLAG_COPY))) {
int have_create_mode = 0;
if (log->createUid == NO_UID)
sb.st_uid = state->sb.st_uid;
else
sb.st_uid = log->createUid;
if (log->createGid == NO_GID)
sb.st_gid = state->sb.st_gid;
else
sb.st_gid = log->createGid;
if (log->createMode == NO_MODE)
sb.st_mode = state->sb.st_mode & 0777;
else {
sb.st_mode = log->createMode;
have_create_mode = 1;
}
message(MESS_DEBUG, "creating new %s mode = 0%o uid = %d "
"gid = %d\n", log->files[logNum], (unsigned int) sb.st_mode,
(int) sb.st_uid, (int) sb.st_gid);
if (!debug) {
if (!hasErrors) {
int fd = createOutputFile(log->files[logNum], O_RDWR,
&sb, prev_acl, have_create_mode);
#ifdef WITH_ACL
if (prev_acl) {
acl_free(prev_acl);
prev_acl = NULL;
}
#endif
if (fd < 0)
hasErrors = 1;
else {
close(fd);
}
}
}
}
restoreSecCtx(&savedContext);
// copytruncate 处理方式,调用copyTruncate函数
if (!hasErrors
&& (log->flags & (LOG_FLAG_COPYTRUNCATE | LOG_FLAG_COPY))
&& !(log->flags & LOG_FLAG_TMPFILENAME)) {
hasErrors = copyTruncate(log->files[logNum], rotNames->finalName,
&state->sb, log, !log->rotateCount);
}
#ifdef WITH_ACL
if (prev_acl) {
acl_free(prev_acl);
prev_acl = NULL;
}
#endif /* WITH_ACL */
}
return hasErrors;
}
copyTruncate函数,拷贝和清空文件:
static int copyTruncate(const char *currLog, const char *saveLog, const struct stat *sb,
const struct logInfo *log, int skip_copy)
{
int rc = 1;
int fdcurr = -1, fdsave = -1;
message(MESS_DEBUG, "copying %s to %s\n", currLog, saveLog);
if (!debug) {
/* read access is sufficient for 'copy' but not for 'copytruncate' */
const int read_only = (log->flags & LOG_FLAG_COPY)
&& !(log->flags & LOG_FLAG_COPYTRUNCATE);
if ((fdcurr = open_logfile(currLog, log, !read_only)) < 0) {
message(MESS_ERROR, "error opening %s: %s\n", currLog,
strerror(errno));
goto fail;
}
if (!skip_copy) {
char *prevCtx;
if (setSecCtx(fdcurr, currLog, &prevCtx) != 0) {
/* error msg already printed */
goto fail;
}
#ifdef WITH_ACL
if ((prev_acl = acl_get_fd(fdcurr)) == NULL) {
if (is_acl_well_supported(errno)) {
message(MESS_ERROR, "getting file ACL %s: %s\n",
currLog, strerror(errno));
restoreSecCtx(&prevCtx);
goto fail;
}
}
#endif /* WITH_ACL */
// copytruncate 处理方式,步骤1:创建新文件
fdsave = createOutputFile(saveLog, O_WRONLY, sb, prev_acl, 0);
restoreSecCtx(&prevCtx);
#ifdef WITH_ACL
if (prev_acl) {
acl_free(prev_acl);
prev_acl = NULL;
}
#endif
if (fdsave < 0)
goto fail;
// copytruncate 处理方式,步骤2:将日志文件内容复制到新文件
if (sparse_copy(fdcurr, fdsave, sb, saveLog, currLog) != 1) {
message(MESS_ERROR, "error copying %s to %s: %s\n", currLog,
saveLog, strerror(errno));
unlink(saveLog);
goto fail;
}
}
}
if (log->flags & LOG_FLAG_COPYTRUNCATE) {
message(MESS_DEBUG, "truncating %s\n", currLog);
if (!debug) {
if (fdsave >= 0)
fsync(fdsave);
// copytruncate 处理方式,步骤3:清空日志文件
if (ftruncate(fdcurr, 0)) {
message(MESS_ERROR, "error truncating %s: %s\n", currLog,
strerror(errno));
goto fail;
}
}
} else
message(MESS_DEBUG, "Not truncating %s\n", currLog);
rc = 0;
fail:
if (fdcurr >= 0) {
close(fdcurr);
}
if (fdsave >= 0) {
close(fdsave);
}
return rc;
}
}
}
} else
message(MESS_DEBUG, “Not truncating %s\n”, currLog);
rc = 0;
fail:
if (fdcurr >= 0) {
close(fdcurr);
}
if (fdsave >= 0) {
close(fdsave);
}
return rc;
}
边栏推荐
- 基于QT的旅行查询与模拟系统
- k59.第二章 基于二进制包安装kubernetes v1.23 --集群部署
- Reading mysql45 lecture - self summary (part)
- A simple understanding of b+ tree
- 【CF1392D】D. Omkar and Bed Wars(环形与后效性dp)
- SOT23(Small Outline Transistor)
- Leetcode 2169. 得到 0 的操作数
- AcWing 128. 编辑器(对顶栈 实现序列内部指定位置高效修改)
- Malicious code analysis practice - lab03-02 DLL analysis
- Error during session start; please check your PHP and/or webserver log file and configure your PHP
猜你喜欢

Leetcode 2169. Get operands of 0

M-Arch(番外12)GD32L233评测-CAU加解密(捉弄下小编)

Malicious code analysis practice - lab06-01 exe~Lab06-04. Exe dynamic analysis

Fiddler automatically saves the result of the specified request to a file

^34 scope interview questions

AcWing 131. 直方图中最大的矩形(单调栈经典运用 模板)

The solution of Lenovo notebook ThinkPad t440 WiFi unable to connect to the Internet

Malicious code analysis practice - lab03-01 Exe basic dynamic analysis

SOT23(Small Outline Transistor)

M-Arch(番外13)GD32L233评测-来点音乐
随机推荐
Bug easily ignored by recursion
Distributed storage exploration
Module 8 job
Construction and construction of meta Universe System
【CF1392D】D. Omkar and Bed Wars(环形与后效性dp)
MySQL implements split method
人脸识别pip 安装dlib库失败
Php中redis的keys问题
Several solutions across domains
The name of a great man
AcWing 131. 直方图中最大的矩形(单调栈经典运用 模板)
重量级代理缓存服务器Squid
k52.第一章 基于kubeadm安装kubernetes v1.22 -- 集群部署
Error during session start; please check your PHP and/or webserver log file and configure your PHP
M-arch (fanwai 13) gd32l233 evaluation - some music
Verifiability and scarcity of NFT Digital Collections
JS open common application market
命名规范/注释规范/逻辑规范
A few secrets - a special day
tensorflow 2.x 多分类混淆矩阵及评价指标计算方法(精确率、召回率、f1分数)