1. 程式人生 > 其它 >Unix/Linux 日誌記錄syslog

Unix/Linux 日誌記錄syslog

目錄

1. syslogd守護程序

我們知道, 守護程序(daemon)是

在後臺執行且不與任何控制終端關聯的程序.

參見: Linux 系統程式設計學習筆記 - 終端、作業控制與守護程序 守護程序章節.

那麼如何得知守護程序的狀態, 和某些事情發生呢?守護程序如何輸出訊息, 或者告知管理員?
可以呼叫syslog函式輸出這些訊息, 函式把訊息傳送給syslogd守護程序, 而syslogd守護程序可以將訊息寫入同一個檔案或者傳送至另一個主機, 方便系統管理人員檢視.

1.1 BSD syslog組織結構:


有以下3種產生日誌訊息的方法:
1)核心例程呼叫log函式
任何一個使用者程序都可以通過open, read /dev/klog裝置來讀取這些訊息. 不過, 編寫核心例程時, 才會用到.

2)大多數使用者程序(守護程序)呼叫syslog(3)函式來產生日誌訊息
3)本機上的使用者程序, 或者網路上的使用者程序, 都可以通過TCP/IP網路連線到此主機, 可將日誌訊息發向UDP port 514.
syslog函式本身不會產生UDP資料報, 而是要求產生此日誌訊息的程序進行顯式的網路程式設計.

1.2 syslogd守護程序的啟動

syslond守護程序是由某個系統初始化指令碼啟動, 而且在系統工作期間一直執行.
源自Berkeley的syslogd的啟動實現步驟:
1)讀取配置檔案
通常為/ect/syslog.conf 的配置檔案指定本守護程序可能收取的各種日誌訊息(log message)應該如何處理. 這些訊息可能被新增到一個檔案(特例/dev/console), 或被寫到指定使用者的登入視窗(若該使用者已登入到本守護程序所在系統中), 或被轉發給另一個主機上的syslogd程序.

2)建立一個Unix Domain資料報套接字, 給他捆綁路徑名/var/run/log(某些系統是/dev/log)

3)建立一個UDP套接字, 捆綁埠514(syslog服務使用埠號)

4)開啟路徑名/dev/klog
來自核心中的任何出錯訊息看著像是這個裝置的輸入.

5)此後, syslogd守護程序在一個無限迴圈中執行: 呼叫select以等待它的3個描述符(來自上面的1),2),3))之一可讀, 讀入日誌訊息, 並按照配置檔案進行處理. 如果守護程序收到SIGHUP訊號, 那麼就重新讀取配置檔案.

注意: 較新的syslogd實現禁止建立UDP套接字, 除非管理員明確要求. 理由: 允許任何程序往該套接字傳送UDP資料報, 會讓系統易遭拒絕服務攻擊, 其檔案系統可能被填滿, 而合法程序的日誌訊息可能被排擠掉.


2. 日誌記錄函式

2.1 syslog

守護程序沒有控制終端, 不能列印訊息到stdout, stderr. 使用者程序從syslogd守護程序中登記訊息的常用方法是呼叫syslog函式.
呼叫syslog產生一個日誌訊息.

#include <syslog.h>

void syslog(int priority, const char *format, ...);
  • 引數
    priority 是facility和level的組合. level見下表, facility見openlog的facility.

syslog的level:

level 說明
LOG_EMERG 緊急(系統不可使用)(最高優先順序)
LOG_ALERT 必須立即修復的情況
LOG_CRIT 嚴重情況(如硬體裝置出錯)
LOG_ERR 出錯情況
LOG_WARNING 警告情況
LOG_NOTICE 正常但重要的情況
LOG_INFO 資訊性訊息
LOG_DEBUG 除錯訊息(最低優先順序)

2.2 openlog, closelog

#include <syslog.h>

void openlog(const char *ident, int option, int facility);
void closelog(void);
void vsyslog(int priority, const char *format, va_list ap);

