a.py
import multiprocessingimport osimport signalimport timechild_processes = []def process1(): while True: print(f"子进程运行中,其父pid是:{os.getpgid(os.getppid())}") time.sleep(1)if "__main__" == __name__: a = multiprocessing.Process(target=process1) a.daemon = True a.start() parent_pid = os.getpgid(os.getpid()) with open("/var/run/crawler.pid", 'w') as f: f.write(str(os.getpid())) a.join()
b.py
import osimport signalwith open('/var/run/crawler.pid', 'r') as f: try: pid = int(f.read()) os.kill(pid, signal.SIGTERM) print("Signal sent successfully to process", pid) except Exception as e: print("Error sending signal:", e)
当父进程被 kill
后,孤儿进程确实可能会继续运行并向屏幕输出数据。这是因为孤儿进程是已经被其父进程终止,但还没有被 init
进程(在 Unix 和 Linux 系统中)或 Taskmgr
(在 Windows 系统中)收养的进程。孤儿进程会继续运行,直到它自己也终止或被其他进程终止。
在你的代码中,你启动了一个守护进程(daemon process)a
,并将其设置为 True
。守护进程在主程序结束后会自动终止,但由于 a.join()
会阻塞主进程,直到 a
进程结束,因此这里的守护进程实际上并不会在主程序结束后立即终止。然而,如果你手动 kill
了父进程,a
进程就会成为孤儿进程。
要解决这个问题,你可以考虑以下几种方法:
SIGTERM
信号:你可以在父进程中捕获 SIGTERM
信号,并在接收到该信号时,先正常终止子进程,然后再让父进程自己终止。这样,即使父进程被 kill
,子进程也会先被正常终止,不会成为孤儿进程。multiprocessing.Pool
或 concurrent.futures.ProcessPoolExecutor
:这些高级 API 在创建子进程时,会自动处理孤儿进程的问题。当父进程结束时,它们会自动等待并终止所有子进程。os.killpg()
发送信号给进程组:你可以使用 os.getpgid()
获取父进程的进程组 ID,然后使用 os.killpg()
发送信号给整个进程组,包括子进程。这样,即使父进程被 kill
,子进程也会接收到信号并被终止。以下是使用第一种方法的示例代码:
import multiprocessingimport osimport signalimport timechild_processes = []def process1(): while True: print(f"子进程运行中,其父pid是:{os.getpgid(os.getppid())}") time.sleep(1)def handle_sigterm(signum, frame): for p in child_processes: p.terminate() exit(0)if "__main__" == __name__: signal.signal(signal.SIGTERM, handle_sigterm) a = multiprocessing.Process(target=process1) a.daemon = True a.start() child_processes.append(a) parent_pid = os.getpgid(os.getpid()) with open("/var/run/crawler.pid", 'w') as f: f.write(str(os.getpid())) a.join()
在这个示例中,我们定义了一个 handle_sigterm
函数来处理 SIGTERM
信号。当父进程接收到 SIGTERM
信号时,该函数会终止子进程,并让父进程退出。这样,即使父进程被 kill
,子进程也会被正常终止,不会成为孤儿进程。
孤儿进程概念 我们经常听别人说到孤儿进程(Orphan Process),究竟是什么呢,现在我们一次理解透。 根据维基百科的解释,孤儿进程指的是在其父进程执行完成或被终止后仍继续运行的一类进程。 孤儿进程与僵尸进程是完全不同的,后面会详细介绍僵尸进程。而孤儿进程借用了现实中孤儿的概念,也就是父进程不在了,子进程还在运行,这时我们就把子进程的PPID设为1。前面讲PID提到,操作系统会创建进程号为1
更多面试题总结请看:【面试题】技术面试题汇总 进程的状态 基本状态 进程的基本状态:“就绪”、“执行”、“阻塞”。 就绪:进程已获得除处理机以外的所需资源,等待分配处理机资源 执行:进程正在占用处理机资源执行 阻塞:进程等待某种条件,在条件满足之前无法执行。如发起了 I/O 系统调用,会被阻塞,等待 I/O 中断发生 挂起 “挂起”是指将暂不执行的进程换出到外存,节省内存空间。 “挂起”和“阻塞”
本文向大家介绍pt-kill 常用杀进程参数介绍,包括了pt-kill 常用杀进程参数介绍的使用技巧和注意事项,需要的朋友参考一下 pt-kill 是一个优秀的kill MySQL连接的一个工具,是percona toolkit的一部分,在因为空闲连接较多导致超过最大连接数、某个有问题的sql导致mysql负载很高时,都需要将一些连接kill掉,这个工具主要就是这个用途。 1. 按user kil
本文向大家介绍Linux查看端口、进程情况及kill进程的方法,包括了Linux查看端口、进程情况及kill进程的方法的使用技巧和注意事项,需要的朋友参考一下 看端口: ps -aux | grep tomcat 发现并没有8080端口的Tomcat进程。 使用命令:netstat –apn 查看所有的进程和端口使用情况。发现下面的进程列表,其中最后一栏是PID/Program name 发现80
我想运行node。js作为子流程,并向其提供输入。使用C,下面是我的一些示例代码。 我遇到的问题是,尽管子进程的stdout仍然指向终端,但在向子进程stdin输入打印的“helloworld”行后,我什么也看不到。即使我对管道进行了fflush()操作,我也看不到任何输出。但是,如果关闭管道的输入,则“Hello World”将显示在终端上。 子流程似乎只是缓冲-为什么?我希望最终将子流程std
上篇我整篇尬聊的都是 pcntl_fork(),只管 fork 生产,不管产后护理,实际上这样并不符合主流价值观,而且,操作系统本身资源有限,这样无限生产不顾护理,操作系统也会吃不消的。 孤儿进程是指父进程在 fork 出子进程后,自己先完了。这个问题很尴尬,因为子进程从此变得无依无靠、无家可归,变成了孤儿。用术语来表达就是,父进程在子进程结束之前提前退出,这些子进程将由 init(进程 ID 为