挂起进程而不杀死它

kov*_*h.j 11 process kill

所以我有一个在后台运行的持久程序。杀死它只会导致它以不同的 PID 重新启动。我想暂停它(让它进入睡眠状态而不实际杀死它)。kill -9 会这样做吗?如果不是,这应该怎么做?

Hau*_*ing 14

kill -STOP $PID
[...]
kill -CONT $PID
Run Code Online (Sandbox Code Playgroud)

@jordanm 补充:还要注意,像 SIGKILL ( kill -9) 一样, SIGSTOP不能被忽略。


小智 6

(还要回答重复/已关闭的问题如何暂停或冻结正在运行的进程?,询问应用程序恢复后崩溃时该怎么办。)

kill -STOP $PID有些进程在&之后无法正确恢复kill -CONT $PID。如果是这种情况,您可以尝试使用CRIU进行检查点/恢复。如果您不介意开销,您还可以在虚拟机中运行该进程,并且可以将其挂起。

SIGSTOP进程在/之后无法恢复的原因之一可能是,当进程停止然后通过 恢复时,SIGCONTLinux 上的某些阻塞系统调用会失败。来自信号(7):EINTRSIGCONT

通过停止信号中断系统调用和库函数

在 Linux 上,即使没有信号处理程序,在进程被停止信号之一停止然后通过 SIGCONT 恢复后,某些阻塞接口也可能会失败并出现错误 EINTR。此行为不受 POSIX.1 认可,并且不会发生在其他系统上。

[...]

受影响的系统调用之一是epoll_wait(2)。例子:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/epoll.h>

int
main(int argc, char *argv[])
{
    int fd = 0;

    int efd = epoll_create(1);
    if (efd == -1) {
        perror("epoll_create");
        exit(1);
    }

    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN;
    ev.data.fd = fd;

    if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) == -1) {
        perror("epoll_ctl");
        exit(1);
    }

    int res = epoll_wait(efd, &ev, 1, -1);
    if (res == -1) {
        perror("epoll_wait");
        exit(1);
    }

    if (ev.events & EPOLLIN && ev.data.fd == fd) {
        printf("Received input\n");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译并运行:

$ gcc -o example example.c
$ echo 'input' | ./example
Received input
$ ./example
Ctrl+Z
[1]+  Stopped                 ./example
$ fg
./example
epoll_wait: Interrupted system call
Run Code Online (Sandbox Code Playgroud)