顯示具有 System 標籤的文章。 顯示所有文章
顯示具有 System 標籤的文章。 顯示所有文章

2020年8月7日 星期五

PROCESS GROUPS, SESSIONS, AND JOB CONTROL

一個 job 是一個指令或指令串,形成一個 process group。透過一個控制終端機 (Controlling Terminal) 可以進行多個 job,都屬於同一個 session (譯作「作業階段」),其中一個是 foreground process group,剩下都是 background process group,方便工作控制 (job control)。

建立 session 的 process 是 session leader,其 process ID (PID) 作為 session ID (SID),並連接一個 session 專用的控制終端機並成為其控制 process,讓使用者控制,其中 foreground process group 讀取控制終端機。Signal SIGINT (Ctrl-C)、SIGQUIT (Ctrl-\)、和 SIGSTP (Ctrl-Z) 會送到 foreground process group 中的所有 process。當控制終端機斷線時,控制 process 會收到 SIGHUP。

建立 process group 的 process 是 process group leader,其 PID 作為 process group ID (PGID)。process group 最後一個 process 結束或離開時結束。process group leader 未必是最後一個 process。

新 process 繼承親 process 的 SID、PGID、控制終端機等。檔案 /proc/PID/stat 可看到 PGID、SID、控制終端機的 major:monor ID 和控制 process 的 PID (見 proc(5))。

互動式登入時,登入的途徑是控制終端機,登入的 shell 成為 session leader 及控制行程,也是唯一 process group 的唯一成員。然後,從 shell 啟動的每個指令或指令串,都會建立一個或多個 process,全部收納在一個新的 process group。如果指令或指令串以 & 符號結束時,這個 process group 會在背景執行。這些都在同一個 session 下。

在視窗環境,控制終端機是 pseudoterminal,每個終端機視窗有獨立的 session,視窗起始的 shell 是 session leader。

除了 job 控制,process 群組偶而也用在別的地方,因為群組有兩個有用的特點:parent process 可以等候特定群組的任一個 children (TLPI §26.1.2),和 signal 可以送給一個群組的全部成員 (TLPI §20.5)。

範例

$ echo $$                       # Display the PID of the shell
400
$ find / 2> /dev/null | wc -l & # Create 2 processes in background group
[1] 659
$ sort < longlist | uniq -c     # Create 2 processes in foreground group
此時,shell bashfindwcsort、和 uniq 都在執行,全部屬於同一 session,session leader 是 bash,同時也是控制 process,其它 process 都是 bash 產生。session 全部分成三個群組,前景執行的群組是 sortuniqsort 是群組 leader。另外兩個群組背景執行,一個是 bash,另一個是 findwcfind 是群組 leader。
$ echo $$                       # Display the PID of the shell
4056
$ find / 2> /dev/null | wc -l & # Create 2 processes in background group
[1] 5781
$ ps -s 4056 -o comm,pid,sess,tt,pgrp,ppid,tpgid,state
COMMAND           PID  SESS TT        PGRP  PPID TPGID S
bash             4056  4056 pts/2     4056  1579  5782 S
find             5780  4056 pts/2     5780  4056  5782 R
wc               5781  4056 pts/2     5780  4056  5782 S
ps               5782  4056 pts/2     5782  4056  5782 R

用 ps 可看出各自指令的資訊,其中一開始的 shell 是 bash,PID 4056。SID (SESS) 等於 PID,所以是 session leader,連接終端機 pts/2。PGID (PGRP) 等於 PID,是群組 leader。沒其它 process 的 PGID 為 4056,是群組中唯一 process。parent PID (PPID) 是其它 process,但其它 process 都是 4056,也就是都是其產生。TPGID 可看出前景執行的群組是 5782,也就是 ps 指令,其它群組 4056 和 5780 都背景執行。5780 群組的指令包含 find 和 wc 兩個 process。

pid_t getpgrp(void); // 取得 PGID,如果和 PID 一致則是 process group leader

int setpgrp(pid_t pid, pid_t pgid); // 將 pid 的 porcess group 設為 pgid。pid 可以是自己或子 process (不能是 SID)。pgid ...

參考來源

TLPI §34.1

34.2 Process Groups
34.3 Sessions
34.4 Controlling Terminals and Controlling Processes
34.5 Foreground and Background Process Groups
34.6 The SIGHUP Signal
34.6.1 Handling of SIGHUP by the Shell
34.6.2 SIGHUP and Termination of the Controlling Process
34.7 Job Control
34.7.1 Using Job Control Within the Shell
34.7.2 Implementing Job Control
34.7.3 Handling Job-Control Signals
34.7.4 Orphaned Process Groups (and SIGHUP Revisited)
34.8 Summary
34.9 Exercises

