当前位置:网站首页>Logrotate log rotation method create and copyruncate principles

Logrotate log rotation method create and copyruncate principles

2022-06-12 11:28:00 edycm

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
     Insert picture description here

copytruncate principle

  • take test.log Copy one as test.log.1
  • take test.log Empty
     Insert picture description here

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;
}




原网站

版权声明
本文为[edycm]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/163/202206121105116728.html