后台进程 (postgresql) 从 shell 中的 Ctrl-C 接收 SIGINT

后台进程 (postgresql) 从 shell 中的 Ctrl-C 接收 SIGINT

我写了一个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 $-产生。imBHset -m

我注意到在我的交互式 shell 中(无论是否为 nix-shell),$-imBHs.上下文s中不存在,shellHook并且我在 Bash 内置文档中找不到其含义的解释set。但这可能不相关...

答案1

手册说

启动模式启动一个新服务器。 ...在类Unix系统上,默认情况下,服务器的标准输出和标准错误被发送到pg_ctl的标准输出(不是标准错误)。然后 pg_ctl 的标准输出应该被重定向到一个文件或通过管道传输到另一个进程,例如像rotatelogs这样的日志轮换程序;否则postgres 会将其输出写入控制终端(从后台)并且不会离开shell的进程组。 ...建议使用 -l 或输出重定向

看来您需要重定向输出以将 pg_ctl 从 shell 中分离。

答案2

问题似乎在于 postgresql 服务器作为与通过 启动它的 shell 相同的进程组的一部分运行pg_ctl。键入 a 会将 a 传播SIGINT到组中的所有进程。

解决此问题的一种方法是使用 . 在自己的会话中启动 postgresql setsid

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

也就是说,我仍然不知道为什么这只发生在shellHook.

相关内容