2018年8月12日 星期日

syslog: syslog() and syslogd

syslog 收集應用程式和 Kernel 產生的執行紀錄,執行紀錄含有分類和等級,讓系統管理員好監控管理。
  • 標準函數 syslog() 將紀錄放到 socket /dev/log。
  • daemon syslogd 接收 /dev/log 和 UDP port 514 的訊息,依據設定檔 syslog.conf 中對於分類和等級的規則,選擇將紀錄訊息導到終端機、FIFO、硬碟、遠端、或登入的使用者。
  • 遠端可能是另一個 syslogd,更進一步集中紀錄,也可以有備份紀錄的作用。
  • process 用標準函數 syslog() 產生紀錄。
  • kernel 用 printk() 產生紀錄,經過系統呼叫 syslog() 或 /proc/kmsg 給 daemon klogd 收集。klogd 再呼叫標準函式 syslog()。
  • 遠端產生的紀錄傳給 UDP port 514。
註:glibc 提供 klogctl() 使用系統呼叫 syslog()。
擷取自 TLPI Figure 37-1

syslog API

#include <syslog.h>

/* 開啟和關閉,非必要 */
void openlog(const char *ident, int option, int facility);
void closelog(void);

/* 產生紀錄 */
void syslog(int priority, const char *format, ...);
void vsyslog(int priority, const char *format, va_list ap);
這些函數都沒回傳值,因為會假設 syslog 系統都會正常。如果 syslog 系統出錯,那也就無處回報,系統管理員應該會先注意到。

syslog() 或 vsyslog()  產生紀錄,priority 是分類和等級的 OR 組合,format 之後的參數和 printf() 和 vprintf() 仝款,不同的是 syslog() 會自動在最後加上換行,另外「%m」會取代為目前 errno 的錯誤字串,相當於 strerror(errno)。
分類 (facility)名稱說明
0LOG_KERNkern來自 Kernel。user process 使用會轉為 user。
1LOG_USERuser來自 user process (預設)
2LOG_MAILmail來自郵件系統。
3LOG_DAEMONdaemon來自其它系統 daemons。
4LOG_AUTHauth (security)Security 或 authorization 訊息 (e.g., su)
5LOG_SYSLOGsyslog來自 syslogd 內部。
6LOG_LPRlpr來自印表機系統 (lpr, lpd, lpc)。
7LOG_NEWSnews來自 Usenet 網路新聞。
8LOG_UUCPuucp來自 UUCP 系統
9LOG_CRONcron來自 cron 和 at daemons。
10LOG_AUTHPRIVauthprivPrivate 的 security 或 authorization 訊息。訊息包含密碼或其它敏感資訊位置不同於 LOG_AUTH。
11LOG_FTPftp來自 ftpd。
16
~
23
LOG_LOCAL0
~
LOG_LOCAL7
local0
~
local7
保留為本機使用。

等級 (level)名稱說明
0LOG_EMERGemerg (panic)系統當機或無法使用
1LOG_ALERTalert需要立即處理 (例如系統資料庫毀壞)
2LOG_CRITcrit危急發生 (例如硬碟裝置錯誤)
3LOG_ERRerr (error)錯誤發生
4LOG_WARNINGwarning (warn)警告發生
5LOG_NOTICEnotice正常,但需要注意
6LOG_INFOinfo一般資訊
7LOG_DEBUGdebug除錯訊息


none

syslog() 用下列方式輸出使用者提供的字串是危險的:

syslog(priority, user_supplied_string);
如果使用者提供的字串包含 format specifiers (例如 %s),無法預期造成什麼結果。較安全作法是改用:
syslog(priority, "%s", user_supplied_string);