openlog 可選呼叫, 如果不呼叫openlog, 則在第一次呼叫syslong時, 自動呼叫openlog. openlog可以在首次呼叫syslog前呼叫.
closelog 可選呼叫, 因為它只是關閉曾被用於與syslogd守護程序進行通訊的描述符. 這些描述符在程序正常終止以後, 也會自動關閉. closelog可以在應用程序不再需要傳送日誌訊息時呼叫, 以關閉與syslogd通訊的描述符.

  • 引數
    options 呼叫openlog時, 通常不立即建立Unixo Domain socket, 而該socket到首次呼叫syslog時才打開. openlog的options能影響log的行為, 如指定LOG_NDELAY選項將迫使該socket在openlog呼叫後立即建立, 而不是到呼叫syslog時才建立.
    openlog的options由一個或多個常值的構成(邏輯或):
options 說明
LOG_CONS 若無法傳送到syslogd守護程序則登記到控制檯
LOG_NDELAY 不延遲開啟, 立即建立套接字
LOG_PERROR 既傳送到syslogd守護程序, 又登記到標準錯誤輸出
LOG_PID 隨每個日誌訊息登記程序ID

facility 為沒有指定設施的後續syslog呼叫指定一個預設值.

facility XSI 說明
LOG_AUDIT 審計設施
LOG_AUTH 授權程式: login, su, getty等
LOG_AUTHPRIV 與LOG_AUTH相同, 但寫日誌檔案時具有許可權限制
LOG_CONSOLE 訊息寫入 /dev/console
LOG_CRON cron和at
LOG_DAEMON 系統守護程序: inetd, routed等
LOG_FTP FTP守護程序(ftpd)
LOG_KERN 核心產生的訊息
LOG_LOCAL0 保留本地使用
LOG_LOCAL1 保留本地使用
LOG_LOCAL2 保留本地使用
LOG_LOCAL3 保留本地使用
LOG_LOCAL4 保留本地使用
LOG_LOCAL5 保留本地使用
LOG_LOCAL6 保留本地使用
LOG_LOCAL7 保留本地使用
LOG_LPR 行式印表機系統: lpd, lpc等
LOG_MAIL 郵件系統
LOG_NEWS Usenet網路新聞系統
LOG_NTP 網路時間協議系統
LOG_SECURITY 安全子系統
LOG_SYSLOG syslogd守護程序本身
LOG_USER 來自其他使用者程序的訊息(預設)
LOG_UUCP UUCP系統

3. syslog檔案

3.1 syslog檔案存放位置

Linux下呼叫syslog函式輸出的訊息就放在syslog檔案, 存放在/var/log/syslog. syslog檔案, 通常用於存放應用程式(守護程序)警告資訊.
其他日誌存放位置, 詳見: linux系統各種日誌儲存路徑和詳細介紹 | 部落格園

3.2 手動刪除syslog檔案

步驟:

  1. 刪除syslog檔案
    到/var/log/目錄下rm檔案
$ cd /var/log 
$ rm -f syslog  # 需要root許可權
  1. 重啟syslog服務
$ service syslog restart

參見: [LINUX]手動清理syslog | CSDN


4. 例程

同時向控制檯和syslog輸出包含PID的進度資訊, 1秒鐘更新10%, 到100%為止.

#include <syslog.h>
#include <unistd.h>
#include <stdio.h>

/**
 * linux下syslog存放位置 : /var/log/syslog
 */
int main()
{
    int i;
    puts("hello");

    /* LOG_CONS: 若無法傳送到syslogd守護程序則登記到控制檯; 
    LOG_PID: 隨每個日誌訊息登記程序PID;
    LOG_PERROR: 既傳送到syslogd守護程序,也傳送到stderr;
    LOG_USER: 任意的使用者級訊息(預設) */
    openlog("mysyslog", LOG_CONS | LOG_PID |  LOG_PERROR, LOG_USER);
    syslog(LOG_INFO, "system is starting..." );
    
    for (i = 0; i < 10; ++i) {
        
        syslog(LOG_WARNING | LOG_USER, "process %d\n", (i + 1) * 10);
        sleep(1);
    }
    
    closelog();
    return 0;
}

控制檯輸出結果:

$ ./a.out 
hello
mysyslog[26710]: system is starting...
mysyslog[26710]: process 10
mysyslog[26710]: process 20
mysyslog[26710]: process 30
mysyslog[26710]: process 40
mysyslog[26710]: process 50
mysyslog[26710]: process 60
mysyslog[26710]: process 70
mysyslog[26710]: process 80
mysyslog[26710]: process 90
mysyslog[26710]: process 100

syslog輸出結果: