为什么“kill -9”会杀死浏览器和服务器?

iva*_*van 3 bash kill shell-script

有时我不得不使用kill -9作为终止我的 rails 服务器的最后手段。不幸的是,我必须经常这样做,以至于我在 bash_profile 中编写了一个辅助函数来完成它。

如果我手动执行 -- ps aux | grep '[r]ails],获取 pid(例如12345),并且kill -9 12345-- 它会杀死服务器并保持浏览器完好无损。但是我的功能也会杀死浏览器,我不想这样做:

function running {
  ps -p $(lsof -i :3000 -t) &> /dev/null
}

function k9 {
  if running
  then
    kill -9 $(lsof -i :3000 -t)
  else
    echo "Rails server is not running"
  fi
}
Run Code Online (Sandbox Code Playgroud)

我已经确认它lsof -i :3000 -t获取的 pid 与我从中获取的 pid 相同ps aux,那么我做错了什么?

Vol*_*gel 16

问题:

使用lsof -i :3000 -t,您将查找连接到端口 3000 的任何进程,该端口可能位于远程端。

在您使用脚本的情况下,浏览器似乎在端口 3000 上连接到 rails 服务器。不同之处在于使用浏览器和使用kill.

这意味着浏览器也被列在了输出中lsof,并被杀死了。

您应该更好地杀死看起来像您的 rails 服务器的进程,而不是在本地或其他地方使用端口 3000 的任何进程。


一般解决方案:

pkill是完成这项工作的正确工具
尝试匹配的内容,请使用pgrep,它以相同的方式匹配:

如果服务器的命令行(如 ps 中所示)以标识服务器实例的命令名称开头,则可以使用pkill servercommand.
如果您需要匹配命令行参数的一部分,请添加-f,例如pkill -f serverargument

被杀死的进程pkill将被列出pgrep- 所以用它来尝试将被杀死的进程。添加选项-apgrep列出命令行,而不仅仅是 pid。


pgrep / pkill 的示例:

作为使用示例-f:根据ps,这两个实例xbindkeys正在运行:

$ ps aux|grep '[x]bindkeys'
26719 ?        S      0:00 xbindkeys -f /tmp/xbindkeysrc-tmp
32046 ?        S      0:00 xbindkeys -f /home/auser/.xbindkeysrc
Run Code Online (Sandbox Code Playgroud)

现在我可以找到两个实例:

$ pgrep xbindkeys
26719
32046
Run Code Online (Sandbox Code Playgroud)

或显示命令:

$ pgrep -a xbindkeys
26719 xbindkeys -f /tmp/xbindkeysrc-tmp
32046 xbindkeys -f /home/auser/.xbindkeysrc
Run Code Online (Sandbox Code Playgroud)

或者通过命令行参数匹配实例之一:

$ pgrep -f '/home/auser/.xbindkeysrc'
32046
Run Code Online (Sandbox Code Playgroud)

如果没有-f,则没有任何进程匹配:

$ pgrep '/home/auser/.xbindkeysrc'
Run Code Online (Sandbox Code Playgroud)

最后,向进程发送一个信号,例如kill

$ pkill -f '/home/auser/.xbindkeysrc'
Run Code Online (Sandbox Code Playgroud)


基于原始方法的替代解决方案:

解决方案pkill更通用,但要遵循您的原始方法,lsof可以更严格地匹配
“任何本地服务器侦听端口”,
而不是
“以任何方式使用本地端口的任何程序,或使用该号码的远程端口以任何方式”。

该选项-sTCP:LISTEN将列表限制为侦听端口,并且由于只能侦听本地端口,因此也只能侦听本地端口。

它可以用作这样的if测试:

if lsof -i :3000 -sTCP:LISTEN -t >/dev/null ; then
    echo running
else
    echo not running
fi
Run Code Online (Sandbox Code Playgroud)



使用 SIGKILL 的旁注,如 kill -9:

KILL 信号的使用pkill方式与kill:

$ pkill -9 -f '/home/auser/.xbindkeysrc'
Run Code Online (Sandbox Code Playgroud)

但在大多数情况下,这比默认信号没有优势-15,在某些情况下,它会破坏事情。所以养成习惯并不是一个好主意。

看看我什么时候不应该杀死 -9 进程?了解为什么您不想-9默认使用。