【问题标题】:Tie the life of a process to the shell that started it将进程的生命周期与启动它的 shell 联系起来
【发布时间】:2010-12-23 08:34:33
【问题描述】:

以 UNIX-y 方式,我尝试启动一个进程,将其置于后台,并将该进程的生命周期绑定到我的 shell。

我所说的不仅仅是后台处理进程,我希望向进程发送 SIGTERM,或者让它有一个关闭的打开文件描述符,或者 something 当shell 退出,因此 shell 的用户不必显式终止进程或收到“您有正在运行的作业”警告。

最终我想要一个程序,它可以为每个 shell 唯一地运行,并与该 shell 一起携带状态,并在 shell 关闭时关闭。

IBM 的 DB2 控制台命令以这种方式工作。当您连接到数据库时,它会生成一个“db2bp”进程,该进程携带数据库状态和连接并将其绑定到您的 shell。您可以在多个不同的终端或 ssh 连接中进行连接,每个都有自己的 db2bp 进程,当这些连接关闭时,相应的 db2bp 进程就会终止,并且该连接也将关闭。

然后使用 db2 命令启动 DB2 查询,该命令只是将其交给适当的 db2bp 进程。我不知道它是如何与正确 db2bp 进程通信的,但也许它使用连接到stdin 的tty 设备作为唯一键?我想我也需要弄清楚这一点。

我从来没有写过任何 tty 操作的东西,所以我什至不知道从哪里开始。如果我可以生成一个在 shell 退出时自动终止的进程,我想我可以解决剩下的问题。有谁知道 DB2 是怎么做到的?

【问题讨论】:

    标签: unix shell process db2 terminal


    【解决方案1】:

    如果您的外壳不是子外壳,您可以执行以下操作;将以下内容放入名为“ttywatch”的脚本中:

    #!/usr/bin/perl
    my $p=open(PI, "-|") || exec @ARGV; sleep 5 while(-t); kill 15,$p;
    

    然后运行你的程序:

    $ ttywatch commandline... & disown
    

    不拥有该进程将防止shell抱怨有正在运行的进程,并且当终端关闭时,它会导致SIGTERM(15)在5秒内传递给子进程(您的应用程序)。

    如果shell不是子shell,你可以使用ttywrap之类的程序至少给它自己的tty,然后上面的技巧就可以了。

    【讨论】:

    • 是的,这行得通!我弄清楚了 db2 是如何做到的,这并不完全相同,但这是如此简短和简单。不过,我的 perl 并不是那么好……什么是 while(-t) 测试?
    • 啊,找到了。 -t 默认为标准输入,并测试文件是否打开到 tty... 非常漂亮。
    【解决方案2】:

    好吧,我想我明白了。我把它弄得太复杂了:)

    我认为所有 db2 都在对 db2bp 进行守护进程,然后 db2bp 在父 PID(shell 的 PID)上调用 waitpid 并在 waitpid 返回后退出。

    db2 命令和 db2bp 之间的通信似乎是通过 fifo 完成的,文件名基于父 shell PID。

    Waaaay 比我想象的要简单 :)

    对于任何好奇的人来说,整个努力是为了能够将 python 或 groovy 交互式会话绑定到 shell,这样我就可以在测试代码的同时轻松地跳入和跳出保留数据库连接和临时类的会话/ 变量。

    感谢大家的帮助!

    【讨论】:

      【解决方案3】:

      您真正的问题是否可能是外壳而不是您的进程。我的理解同意吉姆·刘易斯的观点,即当外壳死亡时,它的孩子应该得到 SIGHUP。但是您抱怨的是 shell(或者可能是终端)试图阻止您意外杀死一个正在运行的带有活动子代的 shell。

      考虑阅读 shell 或终端的手册,看看此行为是否可配置。

      来自我 MacBook 上的 bash 手册:

      shell 在收到 SIGHUP 后默认退出。在退出之前,交互式 shell 会重新发送 SIGHUP 所有作业,运行或停止。停止的作业被发送 SIGCONT 以确保它们收到 SIGHUP。到 防止外壳将信号发送到特定作业,应将其从作业表中删除 disown 内置命令(参见下面的 SHELL BUILTIN COMMANDS)或使用 disown -h 标记为不接收 SIGHUP。

      如果已经使用 shopt 设置了 huponexit shell 选项,bash 会在交互时向所有作业发送 SIGHUP 登录 shell 退出。

      这可能会为您指明正确的方向。

      【讨论】:

      • 是的,但我不应该那样做。我以前没有看过,但我确实在 bash 和 zsh 手册页中找到了该选项。不过,我不应该必须这样做。是的,我可以将 bash 或 zsh 配置为在所有后台进程退出后kill,即使联机帮助页建议不要这样做,但 DB2 似乎不需要它,而且它现在可以工作。 DB2 是如何做到的?
      • '恐怕我帮不上什么忙。我同意这是一个理想的功能,只是不知道该怎么做。
      • 好吧,纠正我自己,他们并没有被杀死——就像你说的,他们正在被 SIGHUP 编辑 :) 而且,只有 zsh 手册页建议总是一起使用 NO_CHECK_JOBS 和 NO_HUP .但是,我不应该重新配置我的 shell
      【解决方案4】:

      您的 shell 在关闭时应该向任何正在运行的子进程发送 SIGHUP 信号。您是否尝试将 SIGHUP 处理程序添加到您的应用程序以干净地关闭它 外壳何时退出?

      【讨论】:

      • 我刚刚尝试过,但我认为它不起作用。如果你背景这个 python 进程: import os, sys, time, signal def handler(signum, frame): print 'Exiting after catched with signal', signum sys.exit(0) signal.signal(signal.SIGHUP, handler) while正确:time.sleep(1) 然后 shell 仍然抱怨退出时正在运行作业(或者,如果配置为,只会让进程永远运行)。在我杀死 -SIGHUP 之前,似乎不会向该进程发送 SIGHUP。
      猜你喜欢
      • 1970-01-01
      • 2015-01-15
      • 2013-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      • 1970-01-01
      相关资源
      最近更新 更多