日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 服务器程序规范、服务器日志、用户、进程间的关系

發布時間:2023/12/13 linux 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 服务器程序规范、服务器日志、用户、进程间的关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 服務器程序規范
  • 日志
    • rsyslogd 守護進程
    • syslog函數
    • openlog函數
    • setlogmask函數
    • closelog函數
  • 用戶
  • 進程間的關系
    • 進程組
    • 會話
    • 系統資源限制
    • 改變工作目錄和根目錄
    • 服務器程序后臺化


服務器程序規范

  • Linux 服務器程序一般以后臺進程(守護進程[daemon])形式運行。它沒有控制終端,因此不會意外接受到用戶輸入,守護進程的父進程通常是 init 進程(PID為1)。
  • 服務器的調試和維護都需要一個專業的日志系統,Linux 常用一個守護進程 rsyslogd(syslogd的升級版) 來處理系統日志。
  • Linux 服務器程序一般以 非root 的身份運行。如:mysqld、httpd、syslogd 等后臺進程分別擁有自己的運行賬戶 mysql、apache 和 syslog。
  • Linux 服務器程序通常能處理很多命令行選項,如果一次運行的選項太多,那么可以用配置文件來管理。配置文件一般放在 /etc 目錄下。
  • Linux 服務器程序通常在啟動時會生成一個記錄該后臺進程 PID 的文件并存入 /var/run 目錄中。例如: syslogd 的 PID 文件是 /var/run/syslogd.pid 。

  • 日志

    rsyslogd 守護進程

    既能接受用戶進程輸出的日志,也能接受內核日志。

    • 用戶進程調用 syslog函數 將日志輸出到一個 UNIX 本地域 socket 類型(AF_UNIX)的文件 /dev/log 中,rsyslogd 則監聽該文件以獲得用戶進程的輸出。
    • 內核日志由 printk 等函數打印至內核的 環狀緩存(ring buffer) 中,環狀緩存的內容直接映射到 /proc/kmsg 中,rsyslogd 讀取該文件以獲得內核日志。


    syslog函數

    應用程序通過 syslog函數 與 rsyslogd 守護進程通信:

    #include<syslog.h> void syslog( int priority, const char* message, ...); // 采用可變參數(message 和 第三個參數……)來結構化輸出 // priority:設施值與日志級別的按位或,設施值的默認值是 LOG_USER。

    限于 LOG_USER 設施值對應的日志級別有:

    #include<syslog.h> #define LOG_EMERG 0 // 系統不可用 #define LOG_ALERT 1 // 報警,需要立即采取動作 #define LOG_CRIT 2 // 非常嚴重的狀況 #define LOG_ERR 3 // 錯誤 #define LOG_WARNING 4 // 警告 #define LOG_NOTICE 5 // 通知 #define LOG_INFO 6 // 信息 #define LOG_DEBUG 7 // 調試

    openlog函數

    改變 syslog 的默認輸出方式,進一步結構化日志內容:

    #include<syslog.h> void openlog( const char* ident, int logopt, int facility ); // ident指定的字符串被添加到日志消息的日期和時間之后,通常被設置為程序的名字 // logopt對 syslog 調用的行為進行配置,為下列值的按位或: #define LOG_PID 0x01 // 在日志消息中博阿寒程序 PID #define LOG_CONS 0x02 // 如果消息不能記錄到日志文件,則打印至終端 #define LOG_ODELAY 0X04 // 延遲打開日志功能知道第一次調用 syslog #define LOG_NDELAY 0x08 // 不延遲打開日志功能 // facility用來修改 syslog 函數中的默認設施值

    setlogmask函數

    程序在開發階段可能需要輸出很多調試信息,而發布之后又需要將這些調試信息關閉。

    解決這個問題的方法并非是在發布后刪除調試代碼(日后可能還需要用到),而有更簡單的做法——設置日志掩碼,使日志級別大于掩碼日志信息被系統忽略。

    setlogmask函數 就用以設置日志掩碼:

    #include<syslog.h> int setlogmask( int maskpri ); // maskpri指定日志掩碼值 // 該函數始終會成功,返回調用進程舊的日志掩碼值

    closelog函數

    用以關閉日志功能:

    #include<syslog.h> void closelog();

    用戶

    服務器中不同的用戶有不同的權限,因此 獲取or設置 當前進程的 真實用戶ID(UID)、有效用戶ID(EUID)、真實組ID(GID)、有效組(EGID) 就尤為重要:

    #include <sys/types.h> #include <unistd.h> uid_t getuid(); uid_t geteuid(); gid_t getgid(); gid_t getegid(); int setuid( uid_t uid ); int seteuid( uid_t uid ); int setgid( gid_t gid ); int setegid( gid_t gid );

    一個進程有兩個 用戶ID: UID 和 EUID。EUID 方便了資源訪問:使得 運行程序的用戶 擁有 該程序的有效用戶 的權限。如:任何用戶都可以通過 su程序 修改自己的賬戶信息,這就不得不訪問需要 root 權限的 /etc/passwd 文件。那么以普通用戶身份啟動的 su程序 如何能訪問/etc/passwd 文件呢?

    用 ls 命令可以查看到,su程序 的所有者是 root,且被設置了 set-user-id標志 ,即任何普通用戶運行 su程序 時,su程序 的有效用戶為 root。有效用戶為 root 的進程被稱為 特權進程(privileged processes)

    類似的,EGID 為運行目標程序的組用戶提供有效組的權限。


    進程間的關系

    進程組

    Linux 下每個進程都隸屬于一個進程組,PGID 即為它的 進程組ID。進程組將一直存在,知道其中所有進程都退出或者加入到其他線程組。每個進程組都有一個首領進程,其 PGID 和 PID 相同。

    #include< unistd.h> pid_t getpgid( pid_t pid ); // 成功返回 ID,失敗返回 -1 并設置 errno int setpgid( pid_t pid, pid_t pgid ); // 將 PID 為 pid 的進程的 PGID 設置為 pgid,若 pid 和 pgid 相等,則 pid 指定的進程將被設定為進程組首領 // 若 pid=0,則表示設置 當前進程 的 PGID 為 pgid // 若 pgid=0,則使用 pid 作為目標進程的 PGID // 成功時返回 0,失敗返回 -1 并設置 errno

    一個進程只能設置自己或者子進程的 PGID,子進程調用 exec 系列函數后,父進程不再能設置它的 PGID。


    會話

    一些有關聯的進程組能形成一個會話(session),下面的函數用以創建一個會話:

    #include<unistd.h> pid_t setsid( void ); // 成功時返回新的進程組的 PGID,失敗則返回 -1 并設置 errno

    該函數不能由進程組的首領進程調用,否則產生一個錯誤。對于非組首領的進程,創建新會話的同時且有如下額外效果:

    • 調用進程成為會話的首領,此時該進程是新會話的唯一成員。
    • 新建一個進程組,其 PGID 就是調用進程的 PID,調用進程成為該組的首領。
    • 調用進程將甩開終端(如果有的話)。

    Linux 進程并未提供所謂 會話ID(SID) 的概念,但將會話首領所在的進程組的 PGID 視為 SID,并提供了如下函數來讀取 SID:

    #include<unistd.h> pid_t getsid( pid_t pid );

    系統資源限制

    Linux 上運行的程序都會受到資源限制的影響,比如物理設備限制(CPU數量、內存數量等)、系統策略限制(CPU時間等),以及具體實現的限制(文件名的最大長度)。這些系統資源限制可以通過下面的函數來讀取設置

    #include <sys/resource.h> int getrlimit( int resource, struct rlimit* rlim ); int setrlimit( int resource, const struct rlimit* rlim ); // 成功時返回 0,失敗時返回 -1 并設置 errno。 struct rlimit{rlim_t rlim_cur; // 指定資源的軟限制,是一個建議性的,最好不要超越的限制,若超越限制,則系統可能向進程發送信號以終止其運行。rlim_t rlim_max; // 指定資源的硬限制,一般是軟限制的上限。普通程序可以減小硬限制,只有以 root 身份運行的程序才能增加硬限制。// rlim_t是一個整數類型,描述資源級別。 };

    除上述外:

    • 還可以使用 ulimit 命令修改當前 shell 環境下的資源限制(軟限制或/和硬限制),這種修改將對該 shell 啟動的所有后續程序有效。
    • 還可以通過修改配置文件來改變系統軟限制和硬限制,這種修改是永久的。

    改變工作目錄和根目錄

    #include<unistd.h> /* 獲取進程當前工作目錄 */ char* getcwd( char* buf, size_t size ); // buf指向的內存用于存儲進程當前工作目錄的絕對路徑名,大小由 size 參數指定 // 如果當前工作的絕對路徑長度(加上末尾的“\0”)超過了 size,則返回 NULL 并設置 errno 為 ERANGE。 // 若 buf 為 NULL 并且 size 非 0,則 getcwd 可能在內部使用 malloc 動態分配內存,并將進程的當前工作目錄存儲在其中, // 此時我們需要自己釋放 getcwd 在內部創建的這塊內存。 // 成功返回一個指向目標存儲區(buf指向的緩存區或者getcwd在內部動態創建的緩存區)的指針,失敗返回 NULL 并設置 errno。/* 改變進程的工作目錄 */ int chdir( const char* path ); // path 指定要切換到的目標目錄 // 成功返回 0,失敗返回 -1 并設置 errno/* 改變進程根目錄 */ int chroot(const char* path); // 參數和返回值同上,調用本函數后,仍需使用 chdir("/") 來將工作目錄切換至新的根目錄。 // 改變進程的根目錄后,程序可能無法訪問處于舊路徑的文件or目錄, // 不過可以利用進程已經打開的文件描述符來訪問調用 chroot 之后不能直接訪問的文件。 // 只有特權進程才能改變根目錄

    服務器程序后臺化

    讓一個進程以守護進程的方式運行:

    #include<unistd.h> int daemon(int nochdir, int noclose); // nochdir 用于指定是否改變工作目錄,為 0 則工作目錄被設置為“/”(根目錄),否則繼續使用當前目錄 // noclose 為 0 時,標準輸入、輸出、錯誤輸出都被重定向到 /dev/null 文件,否則依然使用原來的設備 // 成功返回 0,失敗返回 -1 并設置 errno

    總結

    以上是生活随笔為你收集整理的Linux 服务器程序规范、服务器日志、用户、进程间的关系的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。