轉自:https://www.cnblogs.com/vigarbuaa/archive/2013/02/05/2892544.html
Linux下C語言編程的-把程序輸出信息加到系統日志里去
關鍵詞: Linux 系統日志 syslog 服務程序 syslogd
我們的程序一般都會產生輸出信息。但是服務器程序一般卻不希望輸出信息到屏幕上,因為沒有人盯着你的程序執行。所以我們要把一些信息寫成日志文件,正常情況下運行程序的人不用關心日志里的內容,只有在出現問題的時候才會查看日志文件里的內容以確定問題所在。
但如果我們的程序要自己生成一個文件來保存日志卻不是好主意,因為這一方面增加了維護程序運行的人的負擔,另一方面自己維護起系統來也多有不便。
在Linux系統中有一個系統日志,通常放在/var/log目錄下,比如文件名是syslog的,系統中的一些程序產生的日志信息都會存放到這個文件里。日志文件有固定的格式,比如第1列是消息產生的時間,第2列是機器名(因為日志記錄程序支持遠程連接),第3列是標記信息(一般就是程序名稱)等。而且對應的有一些工具來對這個日志進行維護,比如通過輪回機制保證日志文件大小不會把磁盤空間占盡。所以我們把自己程序的信息也寫到這個系統日志里是比較好的想法。
在GNU C語言庫提供的內容中,有接口可以用來做這件事。用下面的命令查看:
nm -D /lib/libc.so.6 | grep log
可以看到一些調用:
000b9410 T closelog
0008b870 T getlogin
0008b960 T getlogin_r
000d0180 T __getlogin_r_chk
000bd190 T klogctl
00027450 T __open_catalog
000b9380 T openlog
0008bae0 T setlogin
000b8b80 T setlogmask
000b9350 T syslog
000b9320 T __syslog_chk
000b92f0 T vsyslog
000b8da0 T __vsyslog_chk
這里面的三個函數openlog, syslog, closelog是一套系統日志寫入接口。另外那個vsyslog和syslog功能一樣,只是參數格式不同。
程序的用法示例代碼如下:
#include <syslog.h>
int main(int argc, char **argv)
{
openlog("MyMsgMARK", LOG_CONS | LOG_PID, 0);
syslog(LOG_DEBUG,
"This is a syslog test message generated by program '%s'/n",
argv[0]);
closelog();
return 0;
}
編譯生成可執行程序后,運行一次程序將向/var/log/syslog文件添加一行信息如下:
Feb 12 08:48:38 localhost MyMsgMARK[7085]: This is a syslog test message generated by program './a.out'
openlog及closelog函數說明
此函數原型如下:
void openlog(const char *ident, int option, int facility);
此函數用來打開一個到系統日志記錄程序的連接,打開之后就可以用syslog或vsyslog函數向系統日志里添加信息了。而closelog函數就是用來關閉此連接的。
openlog的第一個參數ident將是一個標記,ident所表示的字符串將固定地加在每行日志的前面以標識這個日志,通常就寫成當前程序的名稱以作標記。第二個參數option是下列值取與運算的結果:LOG_CONS, LOG_NDELAY, LOG_NOWAIT, LOG_ODELAY, LOG_PERROR, LOG_PID,各值意義請參考man openlog手冊:
LOG_CONS
Write directly to system console if there is an error while sending to system logger.
LOG_NDELAY
Open the connection immediately (normally, the connection is opened when the first message is logged).
LOG_NOWAIT
Don’t wait for child processes that may have been created while logging the message. (The GNU C library does not create a
child process, so this option has no effect on Linux.)
LOG_ODELAY
The converse of LOG_NDELAY; opening of the connection is delayed until syslog() is called. (This is the default, and need
not be specified.)
LOG_PERROR
(Not in SUSv3.) Print to stderr as well.
LOG_PID
Include PID with each message.
第三個參數指明記錄日志的程序的類型。
void openlog( char *ident, int option, int facility)
void syslog( int priority, char *format, ...)
void closelog( void )
option
用於openlog()的option參數可以是以下幾個的組合:
LOG_CONS : 如果送到system logger時發生問題,直接寫入系統console。
LOG_NDELAY : 立即開啟連接(通常,連接是在第一次寫入訊息時才打開的)。
LOG_PERROR : 將訊息也同時送到stderr
LOG_PID : 將PID含入所有訊息中
facility
facility參數用來指定何種程式在記錄訊息,這可讓設定檔來設定何種訊息如何處理。
LOG_AUTH : 安全/授權訊息(別用這個,請改用LOG_AUTHPRIV)
LOG_AUTHPRIV : 安全/授權訊息
LOG_CRON : 時間守護神專用(cron及at)
LOG_DAEMON : 其它系統守護神
LOG_KERN : 核心訊息
LOG_LOCAL0到LOG_LOCAL7 : 保留
LOG_LPR : line printer次系統
LOG_MAIL : mail次系統
LOG_NEWS : USENET news次系統
LOG_SYSLOG : syslogd內部所產生的訊息
LOG_USER(default) : 一般使用者等級訊息
LOG_UUCP : UUCP次系統
level
決定訊息的重要性. 以下的等級重要性逐次遞減:
LOG_EMERG : 系統無法使用
LOG_ALERT : 必須要立即采取反應行動
LOG_CRIT : 重要狀況發生
LOG_ERR : 錯誤狀況發生
LOG_WARNING : 警告狀況發生
LOG_NOTICE : 一般狀況,但也是重要狀況
LOG_INFO : 資訊訊息
LOG_DEBUG : 除錯訊息
syslog函數及參數
syslog函數用於把日志消息發給系統程序syslogd去記錄,此函數原型是:
void syslog(int priority, const char *format, ...);
第一個參數是消息的緊急級別,第二個參數是消息的格式,之后是格式對應的參數。就是printf函數一樣使用。
如果我們的程序要使用系統日志功能,只需要在程序啟動時使用openlog函數來連接syslogd程序,后面隨時用syslog函數寫日志就行了。
另外,作為syslog的替代程序的新一代工具是syslog-ng,syslog-ng具有很強的網絡功能,可以方便地把多台機器上的日志保存到一台中心日志服務器上。