Background-Process

後台程序(postgresql)在 shell 中從 Ctrl-C 接收 SIGINT

  • August 10, 2018

我寫了一個shell.nix文件來為我的一個項目建構開發環境。我使用 ashellHook來確保在您進入nix-shell.

shellHook本質上是:

export PGDATA=$PWD/nix/pgdata

pg_ctl start --silent --log $PWD/log/pg.log

儘管pg_ctl在後台啟動伺服器,但如果我在 shell 中鍵入 Ctrl-C,伺服器就會關閉。如果我在 nix-shell 之外設置相同的場景,則不會發生這種情況。

我是 strace 的新手,但在我看來,SIGINT當我在終端中鍵入 Ctrl-C 時,postgresql 程序正在接收:

$ strace -p $postgres_pid
strace: Process 20546 attached
select(6, [3 4 5], NULL, NULL, {tv_sec=51, tv_usec=289149}) = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
rt_sigprocmask(SIG_SETMASK, ~[ILL TRAP ABRT BUS FPE SEGV CONT SYS RTMIN RT_1], NULL, 8) = 0
write(2, "LOG:  received fast shutdown req"..., 37) = 37
kill(20550, SIGTERM)                    = 0
...

postgresql 程序與我的 nix-shell 程序連接到同一個控制終端 ( pts/12)(儘管當我在 nix-shell 之外執行它時也是如此):

$ ps -p ${postgres_pid},${nixshell_pid} -o pid,ppid,wchan,tty,cmd
 PID  PPID WCHAN  TT       CMD
14608 18292 core_s pts/12   bash --rcfile /tmp/nix-shell-14608-0/rc
16355     1 core_s pts/12   /nix/store/xxxxxx-postgresql-9.6.8/bin/postgres

調試這個好的下一步是什麼?我應該閱讀程序組嗎?

更新:嘗試另一個問題的提示,我發現這解決了問題:

set -m
pg_ctl start --silent --log $PWD/log/pg.log

奇怪的是,根據$-,該m選項已經設置。執行在. echo $-_imBH``set -m

我注意到在我的互動式 shell(無論是否 nix-shell)中,$-imBHs. 上下文中s不存在,我在 Bash內置shellHook的文件中找不到其含義的解釋。set雖然這可能不相關……

似乎問題在於 postgresql 伺服器與通過pg_ctl. 鍵入將 a 傳播SIGINT到組中的所有程序。

解決此問題的一種方法是使用setsid.

setsid pg_ctl start --silent --log $PWD/log/pg.log

也就是說,我仍然不知道為什麼這只發生在shellHook.

手冊說

啟動模式啟動一個新伺服器。… 在類 Unix 系統上,預設情況下,伺服器的標準輸出和標準錯誤被發送到 pg_ctl 的標準輸出(不是標準錯誤)。然後 pg_ctl 的標準輸出應該被重定向到一個文件或通過管道傳送到另一個程序,例如像 rotatelogs 這樣的日誌輪換程序;否則postgres 會將其輸出寫入控制終端(從後台),並且不會離開 shell 的程序組。…建議使用 -l 或輸出重定向

看來您需要重定向輸出以從外殼中分離 pg_ctl 。

引用自:https://unix.stackexchange.com/questions/460955