发送信号到 tmux 窗格中的进程

发送信号到 tmux 窗格中的进程

假设应用程序 X 在 tmux 窗格的前台运行。我想向应用程序 X 发送给定信号,例如 SIGUSR1。我可以配置 tmux 键绑定以向当前选定窗格的前台进程(或进程组)发送信号吗?

答案1

在我的 Kubuntu 中,ps可以给我进程所连接的终端上的前台进程组的 ID。关键字是tpgid.如果我告诉查询由asps标识的进程,那么我将在此窗格中获取前台进程组 ID。tmux#{pane_pid}

以下绑定(在 中~/.tmux.conf)会将prefixkSIGUSR1 发送到前台进程组(默认prefixCtrl+ b):

bind-key k run-shell 'kill -s USR1 -- "-$(ps -o tpgid:1= -p #{pane_pid})"'

笔记:

  • 前面的破折号(-$(…)负责定位前台进程团体。您可以尝试不使用破折号,仅针对一个进程;它将成为前台进程组的“领导者”。但不能保证“领导者”(仍然)存在。以组为目标是一种明智的方法,它类似于Ctrl+c向组发送 SIGINT,尽管机制不同。

  • :1摘自这个答案:设置ps命令输出的格式,不含空格。当我们在前面添加破折号时,摆脱前导空格至关重要。

  • 有一个竞争条件:kill在之后执行ps,并且不能保证进程组仍然在前台(或根本存在)。

  • 您可能会不幸地prefixk在您想要定位的进程退出时遇到问题。这样您可能会无意中将 SIGUSR1 发送到另一个进程。可能是外壳。进而…

  • SIGUSR1 的默认操作是终止。特别是,处于前台的交互式 shell(即等待命令)可能会在prefixk.巴什确实如此。您可以通过预先设置陷阱来防止这种情况:

    • trap '' USR1将使 shell 忽略该信号。在这种情况下,子进程也将忽略该信号,除非它们明确选择处理它(例如dd这样做)。
    • trap : USR1将使 shell“忽略”该信号(通过不执行任何操作来做出反应),但这不会影响子进程的行为。

答案2

Tmux 提供了pane_pid,但这将是窗格中最顶层进程的 PID,该进程通常是 shell。您需要深入挖掘才能找到前台进程的 PID,但您可以将其用作pane_pid起点。

简单版本——类似:

bind k run-shell "kill -s SIGUSR1 $(cat /proc/#{pane_pid}/task/#{pane_pid}/children)"

我相信如果窗格中没有后台进程,这应该可行。

如果您可能有多个同级进程在 shell 中运行,其中一些进程处于后台,那么情况会变得更加复杂。我相信您需要执行类似 use 的ps -h --ppid #{pane_pid} -O stat操作来获取 的子进程pane_pid,然后确定其中哪一个在前台运行(即列+中有STAT),并解析出该 PID。

一种可能的实现:

bind k run-shell "kill -s SIGUSR1 $(ps -h --ppid #{pane_pid} -O stat | grep -o '^[[:blank:]]*[[:digit:]]\\+[[:blank:]]\\+[^[:blank:]]*+' | cut -d ' ' -f2)"

然而,如果有的话,这仍然会失败子进程(即窗格中的前台进程是 shell 本身)。

当然,如果您需要将其稳健性提升到一个新的水平,请将其移至 shell 脚本并检查是否确实存在发送信号之前的子进程。

相关内容