当前位置:网站首页>Logrotate log rotation method create and copyruncate principles
Logrotate log rotation method create and copyruncate principles
2022-06-12 11:28:00 【edycm】
List of articles
Purpose
This paper mainly introduces create、copytruncate The principle of two kinds of log rotation
create principle
Processing logic for log rotation :
- take test.log Rename it to test.log.1
- Create a new test.log file

copytruncate principle
- take test.log Copy one as test.log.1
- take test.log Empty

Source code analysis
Reference code
rotateSingleLog function , Rotate a single log file :
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 Method handling : step 1: Rename file
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 Method handling : step 2: Create a new file
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 Processing mode , call copyTruncate function
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 function , Copy and empty files :
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 Processing mode , step 1: Create a new file
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 Processing mode , step 2: Copy the contents of the log file to a new file
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 Processing mode , step 3: Empty log file
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;
}
边栏推荐
- k52.第一章 基于kubeadm安装kubernetes v1.22 -- 集群部署
- selenium使用代理IP
- Redis summary
- arm各种交叉编译工具的区别
- SOT23(Small Outline Transistor)
- K58. Chapter 1 installing kubernetes V1.23 based on kubeadm -- cluster deployment
- LVS health state detection based on application layer
- InfoQ geek media's 15th anniversary solicitation |position:fixed virtual button cannot take effect after being triggered. Problem analysis and Solution Exploration
- SOT23(Small Outline Transistor)
- 架构训练模块 7
猜你喜欢
随机推荐
AcWing 1986. Mirror (simulation, ring diagram)
C# 37. Textbox scroll bar and multiline
Using stairs function in MATLAB
【蓝桥杯单片机 国赛 第十一届】
字节序(网络/主机)转换
LVS health state detection based on application layer
【clickhouse专栏】基础数据类型说明
Handwritten common interview questions
When you have a server
ReentrantLock源码分析
Verifiability and scarcity of NFT Digital Collections
Clj3-100alh30 residual current relay
FPGA开发——Hello_world例程
Clickhouse column basic data type description
M-arch (fanwai 11) gd32l233 evaluation PWM driven active buzzer
AcWing 1921. Rearranging cows (ring diagram)
postman传入list
Differences among various cross compiling tools of arm
MCUXpresso开发NXP RT1060(3)——移植LVGL到NXP RT1060
Socket programming UDP









