有时我必须使用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
}
我已经确认lsof -i :3000 -t
获取的 pid 与我获取的 pid 相同ps aux
,那么我做错了什么?
答案1
问题:
使用lsof -i :3000 -t
,您将查找连接到端口 3000 的任何进程,该端口可能位于偏僻的边。
在使用脚本的情况下,浏览器似乎在端口 3000 上连接到 Rails 服务器。区别在于使用浏览器和使用kill
.
这意味着浏览器被列在太的输出中lsof
,并被杀死。
您应该更好地终止类似于您的 Rails 服务器的进程,而不是本地或其他地方使用端口 3000 的任何进程。
一般解决方案:
pkill
是个正确的工具为了工作。
为了试匹配什么,使用pgrep
,其匹配方式相同:
如果服务器的命令行(如 ps 所示)以命令名称标识您的服务器实例,您可以使用pkill servercommand
.
如果您需要匹配一部分命令行参数,添加-f
,例如pkill -f serverargument
。
被杀死的进程pkill
将仅被列出pgrep
- 所以用它来尝试将被杀死的进程。添加选项-a
以pgrep
列出命令行,而不仅仅是 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
现在我可以通过以下方式找到这两个实例:
$ pgrep xbindkeys
26719
32046
或者显示命令:
$ pgrep -a xbindkeys
26719 xbindkeys -f /tmp/xbindkeysrc-tmp
32046 xbindkeys -f /home/auser/.xbindkeysrc
或者通过命令行参数匹配实例之一:
$ pgrep -f '/home/auser/.xbindkeysrc'
32046
如果没有-f
,则没有任何进程匹配:
$ pgrep '/home/auser/.xbindkeysrc'
最后,向进程发送信号,例如kill
:
$ pkill -f '/home/auser/.xbindkeysrc'
基于原始方法的替代解决方案:
解决方案pkill
更加通用,但是要遵循您原来的方法,lsof
可以使用命令更严格匹配
“侦听该端口的任何本地服务器”,
而不是
“以任何方式使用本地端口的任何程序,或以任何方式使用该号码的远程端口的任何程序”。
该选项-sTCP:LISTEN
将列表限制为侦听的端口,并且由于只能侦听本地端口,因此也只能侦听本地端口。
它可以用作if
这样的测试:
if lsof -i :3000 -sTCP:LISTEN -t >/dev/null ; then
echo running
else
echo not running
fi
关于使用 SIGKILL 的旁注,如 Kill -9 中所示:
KILL 信号的使用方式与pkill
以下相同kill
:
$ pkill -9 -f '/home/auser/.xbindkeysrc'
但在大多数情况下,这比默认信号没有任何优势-15
,并且在某些情况下,它会破坏一些东西。所以让它成为一种习惯并不是一个好主意。
看一眼我什么时候不应该杀死-9进程?了解为什么您不想使用-9
默认值。