当前位置:网站首页>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;
}
边栏推荐
- AcWing 135. Maximum subsequence sum (prefix sum + monotone queue to find the minimum value of fixed length interval)
- C# 36. DataGridView行号
- NLP data set download address for naturallanguageprocessing
- Flex layout
- Create vite source code analysis
- 网络的拓扑结构
- Windows10安装mysql-8.0.28-winx64
- Get all listening events in the element
- 890. 查找和替换模式
- 疫情居家办公体验 | 社区征文
猜你喜欢

正则表达式 | 浅解

【藍橋杯單片機 國賽 第十一届】

890. 查找和替换模式

Clj3-100alh30 residual current relay

Windows10 install mysql-8.0.28-winx64

logrotate日志轮转方式create和copytruncate原理

Reading mysql45 lecture - self summary (part)

信号继电器RXSF1-RK271018DC110V

InfoQ geek media's 15th anniversary solicitation |position:fixed virtual button cannot take effect after being triggered. Problem analysis and Solution Exploration

【clickhouse专栏】基础数据类型说明
随机推荐
Heavyweight proxy cache server squid
selenium使用代理IP
Lambda表达式 | 浅解
[Blue Bridge Cup SCM 11th National race]
(三十七)Bee如何同时使用不同数据源实例
Principle analysis of vite HMR
SOT23(Small Outline Transistor)
字节序(网络/主机)转换
K59. Chapter 2 installing kubernetes V1.23 based on binary packages -- cluster deployment
AcWing 1995. Meet and greet (simulation)
Verifiability and scarcity of NFT Digital Collections
AcWing 1921. 重新排列奶牛(环图)
读mysql45讲-自我总结(部分)
k52.第一章 基于kubeadm安装kubernetes v1.22 -- 集群部署
记录一下使用JPA时遇到的坑
C# 37. Textbox scroll bar and multiline
模块8作业
Les humains veulent de l'argent, du pouvoir, de la beauté, de l'immortalité, du bonheur... Mais les tortues ne veulent être qu'une tortue.
MySQL锁查漏补缺
AI - face