I have a child process which runs in a pseudo terminal. The parent process does not run as root, but the child process does, through su or sudo. Because of this it is not possible to send a signal to the child process to force it to exit. I want to force it to exit by one of these means:
我有一个在伪终端中运行的子进程。父进程不以root身份运行,但子进程通过su或sudo运行。因此,无法向子进程发送信号以强制它退出。我想通过以下方法之一强制退出:
- emulating a Ctrl-C.
- emulating a terminal hangup.
模拟Ctrl-C。
模拟终端挂断。
How do I do either of these? I already have a pty master fd, and I've tried something like this:
我该怎么做?我已经有一个pty master fd,我尝试过这样的事情:
write(master, &termios.c_cc[VINTR], 1)
but it doesn't do anything.
但它没有做任何事情。
6 个解决方案
#1
4
It seems to me that if you truly have a pty (unless you mean something else by pseudo terminal), that all you have to do is send a Control-C to that FD. As evidence of this, I submit the following code in Python (but fairly close to the C required to do it):
在我看来,如果你真的有一个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)
This forks a process under a pty, which runs an infinite loop printing the date. Then the parent waits 3 seconds and sends a control-C.
这会在pty下执行一个进程,它会运行一个打印日期的无限循环。然后父母等待3秒并发送一个control-C。
This results in the following output:
这导致以下输出:
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$
It ran just over 3 seconds, printed out the date 3 times, and exited.
它跑了3秒多,打印出日期3次,然后退出。
#2
2
I eventually went with the following solution:
我最终选择了以下解决方案:
After forking, instead of exec'ing sudo immediately, I exec() a helper child process instead, which in turn forks and execs sudo and calls waitpid on it. So the process hierarchy looks like this:
在分叉之后,我不再立即执行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
By killing the helper process, the pty does not have a foreground process anymore. This will cause the OS to send SIGHUP to the entire foreground process group, regardless of the user, so sudo is SIGHUP'ed too.
通过杀死辅助进程,pty不再具有前台进程。这将导致操作系统将SIGHUP发送到整个前台进程组,无论用户如何,因此sudo也是SIGHUP。
#3
0
There is two ways to achieve this:
有两种方法可以实现这一目标:
- From the child process, trap the SIGCHLD signal and handle it, you could _exit(0) to end the child process
- There's a program called ptree. You could cheat this by doing it this way...in pseudocode:
从子进程捕获SIGCHLD信号并处理它,您可以_exit(0)结束子进程
有一个名为ptree的程序。你可以通过这种方式来欺骗这个......在伪代码中:
obtain the parent's pid. using _popen("ptree %d", parent_pid) for each entry of child process system ("kill -1 %d", child_process_pid)
There the two that comes to mind...sorry if its not of further help to you,
有两个想到的...抱歉,如果它不是对你的进一步帮助,
Hope this helps, Best regards, Tom.
希望这会有所帮助,最好的问候,汤姆。
#4
0
Closing the master should signal a hangup to the controlling process group of the slave.
关闭主设备应该向从设备的控制进程组发出挂断信号。
#5
0
I think you need to use ioctl
to insert the interrupt character instead of write
. Unfortunately the mechanism for this does not seem to be portable. For linux it looks this might work:
我认为你需要使用ioctl插入中断字符而不是写入。不幸的是,这种机制似乎并不便携。对于Linux,它看起来可能有用:
ioctl(master, TIOCSTI, &termios.c_cc[VINTR]);
#6
0
The first thing I'd check is if you need to make it the controlling terminal on the slave side. It turns out this is more complex than I remember, with ptys possibly not becoming controlling by default. That link is for Linux, other systems should do one or the other depending on their SysV vs. BSD-ness, but it looks like the TIOCSCTTY is a good bet to try.
我要检查的第一件事是你是否需要将它作为从属端的控制终端。事实证明这比我记忆中的更复杂,ptys可能默认不会控制。这个链接适用于Linux,其他系统应该根据他们的SysV和BSD-ness做一个或另一个,但看起来TIOCSCTTY是一个不错的选择。
Secondly, I'd check if you're setting ISIG in your termios; if not, VINTR and VQUIT won't work.
其次,我会检查你是否在你的termios中设置了ISIG;如果没有,VINTR和VQUIT将无法正常工作。
Of course, if the other end is catching SIGINT and SIGQUIT, you will have other issues.
当然,如果另一端正在捕获SIGINT和SIGQUIT,那么您将遇到其他问题。
#1
4
It seems to me that if you truly have a pty (unless you mean something else by pseudo terminal), that all you have to do is send a Control-C to that FD. As evidence of this, I submit the following code in Python (but fairly close to the C required to do it):
在我看来,如果你真的有一个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)
This forks a process under a pty, which runs an infinite loop printing the date. Then the parent waits 3 seconds and sends a control-C.
这会在pty下执行一个进程,它会运行一个打印日期的无限循环。然后父母等待3秒并发送一个control-C。
This results in the following output:
这导致以下输出:
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$
It ran just over 3 seconds, printed out the date 3 times, and exited.
它跑了3秒多,打印出日期3次,然后退出。
#2
2
I eventually went with the following solution:
我最终选择了以下解决方案:
After forking, instead of exec'ing sudo immediately, I exec() a helper child process instead, which in turn forks and execs sudo and calls waitpid on it. So the process hierarchy looks like this:
在分叉之后,我不再立即执行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
By killing the helper process, the pty does not have a foreground process anymore. This will cause the OS to send SIGHUP to the entire foreground process group, regardless of the user, so sudo is SIGHUP'ed too.
通过杀死辅助进程,pty不再具有前台进程。这将导致操作系统将SIGHUP发送到整个前台进程组,无论用户如何,因此sudo也是SIGHUP。
#3
0
There is two ways to achieve this:
有两种方法可以实现这一目标:
- From the child process, trap the SIGCHLD signal and handle it, you could _exit(0) to end the child process
- There's a program called ptree. You could cheat this by doing it this way...in pseudocode:
从子进程捕获SIGCHLD信号并处理它,您可以_exit(0)结束子进程
有一个名为ptree的程序。你可以通过这种方式来欺骗这个......在伪代码中:
obtain the parent's pid. using _popen("ptree %d", parent_pid) for each entry of child process system ("kill -1 %d", child_process_pid)
There the two that comes to mind...sorry if its not of further help to you,
有两个想到的...抱歉,如果它不是对你的进一步帮助,
Hope this helps, Best regards, Tom.
希望这会有所帮助,最好的问候,汤姆。
#4
0
Closing the master should signal a hangup to the controlling process group of the slave.
关闭主设备应该向从设备的控制进程组发出挂断信号。
#5
0
I think you need to use ioctl
to insert the interrupt character instead of write
. Unfortunately the mechanism for this does not seem to be portable. For linux it looks this might work:
我认为你需要使用ioctl插入中断字符而不是写入。不幸的是,这种机制似乎并不便携。对于Linux,它看起来可能有用:
ioctl(master, TIOCSTI, &termios.c_cc[VINTR]);
#6
0
The first thing I'd check is if you need to make it the controlling terminal on the slave side. It turns out this is more complex than I remember, with ptys possibly not becoming controlling by default. That link is for Linux, other systems should do one or the other depending on their SysV vs. BSD-ness, but it looks like the TIOCSCTTY is a good bet to try.
我要检查的第一件事是你是否需要将它作为从属端的控制终端。事实证明这比我记忆中的更复杂,ptys可能默认不会控制。这个链接适用于Linux,其他系统应该根据他们的SysV和BSD-ness做一个或另一个,但看起来TIOCSCTTY是一个不错的选择。
Secondly, I'd check if you're setting ISIG in your termios; if not, VINTR and VQUIT won't work.
其次,我会检查你是否在你的termios中设置了ISIG;如果没有,VINTR和VQUIT将无法正常工作。
Of course, if the other end is catching SIGINT and SIGQUIT, you will have other issues.
当然,如果另一端正在捕获SIGINT和SIGQUIT,那么您将遇到其他问题。