【问题标题】:Shell script to get the process ID on Linux [duplicate]在Linux上获取进程ID的Shell脚本[重复]
【发布时间】:2011-09-20 05:22:58
【问题描述】:

我想编写一个 shell 脚本(.sh 文件)来获取给定的进程 ID。我在这里要做的是,一旦我获得进程 ID,我想终止该进程。我在 Ubuntu (Linux) 上运行。

我可以用类似的命令来做到这一点

ps -aux|grep ruby
kill -9 <pid>

但我不确定如何通过 shell 脚本来实现。

【问题讨论】:

  • 好吧,逗我开心。 为什么你要在上面使用kill -9
  • @Konstantin 想象你想杀死一个 Java 进程。你可能有几个 java 进程正在运行,这样你就不能使用“killall java”,因为你会杀死每个进程
  • 扩展@IgnacioVazquez-Abrams 的评论,除非您知道该进程没有信号处理程序和/或已损坏且不尊重常规@987654325 @,这是useless use of kill -9

标签: linux bash shell scripting


【解决方案1】:

ps 的结果上使用grep 在脚本中是个坏主意,因为在某些情况下它还会匹配您刚刚调用的grep 进程。命令pgrep 避免了这个问题,所以如果您需要知道进程ID,这是一个更好的选择。 (请注意,当然,匹配的进程可能很多。)

但是,在您的示例中,您可以使用类似的命令 pkill 来终止所有匹配的进程:

pkill ruby

顺便说一句,您应该知道,在几乎所有情况下使用 -9 都是多余的(ho ho) - 在“无用使用 kill -9 套用信函”的文本中有一些有用的建议:

不不不。不要使用kill -9

它没有给进程一个干净的机会:

  1. 关闭套接字连接
  2. 清理临时文件
  3. 通知它的孩子它即将消失
  4. 重置其终端特征

等等等等等等。

一般情况下,发送 15,然后等待一两秒,如果没有 工作,发送 2,如果不起作用,发送 1。如果没有, 删除二进制文件,因为程序表现不佳!

不要使用kill -9。不要为了整理而拿出联合收割机 把花盆装起来。

【讨论】:

  • 感谢@Mark,真的很有帮助
  • 希望我能用这个,bash-4.2# pgrep bash: pgrep: command not found :(
  • @SSHThis:您使用的是什么操作系统/发行版和版本? (pgrep / pkill 在基于 Linux 的系统上分布在 procps 中。)
  • 我在 AIX 上,我基本上只是将进程 ID 作为参数传递给我的脚本并在运行它之前找到它。对我来说没什么大不了的,感谢您提供的额外信息:)
  • 应该包含1521 信号的含义——或者至少是一个阅读它们的链接:linux.org/threads/kill-signals-and-commands-revised.8096
【解决方案2】:

如果你打算使用psgrep 那么你应该这样做:

ps aux|grep r[u]by

这些方括号将导致 grep 跳过 grep 命令本身的行。所以要在脚本中使用它:

output=`ps aux|grep r\[u\]by`
set -- $output
pid=$2
kill $pid
sleep 2
kill -9 $pid >/dev/null 2>&1

反引号允许您在 shell 变量中捕获命令的输出。 set -- 将 ps 输出解析为单词,$2 是该行的第二个单词,恰好是 pid。然后你发送一个 TERM 信号,等待几秒钟让 ruby​​ 自行关闭,如果它仍然存在,则无情地杀死它,但丢弃任何输出,因为大多数时候 kill -9 会抱怨进程已经死了.

我知道我在方括号前没有使用反斜杠,但刚才我在 Ubuntu 12 上检查了它,它似乎需要它们。这可能与 bash 的许多选项和不同 Linux 发行版上的默认配置有关。希望 [ 和 ] 可以在任何地方工作,但我无法再访问我知道它在没有反斜杠的情况下工作的服务器,所以我不能确定。

