详解printf重定向到文件中,打印日志的实现
生活随笔
收集整理的這篇文章主要介紹了
详解printf重定向到文件中,打印日志的实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
printf是將信息打印到終端,但是有時當我們需要打印的信息比較多時,終端無法將所有信息都能夠保留在屏幕上,這樣我們就不能在終端獲取我們想要的信息了,重定向很好的幫我們解決了這個問題,下面我就通過重定向printf將打印信息打印到文件中,這也相當于一個打印日志。
打印日志的功能是這樣的,日志文件命名為YYYYMMDD.log,例如20180530.log,默認保存在與執行程序同一目錄下;
若連續記錄,則在每天0點重新生成當天日志;若程序運行時已有當天的日志,新的調試信息追加到該日志文件末。 創建一個線程,用來檢測時間,當過了24點進入新的一天時,已追加的方式重新創建一個日志文件 ,這樣就可以將打印信息都記錄到日志文件中,當然前提是標準輸出已經重定向到文件了,這才是本文的重點。 因為標準輸入輸出是行緩存,而我們的文件屬于全緩存,所以我們需要將緩存區設置為無緩沖直接寫到文件中,使用setbuf函數設置緩存區緩存為無緩存,使用dup2重定向標準輸出為文件描述符 setvbuf(stdout, NULL, _IOLBF, 0) != 0;
#include <time.h> #include <stdio.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "type_def.h"static void *log_thread(void *arg); static void setSysTime(char *timeStr); static void child_process(void);int main(int argc, const char *argv[]) {pthread_t thread_log = -1;UINT32 i = 0;struct tm *p_time = NULL;time_t time_s = 0;pid_t pid = 0;/* 設置系統時間 */setSysTime("2018.5.30 23:59:50");pid = fork();if (pid < 0){perror("fail to fork");return -1;}else if (0 == pid){child_process();}else{if (pthread_create(&thread_log, NULL, log_thread, NULL) != 0){perror("fail to pthread_create");return -1;}while (1){sleep(1);time(&time_s);p_time = localtime(&time_s);printf("parent :day = %d i = %d", p_time->tm_mday, i++);}}return 0; }/** @fn child_process* @brief 進程處理函數**/ static void child_process(void) {UINT32 j = 0;struct tm *p_time_c = NULL;time_t time_s_c = 0;pthread_t thread_log_child = -1;if (pthread_create(&thread_log_child, NULL, log_thread, NULL) != 0){perror("fail to pthread_create");return;}while (1){sleep(1);time(&time_s_c);p_time_c = localtime(&time_s_c);printf("child :day = %d i = %d", p_time_c->tm_mday, j++);}return; }/** @fn log_thread* @brief 線程處理函數,用來改變printf的重定向,每一天創建一個日志文件** @param arg[] 沒有使用** @return 返回線程退出的狀態值。可通過pthread_join函數獲得*/ static void *log_thread(void *arg) {struct tm *p_time = NULL;time_t time_s = 0;UINT32 yesterday = 0; // 用來保存當前的日期,與這一秒的日期比較,判斷是否到新的一天INT32 file_fd[2] = {-1}; // 日志文件的描述符數組CHAR log_name[16] = {0}; // 日志文件名UINT32 i = 0, j = 0;#if 1/* 設置緩存區為無緩存直接向流寫入數據 */fflush(stdout);if (setvbuf(stdout, NULL, _IOLBF, 0) != 0){perror("fail to setvbuf");goto ERR_EXIT;}#endifwhile (1){time(&time_s);p_time = localtime(&time_s);if (NULL == p_time){perror("fail to localtime");goto ERR_EXIT;}/* 如果當前日期不等于yesterday,代表現在已經是新的一天,創建新的日志文件 */if (yesterday != p_time->tm_mday){snprintf(log_name, sizeof(log_name), "./%04d%02d%02d.log", p_time->tm_year + 1900,\p_time->tm_mon + 1, p_time->tm_mday);yesterday = p_time->tm_mday;j = i;i = (i + 1) % 2;file_fd[i] = open(log_name, O_RDWR|O_APPEND|O_CREAT, 0664);if (file_fd[i] < 0){perror("fail to fopen");goto ERR_EXIT;}if (-1 == dup2(file_fd[i], STDOUT_FILENO)){perror("fail to dup2");goto ERR_EXIT;}close(file_fd[j]);}sleep(1);}ERR_EXIT:if (file_fd[0] > 0){close(file_fd[0]);}if (file_fd[1] > 0){close(file_fd[1]);}pthread_exit(0); }/** @fn setSysTime* @brief 用來設置系統的時間** @param timeStr[IN] 指定設置時間**/ static void setSysTime(char *timeStr) {struct timeval tv = {0};struct tm localTime = {0};UINT32 year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;sscanf(timeStr, "%d.%d.%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);localTime.tm_sec = second;localTime.tm_min = minute;localTime.tm_hour = hour;localTime.tm_mday = day;localTime.tm_mon = month - 1;localTime.tm_year = year - 1900;/* 將struct tm結構體的時間轉換成1970年1月1日以來逝去時間的秒數; */tv.tv_sec = mktime(&localTime);tv.tv_usec = 0;settimeofday(&tv, NULL);return; }
若連續記錄,則在每天0點重新生成當天日志;若程序運行時已有當天的日志,新的調試信息追加到該日志文件末。 創建一個線程,用來檢測時間,當過了24點進入新的一天時,已追加的方式重新創建一個日志文件 ,這樣就可以將打印信息都記錄到日志文件中,當然前提是標準輸出已經重定向到文件了,這才是本文的重點。 因為標準輸入輸出是行緩存,而我們的文件屬于全緩存,所以我們需要將緩存區設置為無緩沖直接寫到文件中,使用setbuf函數設置緩存區緩存為無緩存,使用dup2重定向標準輸出為文件描述符 setvbuf(stdout, NULL, _IOLBF, 0) != 0;
#include <time.h> #include <stdio.h> #include <string.h> #include <pthread.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "type_def.h"static void *log_thread(void *arg); static void setSysTime(char *timeStr); static void child_process(void);int main(int argc, const char *argv[]) {pthread_t thread_log = -1;UINT32 i = 0;struct tm *p_time = NULL;time_t time_s = 0;pid_t pid = 0;/* 設置系統時間 */setSysTime("2018.5.30 23:59:50");pid = fork();if (pid < 0){perror("fail to fork");return -1;}else if (0 == pid){child_process();}else{if (pthread_create(&thread_log, NULL, log_thread, NULL) != 0){perror("fail to pthread_create");return -1;}while (1){sleep(1);time(&time_s);p_time = localtime(&time_s);printf("parent :day = %d i = %d", p_time->tm_mday, i++);}}return 0; }/** @fn child_process* @brief 進程處理函數**/ static void child_process(void) {UINT32 j = 0;struct tm *p_time_c = NULL;time_t time_s_c = 0;pthread_t thread_log_child = -1;if (pthread_create(&thread_log_child, NULL, log_thread, NULL) != 0){perror("fail to pthread_create");return;}while (1){sleep(1);time(&time_s_c);p_time_c = localtime(&time_s_c);printf("child :day = %d i = %d", p_time_c->tm_mday, j++);}return; }/** @fn log_thread* @brief 線程處理函數,用來改變printf的重定向,每一天創建一個日志文件** @param arg[] 沒有使用** @return 返回線程退出的狀態值。可通過pthread_join函數獲得*/ static void *log_thread(void *arg) {struct tm *p_time = NULL;time_t time_s = 0;UINT32 yesterday = 0; // 用來保存當前的日期,與這一秒的日期比較,判斷是否到新的一天INT32 file_fd[2] = {-1}; // 日志文件的描述符數組CHAR log_name[16] = {0}; // 日志文件名UINT32 i = 0, j = 0;#if 1/* 設置緩存區為無緩存直接向流寫入數據 */fflush(stdout);if (setvbuf(stdout, NULL, _IOLBF, 0) != 0){perror("fail to setvbuf");goto ERR_EXIT;}#endifwhile (1){time(&time_s);p_time = localtime(&time_s);if (NULL == p_time){perror("fail to localtime");goto ERR_EXIT;}/* 如果當前日期不等于yesterday,代表現在已經是新的一天,創建新的日志文件 */if (yesterday != p_time->tm_mday){snprintf(log_name, sizeof(log_name), "./%04d%02d%02d.log", p_time->tm_year + 1900,\p_time->tm_mon + 1, p_time->tm_mday);yesterday = p_time->tm_mday;j = i;i = (i + 1) % 2;file_fd[i] = open(log_name, O_RDWR|O_APPEND|O_CREAT, 0664);if (file_fd[i] < 0){perror("fail to fopen");goto ERR_EXIT;}if (-1 == dup2(file_fd[i], STDOUT_FILENO)){perror("fail to dup2");goto ERR_EXIT;}close(file_fd[j]);}sleep(1);}ERR_EXIT:if (file_fd[0] > 0){close(file_fd[0]);}if (file_fd[1] > 0){close(file_fd[1]);}pthread_exit(0); }/** @fn setSysTime* @brief 用來設置系統的時間** @param timeStr[IN] 指定設置時間**/ static void setSysTime(char *timeStr) {struct timeval tv = {0};struct tm localTime = {0};UINT32 year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0;sscanf(timeStr, "%d.%d.%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);localTime.tm_sec = second;localTime.tm_min = minute;localTime.tm_hour = hour;localTime.tm_mday = day;localTime.tm_mon = month - 1;localTime.tm_year = year - 1900;/* 將struct tm結構體的時間轉換成1970年1月1日以來逝去時間的秒數; */tv.tv_sec = mktime(&localTime);tv.tv_usec = 0;settimeofday(&tv, NULL);return; }
總結
以上是生活随笔為你收集整理的详解printf重定向到文件中,打印日志的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 个人如何实现股票量化交易下单 股票交易接
- 下一篇: 按键短按长按连发双击