进程管理:kill命令之-9与-15

简介: kill :发送指定的信号到相应进程。不指定信号将发送SIGTERM(15)终止指定进程。若仍无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。

相关系列文章:

【Linux 系统】一个常驻进程问题的再次分析

一 进程状态转换

二 kill命令回顾

kill :发送指定的信号到相应进程。不指定信号将发送SIGTERM(15)终止指定进程。若仍无法终止该程序可用“-KILL” 参数,其发送的信号为SIGKILL(9) ,将强制结束进程,使用ps命令或者jobs 命令可以查看进程号。root用户将影响用户的进程,非root用户只能影响自己的进程。

2.1 kill命令参数

在命令行输入kill,可以看到参数提示如下:

kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

参数说明:

-l  <信号编号>,若不加信号的编号参数,则使用“-l”参数会列出全部的信号名称。常用的kill -15,kill -9这里的9 和 15就是信号;

-a  当处理当前进程时,不限制命令名和进程号的对应关系;

-p  指定kill 命令只打印相关进程的进程号,而不发送任何信号;

-s  指定发送信号;

-u  指定用户;

2.2 信号

使用kill -l 可以列举所有支持的信号:

[admin@test-3 ~]$ kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH  29) SIGIO 30) SIGPWR
31) SIGSYS  34) SIGRTMIN  35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

也可以通过kill -l SIGHUP 查指定信号对应的数值:

[admin@test-3 ~]$ kill -l SIGHUP
1

几个常用的信号如下:

HUP 1 终端断线
INT 2 中断(同 Ctrl + C)
QUIT 3 退出(同 Ctrl + \)
TERM 15 终止
KILL 9 强制终止
CONT 18 继续(与STOP相反, fg/bg命令)
STOP 19 暂停(同 Ctrl + Z)

其中,信号如果没有指定的话,默认会发出终止信号(15)。比较常用的就是强制终止信号:9终止信号:15,另外,中断信号:2其实就是Ctrl + C结束前台进程。

2.3 kill -15与kill -9

当我们使用kill pid时,实际相当于kill -15 pid。也就是说默认信号为15。使用kill -15时,系统会发送一个SIGTERM的信号给对应的程序。当程序接收到该信号后,具体要如何处理自己可以决定。

这时候,应用程序可以选择:

  • 1、立即停止程序
  • 2、释放响应资源后停止程序
  • 3、忽略该信号,继续执行程序

因为kill -15信号只是通知对应的进程要进行"安全、干净的退出",程序接到信号之后,退出前一般会进行一些"准备工作",如资源释放、临时文件清理等等,如果准备工作做完了,再进行程序的终止。

但是,如果在"准备工作"进行过程中,遇到阻塞或者其他问题导致无法成功,那么应用程序可以选择忽略该终止信号。

这也就是为什么我们有的时候使用kill命令是没办法"杀死"应用的原因,因为默认的kill信号是SIGTERM(15),而SIGTERM(15)的信号是可以被阻塞和忽略的。

kill -15相比,kill -9就相对强硬得多,系统会发出SIGKILL信号,他要求接收到该信号的程序应该立即结束运行,不能被阻塞或者忽略。

所以,kill -9在执行时,应用程序是没有时间进行"准备工作"的,所以这通常会带来一些副作用,数据丢失或者终端无法恢复到正常状态等。

三 Java应用对SIGTERM信号的处理

Java应用在Linux中是以一个独立进程的形式运行的,Java程序的终止运行基于JVM的关闭实现,JVM关闭方式分为3种:

正常关闭:当最后一个非守护线程结束或者调用了System.exit或者通过其他特定平台的方法关闭(接收到SIGINT(2)、SIGTERM(15)信号等)

强制关闭:通过调用Runtime.halt方法或者是在操作系统中强制kill(接收到SIGKILL(9)信号)

异常关闭:运行中遇到RuntimeException异常等。

JVM进程在接收到kill -15信号通知的时候,会做一些清理动作的,例如删除临时文件。同时,也提供了hook机制,来让开发者自定义清理动作,对应的方法为:Java.Runtime.addShutdownHook(Thread hook)。我们可以自定义一个shuthook并测试效果:

package shutdown;
import java.util.concurrent.TimeUnit;
public class MyShutdownHook {
    public static void main(String[] args) throws InterruptedException{
        boolean flag = true;
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("my hook execute end");
        }));
        while (flag) {
            System.out.println("my app is running");
            TimeUnit.SECONDS.sleep(3);
        }
        System.out.println("main thread execute end");
    }
}