openlog():改變使用 syslog() 的預設值,開啟 /dev/log。
  • ident:每個訊息前要加的字串,通常是程式名稱。NULL 時,glibc 自動用程式名稱,但不是所有實作皆如此。註:openlog() 只複製字串指標,沒複製字串內容。
  • option:下列 bit mask 組合。
    • LOG_CONS:訊息寫到 /dev/console。
    • LOG_PERROR:訊息也寫一份到 standard error。(非 SUSv3 標準)
    • LOG_PID:訊息包含 process ID 供辨別。
    • LOG_NDELAY 和 LOG_ODELAY (預設 LOG_ODELAY):LOG_ODELAY 在 log 第一個訊息時才連結到 /dev/log。LOG_NDELAY 則是立刻連結到 /dev/log,例如用在 chroot()。chroot() 後 /dev/log 就看不到了,需要事先 LOG_NDELAY openlog(),tftpd 就是如此使用。
    • LOG_NOWAIT:不 wait() log 訊息的 child process 建立。在 Linux 並不建立 child process,所以沒作用。
  • facility:facility 預設是 LOG_USER,這裡可以提供 syslog() 未指定時的預設分類。
closelog():關閉 /dev/log。如果 daemon 持續在跑並不需要。

過濾 log 訊息

int setlogmask (int mask_priority );
預設不過濾。LOG_MASK() 將 level 轉換成 mask_priority 用的 bit mask,訊息 level 不在目前的 mask_priority 會丟棄。回傳原本的 mask_priority。
setlogmask(LOG_MASK(LOG_EMERG) | LOG_MASK(LOG_ALERT) | LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ERR));
大部份實作也提供 LOG_UPTO(),建立特定 level 以上的 mask_priority:
setlogmask(LOG_UPTO(LOG_ERR));

logger 指令

logger 是用指令方式產生紀錄訊息到 syslog,可指定 level、ident 等。

設定檔 /etc/syslog.conf

/etc/syslog.conf 是 syslogd 的設定檔,內容格式如下:
facility.level action # 註解
設定符合 facility.level 的訊息所要進行的動作 (action)。facility 指定分類,「*」表示全部。level 指定某個等級以上,其中 debug 是最低的,表示所有等級,有些實作 (包括 Linux) 也可以用「*」。等級 none 則排除符合的分類。多個 facility.level 可用「;」隔來共用 action。一些例子:
*.err /dev/tty10
auth.notice root
*.debug;mail.none;news.none -/var/log/messages

action 可能是

  • 檔案。寫入的檔案,前置「-」表示每次寫入不進行 sync (TLPI §13.3),可以有較快的寫入速度,但當機可能會造成資料流失。
  • 裝置。特定終端機 /dev/tty10 console device
  • 使用者名稱。如 root 登入的終端機。
  • 遠端主機

修改 syslog.conf 後,需要送 SIGHUP 叫 syslogd 重新初始化:

$ killall -HUP syslogd

參考

  1. TLPI §37.5 全部
  • man-page syslog.conf(5) (不存在?)
  • OpenWrt AA 以前用 busybox syslogd 和 logread,BB 以後用 ubox logd 和 logread。
  • RFC 5424: The Syslog Protocol
  • 限制:
  • http://linux.vbird.org/linux_basic/0570syslog.php
  • http://taiwanwolf.blogspot.com/2011/08/centos-6-rsyslogd-log.html
  • journald
  • 思考
    • 一種儲存 log 的方式或者檔案系統,隨時存 log、當機不會造成損毀,又盡量延長 flash 使用壽命。
    • log merge:隨著進展,更新某項 log 內容,只需要最後的情況。
    • 非文字的 log。
    • 動作是執行程式?

2018年7月17日 星期二

TLPI: DAEMONS Overview

daemon 是有下列特性的 process:
  • 常駐的。通常在系統起始時建立,運作到系統結束。
  • 背景執行,且沒有控制終端機。由於缺乏終端機,要確保 kernel 不會自動生任何 job 控制或終端相關 signals (如 SIGINT、SIGTSTP、SIGHUP) 給 daemon。
daemon 用來執行特定工作,例如:
  • cron:在排定的時間執行指令。
  • sshd:使用 secure communication protocol 遠端登入的 secure shell daemon。
  • httpd:HTTP 伺服器 daemon,提供網頁。
  • inetd:Internet 超級伺服器 daemon (見 TLPI §60.5),在特定 TCP/IP 埠等待網路連線,啟動對應的伺服器程式處理。
daemon 常習慣取名以子母 d 為結尾。

許多標準 daemon 是特權行程 (也就是 effective user ID 是 0),因此應該依照 TLPI §38 的準則撰寫。

在 Linux,有些 daemon 是 kernel thread,是 kernel 的一部分。當用 ps 指令列出時,名稱會用 [] 包起來,例如 [pdflush],週期 flushes dirty pages 到硬碟。

參考來源:TLPI §37.1

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...