【问题标题】:How to close other shells except current?如何关闭除当前之外的其他外壳?
【发布时间】:2015-04-19 09:53:08
【问题描述】:

我需要一个简单的脚本来关闭除我当前登录的之外的其他 shell/会话。我坚持这一行:

ps -o pid,tty,comm | grep sh$

这会导致选择当前的 shell。

例如:

 1346 136,0  sh
 1355 136,1  sh

我可以使用tty 命令来了解我当前的shell (pts)。然后,我想我需要一个循环。

【问题讨论】:

  • 这通常是个坏主意。你可以在 Linux 上使用pkill
  • 您可能希望将答案之一(对您帮助最大的答案)标记为已接受,而不是“已解决”。
  • 没有人发布简单但完整的解决方案。我感谢阿努巴瓦的贡献。有趣的是,询问后一分钟,用户 vks 发布了一条有用的信息,但后来他删除了它。

标签: regex bash shell unix tty


【解决方案1】:

这实际上并不像起初看起来那么容易。主要挑战是ps 实用程序在不同平台之间相当不兼容,这会产生一个非常重大的风险,即您对ps 所做的假设在您可能使用该脚本的系统上并不总是正确的。而且由于这项任务是一项相当...危险的任务,因此您需要在这里小心。举个例子,我当前系统 (Cygwin) 上的 ps 没有 -o 选项,而您的似乎有一个。

无论如何,这是我的解决方案:

pidCol=$(ps| head -1| awk '{ for (i = 1; i <= NF; ++i) if ($i == "PID") { print(i); exit; }; };');
if [[ -n "$pidCol" ]]; then
    ps| tail -n+2| grep sh$| cut -c2-| awk "{ print(\$$pidCol); };"| grep -v "^$$\$"| xargs kill -9;
fi;

它首先在ps 的输出中获取包含进程PID 的列号。我试图通过解析ps 标题行使其尽可能健壮。因此,如果 PID 列位置因系统而异,我们仍然应该为当前系统正确获取它。

然后,我在 kill 管道周围应用了一个保护,以确保它仅在我们从 parse 命令成功获取 $pidCol 时运行。

然后,在实际的终止管道中,我剥离了标头,对所有sh 进程进行grep,切断第一个字符(因为在某些系统上ps 的开头打印了一个小字符指示符一些(但不是所有)行在标题行中没有得到相应的列名),然后使用awk 只打印PID 列值。最后,我grep出当前进程的PID并通过xargs kill -9运行剩余的PID。

【讨论】:

  • 我会更好地格式化您的代码!乍一看,您的解决方案应该有效!
  • 您在同一行中使用 tail、grep、cut、awk 和 grep。我相信这可以通过 awk 一起处理。
【解决方案2】:

你可以在这里使用$$psawk

ps -o pid,tty,comm | awk -v curr=$$ '$3 ~ /sh/ && $1 != curr'

变量$$代表当前shell的PID。

【讨论】:

  • 不错!我试过类似的东西,但你的更直接。请注意,您可能还想说NR&gt;1 不获取标题。
  • 谢谢@fedorqui,我想/sh/ 也会跳过标题行
  • 感谢您提供 $$ 变量信息。
【解决方案3】:

您可以使用 tty 获取当前的 shell 并“清理”它以获取第二个斜线之后的数据,如下所示:

current=$(tty | cut -d/ -f3-)

然后,将所有结果打印在ps -o pid,tty,comm 中,其第二列与您当前的列不匹配...并忽略标题:

ps -o pid,tty,comm | awk -v current="$current" 'NR>1 && $2!=current {print $1}'

然后,您可以循环遍历此结果和kill 给定的 PID。

【讨论】:

    【解决方案4】:

    运行以下命令获取正在运行的会话的PID(进程 ID):

    ps -ft

    使用那些PIDs 强行终止进程:

    kill -TERM <PID1> <PID2> <PID3>
    

    BASH 中使用循环来为所有人完成它,不包括当前会话

    【讨论】:

    • 不是kill -9(与kill -KILL相同)而是kill -TERM
    • -9不是强行的意思吗?
    • -9 一般是-KILL,这是一个坏主意,首先使用:可能会准备程序(包括shell脚本,服务器等...)处理SIGTERM 信号,但他们无法捕获SIGKILL,这应该作为最后的手段。在SIGKILL 之后,某些程序(例如数据库服务器、链接器、文字处理器)可能会使磁盘上的文件处于不一致的状态
    【解决方案5】:

    试试这个。

    pts=$( tty | sed 's/\/dev\(*\)/\1/' ) 
    current=$( ps -C sh  | grep $pts | ps -o pid= | head -n 1 )
    total=$(ps -C sh -o pid= )
    for i in $total ; do                         
        if [[ $i -ne $current ]] ; then
                kill -9 $i
        fi
    done
    

    【讨论】:

      【解决方案6】:
      pgrep -u $USER | grep -v "`pgrep -s 0`" | xargs kill
      

      这会获取当前用户的所有 PID 的列表,并删除当前会话的一个。然后这一切都通过 xargs 提供以终止终止。

      【讨论】:

        【解决方案7】:

        我用这个:

        #!/bin/bash
        current=$(tty | cut -d/ -f3-)
        all=$(ps -A -o tty | grep pts/ | grep -v $current)
        for i in $all ; do
            pkill -9 -t $i
        done
        

        【讨论】:

          猜你喜欢
          • 2013-06-25
          • 2022-08-11
          • 1970-01-01
          • 1970-01-01
          • 2019-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多