Jasha Asked: 2022-01-16 04:20:19 +0800 CST2022-01-16 04:20:19 +0800 CST 2022-01-16 04:20:19 +0800 CST 在 tmux 窗格中向进程发送信号 772 假设应用程序 X 正在 tmux 窗格的前台运行。我想向应用 X 发送一个给定的信号,例如 SIGUSR1。我可以配置一个 tmux 键绑定来向当前选择的窗格的前台进程(或进程组)发送信号吗? keyboard-shortcuts process 2 个回答 Voted Best Answer Kamil Maciorowski 2022-01-17T11:40:53+08:002022-01-17T11:40:53+08:00 在我的 Kubuntups中,可以给我进程连接到的终端上的前台进程组的 ID。关键字是tpgid。如果我告诉ps查询由tmuxas标识的进程,#{pane_pid}那么我将在此窗格中获得前台进程组 ID。 以下绑定(in ~/.tmux.conf)将使prefixkSIGUSR1 发送到前台进程组(默认prefix为Ctrl+ b): bind-key k run-shell 'kill -s USR1 -- "-$(ps -o tpgid:1= -p #{pane_pid})"' 笔记: 前面的破折号( -)$(…)负责定位前台进程组。您可以尝试不使用破折号仅针对一个进程;它将是前台进程组“领导者”。但不能保证“领导者”(仍然)存在。以群组为目标是一种理智的方法,它类似于Ctrl+c向群组发送 SIGINT,尽管机制不同。 :1取自这个答案:Format pscommand output without whitespace。当我们添加破折号时,去掉前导空格是至关重要的。 有一个竞争条件:kill在之后行动ps并且不能保证进程组仍然在前台(或根本存在)。 您可能会很不幸,并且prefixk在您想要定位的进程退出的时候遇到了问题。这样您可能会无意中将 SIGUSR1 发送到另一个进程。它可能是外壳。接着… SIGUSR1 的默认操作是终止。特别是您的交互式 shell 在前台(即等待命令)可能会在prefixk. 巴什会。您可以通过预先设置陷阱来防止这种情况: trap '' USR1将使外壳忽略信号。在这种情况下,子进程也将忽略该信号,除非它们明确选择处理它(例如dd这样做)。 trap : USR1将使外壳“忽略”信号(无所作为做出反应),但这不会影响子进程的行为。 NotTheDr01ds 2022-01-16T23:36:37+08:002022-01-16T23:36:37+08:00 Tmux 提供pane_pid, 但这将是窗格中最顶层进程的 PID,它通常是 shell。您需要更深入地挖掘才能找到前台进程的 PID,但您可以将pane_pid其用作起点。 简单版本——类似: bind k run-shell "kill -s SIGUSR1 $(cat /proc/#{pane_pid}/task/#{pane_pid}/children)" 我相信如果窗格中没有后台进程,这应该可以工作。 如果您可能在 shell 中运行多个同级进程,其中一些是后台进程,那么它会变得有点复杂。我相信您需要执行类似 useps -h --ppid #{pane_pid} -O stat的操作来获取 的子进程pane_pid,然后确定其中哪一个在前台运行(即列+中有 a 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 脚本并在发送信号之前检查是否确实存在子进程。
在我的 Kubuntu
ps
中,可以给我进程连接到的终端上的前台进程组的 ID。关键字是tpgid
。如果我告诉ps
查询由tmux
as标识的进程,#{pane_pid}
那么我将在此窗格中获得前台进程组 ID。以下绑定(in
~/.tmux.conf
)将使prefixkSIGUSR1 发送到前台进程组(默认prefix为Ctrl+ b):笔记:
前面的破折号(
-
)$(…)
负责定位前台进程组。您可以尝试不使用破折号仅针对一个进程;它将是前台进程组“领导者”。但不能保证“领导者”(仍然)存在。以群组为目标是一种理智的方法,它类似于Ctrl+c向群组发送 SIGINT,尽管机制不同。:1
取自这个答案:Formatps
command output without whitespace。当我们添加破折号时,去掉前导空格是至关重要的。有一个竞争条件:
kill
在之后行动ps
并且不能保证进程组仍然在前台(或根本存在)。您可能会很不幸,并且prefixk在您想要定位的进程退出的时候遇到了问题。这样您可能会无意中将 SIGUSR1 发送到另一个进程。它可能是外壳。接着…
SIGUSR1 的默认操作是终止。特别是您的交互式 shell 在前台(即等待命令)可能会在prefixk. 巴什会。您可以通过预先设置陷阱来防止这种情况:
trap '' USR1
将使外壳忽略信号。在这种情况下,子进程也将忽略该信号,除非它们明确选择处理它(例如dd
这样做)。trap : USR1
将使外壳“忽略”信号(无所作为做出反应),但这不会影响子进程的行为。Tmux 提供
pane_pid
, 但这将是窗格中最顶层进程的 PID,它通常是 shell。您需要更深入地挖掘才能找到前台进程的 PID,但您可以将pane_pid
其用作起点。简单版本——类似:
我相信如果窗格中没有后台进程,这应该可以工作。
如果您可能在 shell 中运行多个同级进程,其中一些是后台进程,那么它会变得有点复杂。我相信您需要执行类似 use
ps -h --ppid #{pane_pid} -O stat
的操作来获取 的子进程pane_pid
,然后确定其中哪一个在前台运行(即列+
中有 aSTAT
),然后解析出该 PID。一种可能的实现:
但是,如果没有子进程(即窗格中的前台进程是外壳本身),这仍然会失败。
如果您需要将其提高到下一个级别的稳健性,当然,请将其移至 shell 脚本并在发送信号之前检查是否确实存在子进程。