在IDE内执行后,进程会一直存在,我们在其中加了一个死循环保证进程常驻,且每3秒钟打印一次app正在运行中。通过jps命令查看进程id,并执行kill命令,查看执行效果:

192:dubbo-proxy-tools xxx$ jps
24272 
6178 Launcher
6179 MyShutdownHook
6182 Jps
99256 RemoteMavenServer
585 UserClient
24446 war
192:dubbo-proxy-tools xxx$ kill 6179

其中6179 MyShutdownHook是我们的这个程序运行进程。执行kill后可以看到程序运行控制台的输出如下:

my app is running
my app is running
my app is running
my hook execute end
Process finished with exit code 143 (interrupted by signal 15: SIGTERM)

可见hook被执行,并且给了接收到signal 15信号的提示后,线程中断,所以没有执行结尾的打印主线程退出记录(第13行的System.out.println("main thread execute end");)。

再次运行程序,我们来看看kill -9执行的效果:

my app is running
my app is running
Process finished with exit code 137 (interrupted by signal 9: SIGKILL)

可见kill -9 强杀进程后,没有执行shutdownHook,而是直接退出。给出的提示为:interrupted by signal 9: SIGKILL

相关文章
|
5月前
|
监控 Linux 应用服务中间件
探索Linux中的`ps`命令:进程监控与分析的利器
探索Linux中的`ps`命令:进程监控与分析的利器
128 13
|
1月前
|
运维 监控 Java
使用jps命令查看Java进程
`jps`是Java开发者和系统管理员的得力助手,它简化了Java进程监控的过程,使得快速检查应用运行状态变得轻而易举。通过合理利用其提供的参数,可以高效地进行故障排查、性能监控及日常管理任务,确保Java应用稳定运行。
68 2
|
3月前
|
jenkins Java Shell
解决jenkins结束后kill掉衍生进程
解决jenkins结束后kill掉衍生进程
|
3月前
|
网络协议
Mac根据端口查询进程id的命令
这篇文章介绍了在Mac操作系统上如何使用两种命令来查询监听特定端口的进程ID。第一种方法是使用`netstat -anp tcp -v | grep 端口号`,例如`netstat -anp tcp -v | grep 80`,这将列出所有使用端口80的TCP连接及其相关信息。第二种方法是使用`lsof -P -n -i:端口号`,例如`lsof -P -n -i:8080`,这将显示使用指定端口的进程列表,包括进程ID、用户、文件描述符等信息。文章通过示例展示了如何使用这些命令,并提供了输出结果的截图。
324 2
|
3月前
|
Java Windows
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
|
4月前
|
Java 运维
开发与运维命令问题之使用jstack命令查看Java进程的线程栈如何解决
开发与运维命令问题之使用jstack命令查看Java进程的线程栈如何解决
66 2
|
4月前
|
小程序 Linux
【编程小实验】利用Linux fork()与文件I/O:父进程与子进程协同实现高效cp命令(前半文件与后半文件并行复制)
这个小程序是在文件IO的基础上去结合父子进程的一个使用,利用父子进程相互独立的特点实现对数据不同的操作
106 2
|
4月前
|
Linux 数据处理 调度
深入探索Linux的renice命令:优化进程优先级
`renice`命令在Linux中用于调整运行进程的优先级,范围-20(最高)至19(最低)。它可以实时改变进程的优先级,无需重启,支持按PID、进程组或用户批量修改。例如,`renice -n 10 -p 1234`将PID为1234的进程优先级设为10。使用时要注意不要滥用高优先级,避免频繁修改,了解系统负载,并记录变更,通常需root权限。
|
5月前
|
Web App开发 运维 监控
深入探索Linux命令pwdx:揭秘进程工作目录的秘密
`pwdx`命令在Linux中用于显示指定进程的工作目录,基于`/proc`文件系统获取实时信息。简单易用,如`pwdx 1234`显示PID为1234的进程目录。结合`ps`和`pgrep`等命令可扩展使用,如查看所有进程或特定进程(如Firefox)的目录。使用时注意权限、进程ID的有效性和与其他命令的配合。查阅`man pwdx`获取更多帮助。
|
4月前
|
应用服务中间件 nginx
cmd 杀掉 nginx后台进程 命令杀掉nginx后台 nginx 常用命令
cmd 杀掉 nginx后台进程 命令杀掉nginx后台 nginx 常用命令
447 0