Linux将进程从当前终端detach

阅读量: searchstar 2022-09-07 13:19:22
Categories: Tags:

场景

ssh到服务器,开了进程,然后想把进程转移到后台执行,然后关掉ssh连接。相当于实现nohup xxx &的效果。

方法

ctrl+z,给进程发送SIGTSTP信号,让进程暂停。注意SIGTSTP信号是可以被捕获的,如果进程捕获并忽略了这个信号,那么可以尝试kill -STOP pid发送SIGSTOP信号,这个信号不能被捕获。

然后jobs查看被暂停的进程的编号,再bg 编号将这个进程放到后台执行,然后disown 编号将这个进程从任务列表中删掉,再exit退出当前终端。由于这个进程已经不在jobs里了,而且正在运行,因此不会对这个进程发送SIGHUP,而是让其变成孤儿进程,被init进程或者systemd进程收养,这样就实现了detach。

如果需要获取这个进程的输出,可以用reredirect:重定向正在运行的进程的输出

但是我没找到可以往这个进程的stdin里塞东西的方法。

例子

loop.sh:

while true; do
	date
	sleep 1
done

运行之:

bash loop.sh

ctrl+z

[1]  + 60237 suspended  bash loop.sh

所以它的编号是1,进程号是60237

也可以用jobs:

[1]  + suspended  bash loop.sh

也显示其编号是1

将其放到后台运行:

bg %1

输出:

[1]  + 60237 continued  bash loop.sh

从jobs列表里删除:

disown %1

jobs,打印的列表就是空的了。

此时pstree -lp -s 60237查看其父进程:

systemd(1)───sshd(733)───sshd(57315)───sshd(57321)───zsh(57322)───bash(60237)───sleep(60330)

可以看到其父进程仍然没有改变。

然后exit退出当前终端,也就是上面的zsh(57322),再pstree -lp -s 60237查看其父进程:

systemd(1)───bash(60237)───sleep(60520)

可以看到变成孤儿进程,被1号进程收养了。

如果要获取其输出,可以用reredirect:reredirect -m FILE 60237,然后其stdoutstderr都被重定向到FILE了。详见:重定向正在运行的进程的输出

参考文献

linux shell暂停前台作业

https://stackoverflow.com/questions/11886812/what-is-the-difference-between-sigstop-and-sigtstp

https://superuser.com/questions/1204006/how-to-find-ancestor-chain-of-a-process