如何将Ctrl-C控制字符或终端挂断消息发送到子进程?
我有一个在伪终端中运行的子进程。 父进程不以root身份运行,但子进程通过su或sudo运行。 因此,无法向子进程发送信号以强制它退出。 我想通过以下方法之一强制退出:
- 模拟Ctrl-C。
- 模拟终端挂断。
我该怎么做? 我已经有一个pty master fd,我尝试过这样的事情:
write(master, &termios.c_cc[VINTR], 1)
但它没有做任何事情。
在我看来,如果你真的有一个pty(除非你的意思是伪终端的其他东西),你所要做的就是向该FD发送一个Control-C。 作为证据,我在Python中提交了以下代码(但是非常接近C所需的代码):
import pty, os, sys, time pid, fd = pty.fork() if pid == 0: os.execv('/bin/sh', ['/bin/sh', '-c', 'while true; do date; sleep 1; done']) sys.exit(0) time.sleep(3) os.write(fd, '^C') print 'results:', os.read(fd, 1024)
这会在pty下执行一个进程,它会运行一个打印日期的无限循环。 然后父母等待3秒并发送一个control-C。
这导致以下输出:
guin:/tmp$ time python /tmp/foo results: Fri Feb 5 08:28:09 MST 2010 Fri Feb 5 08:28:10 MST 2010 Fri Feb 5 08:28:11 MST 2010 python /tmp/foo 0.02s user 0.01s system 1% cpu 3.042 total guin:/tmp$
它跑了3秒多,打印出日期3次,然后退出。
我最终选择了以下解决方案:
在分叉之后,我不再立即执行sudo,而是exec()一个辅助子进程,反过来分叉和执行sudo并调用waitpid。 因此,流程层次结构如下所示:
original process <---- runs as user | +-- helper process <---- runs as user, session leader, | has own pty, in pty's foreground process group | +--- sudo <---- runs as root
通过杀死辅助进程,pty不再具有前台进程。 这将导致操作系统将SIGHUP发送到整个前台进程组,无论用户如何,因此sudo也是SIGHUP。
有两种方法可以实现这一目标:
- 从子进程捕获SIGCHLD信号并处理它,您可以_exit(0)结束子进程
- 有一个名为ptree的程序。 你可以通过这种方式来欺骗这个……在伪代码中:
获得父母的pid。 使用_popen(“ptree%d”,parent_pid) 对于子进程的每个条目 system(“kill -1%d”,child_process_pid)
有两个想到的…抱歉,如果它不是对你的进一步帮助,
希望这会有所帮助,最好的问候,汤姆。
关闭主设备应该向从设备的控制进程组发出挂断信号。
我认为你需要使用ioctl
插入中断字符而不是write
。 不幸的是,这种机制似乎并不便携。 对于Linux,它看起来可能有用:
ioctl(master, TIOCSTI, &termios.c_cc[VINTR]);
我要检查的第一件事是你是否需要将它作为从属端的控制终端。 事实certificate这比我记忆中的更复杂 ,ptys可能默认不会控制。 这个链接适用于Linux,其他系统应该根据他们的SysV和BSD-ness做一个或另一个,但看起来TIOCSCTTY是一个不错的选择。
其次,我会检查你是否在你的termios中设置了ISIG; 如果没有,VINTR和VQUIT将无法正常工作。
当然,如果另一端正在捕获SIGINT和SIGQUIT,那么您将遇到其他问题。