我使用 Byobu 来运行不同的长时间运行的进程。有时我想停止这些进程。它们并不总是响应Ctrl-CCtrl-Z。是否可以制作一个 Byobu 热键,只查找当前活动的 Byobu 窗口中正在运行的前台进程并kill -9执行它?

1

  • 注意(假设是 Linux):(1)终端驱动程序会拦截^C^Z字符并发送SIGINTSIGTSTP。终端可能配置为不执行此操作,因此进程不一定会忽略任何内容,发送的相应信号kill可能仍然有效。(2)信号(来自键盘或来自kill)可能有效,但如果父进程没有正确响应,SIGCHLD那么您可能会认为子进程仍然在那里默默地做某事。(3)您写的是“前台进程”(单数)。SIGINTSIGTSTP来自键盘进入前台进程


    – 


最佳答案
2

这个很简单 🙂

我们将利用它
bindkey创建一个快捷方式和内置命令pgreppkill。作为附加信息/演示,我将使用ps它的一些选项。

我们走吧:

1.ps有一些有趣的参数,我们要重点关注的是T-C <command name>-o pid=(是的,之后没有了=!)。

注意:整个段落旨在展示,以便轻松检查下一个解决方案的正确性。

  • ps T打印当前终端中正在运行的进程。例如,我创建了/bin/phps指向 PhpStorm 的临时符号链接,因此运行phps &会在后台打开所提及的 IDE 实例。在一个终端中运行它后(>/dev/null 2>&1添加后不会打印任何内容,&表示“在后台运行”):

    (您可能还注意到当前终端中运行的后台作业数量从绿色变为0了红色!1!

    现在,它在第二个终端中的样子如下:

  • 现在我们要尝试ps -C <command name>– 将我的 phps 作为搜索命令:

    在另一个终端我们有:

    请注意,第二个终端是pts/0(查看上一个图像),但在两个终端上我们都收到了pts/1结果(正确!)——因为那是我们运行命令的终端。

    由于这种行为,我开始使用它
    ps T——所以我们可以捕获当前终端中正在运行的PID进程:)。

  • 我想要详细说明的最后一个参数是-o pid=。它是一个输出修饰符,它只是使ps打印仅包含 PID,而不包含标题(第一行)。最简单的解释方式始终是视觉方式:

  • 所以 – 这里要做的最后一件事是将以上所有内容结合起来。我们将简单地使用ps -C phps -o pid= 以下结果 ps T

    在另一个终端中:

    我们可以看到,我们实现了预期的结果 —— 我们可以捕获所选进程的 PID,但前提是它在当前终端中运行。

2. 我的真正解决方案是基于“pgrep”和“pkill”命令,因为它们更合适,但请注意,使用上述命令ps也可以。

使用的主要原因pgrep是其内置参数-s 0,记录为“仅匹配列出了进程会话 ID 的进程。会话 ID 0 被转换为 pgrep 或 pkill 自己的会话 ID。”

  • 然后,让我们看看它的实际效果:

    在第二个终端中:

    如图所示 – 我们可以使用 实现我们之前所做的事情ps,但只需一个命令。pkill与 类似pgrep,因此它采用相同的参数。 让我们看看它是如何工作的 –在第二个终端中

    正如预期的那样 – 它没有终止该进程,因为它不属于当前终端。现在来看看主控制台:

    所以 – 我们终于得到了想要的结果。最后一步是将我们的命令绑定到快捷方式。

    为了为 zsh 创建它,我们将使用以下命令:

    bindkey -s '^k' 'pkill <YOUR ACTUAL BINARY> -s 0\n'
    

    (此特定示例将命令绑定到 CTRL+k 组合)

    然后只需将其添加到您的~/.zshrc/etc/zsh/zshrc(用于全球采购) – 您就完成了:)

享受!

补充:请注意,pkill(kill事实上也是如此)SIGTERM默认发送信号(如果未指定),如果您的进程接受其他信号,您可以轻松利用它作为 pkill 的附加参数。这样做的目的是正常--signal <NAME>关闭进程。通常,特定守护进程接受的信号列表列在部分。示例来自man <NAME>SIGNALSman stunnel

SIGNALS
       The following signals can be used to control stunnel in Unix environment:
       SIGHUP
           Force a reload of the configuration file.
           Some global options will not be reloaded:
           ·   chroot
           ·   foreground
           ·   pid
           ·   setgid
           ·   setuid
           The use of the 'setuid' option will also prevent stunnel from binding to privileged (<1024) ports during configuration reloading.
           When the 'chroot' option is used, stunnel will look for all its files (including the configuration file, certificates, the log file and the pid file) within the chroot
           jail.
       SIGUSR1
           Close and reopen the stunnel log file.  This function can be used for log rotation.
       SIGUSR2
           Log the list of active connections.
       SIGTERM, SIGQUIT, SIGINT
           Shut stunnel down.

可以使用命令轻松获取可用信号的列表kill -l

因此,如果您想使用相当于kill -9 <PROCESS>(等于kill -SIGKILL <PROCESS>) – 只需在命令中添加--signal SIGKILL(或简单地:) -9pkill

再次强调:尽情享受吧!:)

7

  • 文本图像


    – 

  • @KamilMaciorowski 在这个特定情况下,我必须不同意。图像仅作为输出的示例添加,使用真实输出使我的答案更可靠,图像是一种工作证明。请注意,所有实际命令都以适当的文本形式发布


    – 


  • 1
    实际输出也可以以文本形式发布,这不会使其变得不真实。一般来说,用户会认为您的意图是好的,没有必要让答案看起来“更可靠”。最终重要的是解决方案是否有效。我不会对您的答案或图像做任何“敌对”的事情。不过,对我来说,这些颜色和提示符不会混淆答案并使其变得更糟;例如,时钟完全不相关,它只会混淆。发布文本,在输入前加上# (root 的提示)或$ (普通用户的提示),而输出没有任何内容,这样可读性会更强。


    – 

  • 3
    @KamilMaciorowski 因为我已经完成了所有这些 – 我们能否同意保留图像,而我将避免在下一个答案中插入它们? 重新执行所有命令只是为了捕捉输出(替换图像)似乎是一项繁琐的工作,尤其是在创建答案的这个阶段。


    – 

  • 1
    很好。这是一个合理的计划。


    – 

是的,您可以创建自定义 Byobu 热键来终止当前活动的 Byobu 窗口中的前台进程。设置方法如下:

  1. 创建一个脚本来终止前台进程您需要编写一个小脚本来识别活动 Byobu 窗口中的前台进程并向其发送 kill -9 信号。

  2. 在您的主目录(或您喜欢的任何位置)中创建一个名为 kill_foreground_process.sh 的文件:

    #!/bin/bash
    
    # Get the Byobu window number of the currently active window
    window=$(tmux display-message -p '#I')
    
    # Get the process ID (PID) of the foreground process running in the current window
    pid=$(tmux list-panes -F '#{pane_active} #{pane_pid}' | grep '^1 ' | awk '{print $2}')
    
    # If a PID was found, kill the process
    if [ -n "$pid" ]; then
        kill -9 "$pid"
        echo "Killed process with PID $pid"
    else
        echo "No active foreground process found."
    fi