有一条评论建议使用 grep-v,这也是我过去常做的事情,但当我了解到 [] 变体时,我决定最好在管道中少生成一个进程。

【讨论】:

  • 这是一个为您获取 pid 的绝妙示例,虽然我认为它应该是 2 美元而不是 1 美元,以下是一些更正: output=ps -aux|grep r[u]by;set -- $output;pid=$2 ;kill $pid;sleep 2;kill -9 $pid >/dev/null 2>&1
  • 感谢您的精彩解释!你能解释一下 r[u]by 背后的魔力吗? :)
  • grep 命令不搜索字符串,它搜索正则表达式。方括号用于提供一组字符,其中任何一个都将匹配模式。当然,一组单个字符只会匹配该字符,并且由于 ps 使用方括号显示原始命令行内容,因此该正则表达式将不匹配该命令行。
  • 一种更明确的方式来排除 grep 命令本身 'ps aux | grep 红宝石 | grep -v grep
  • 我不知道 set --。谢谢!
【解决方案3】:

作为开始,不需要执行ps -aux | grep... 命令pidof 使用起来要好得多。几乎从来没有kill -9看到here

要从 bash 中的命令获取输出,请使用类似

pid=$(pidof ruby)

或直接使用pkill

【讨论】:

  • 感谢 Fredrik,感谢您的帮助
  • ps -aux 适用于更多不同的系统,因此值得了解这一点。我使用 kill -9 来准确显示正确的用法。首先你使用 kill -15,只有当它失败时,才使用 kill -9。 sleep 2 是为了给应用程序一个合理的时间来清理和关闭接收信号。
  • 另外需要注意的是,grep 技术还允许您将搜索范围缩小到特定命令,而不仅仅是进程名称。
  • 简单更好!
【解决方案4】:

选项-v 非常重要。它可以排除 grep 表达式本身

例如

ps -w | grep sshd | grep -v grep | awk '{print $1}' to get sshd id

【讨论】:

  • 与往常一样,将 grep 管道传输到 Awk 是 useless。一个更好的解决方案,就像 Steven Penny 的回答一样,是单独使用 Awk。 ps -w | awk '/sshd/ { print $1 }' 并且可能会加入 Michael Dillon 的正则表达式技巧,或者更好的是将匹配限制在单个字段 ps -w | awk '$4 == "sshd" { print $1 }' ......当然,我们仍然在重新发明 pidof,很糟糕。
【解决方案5】:

这在 Cygwin 中有效,但在 Linux 中也应该有效。

ps -W | awk '/ruby/,NF=1' | xargs kill -f

ps -W | awk '$0~z,NF=1' z=ruby | xargs kill -f

Bash Pitfalls

【讨论】:

    【解决方案6】:

    你可以使用命令killall:

    $ killall ruby
    

    【讨论】:

      【解决方案7】:

      它非常简单。 只需像这样运行任何程序:- x= gedit & echo $!这会给你这个过程的PID。 然后这样做杀死 -9 $x

      【讨论】:

        【解决方案8】:

        在shell中杀死进程

        getprocess=`ps -ef|grep servername`
        #echo $getprocess
        set $getprocess 
        pid=$2
        #echo $pid
        kill -9 $pid
        

        【讨论】:

          【解决方案9】:

          如果您已经知道该过程,那么这将很有用:

          PID=`ps -eaf | grep <process> | grep -v grep | awk '{print $2}'`
          if [[ "" !=  "$PID" ]]; then
          echo "killing $PID"
          kill -9 $PID
          fi
          

          【讨论】:

          • 如果你已经知道 PID,为什么还要第二次从ps 输出中解析出来?
          猜你喜欢
          • 1970-01-01
          • 2015-10-12
          • 1970-01-01
          • 2018-10-14
          • 2013-06-02
          • 1970-01-01
          • 2011-04-24
          • 1970-01-01
          • 2012-12-04
          相关资源
          最近更新 更多