如何在 xterm 中按 Ctrl-C 中断 sudo?

如何在 xterm 中按 Ctrl-C 中断 sudo?

请详细解释(包括 tty 相关的内容)sudoX 终端模拟器上的前台进程实际上是如何在Ctrl-C.

请参阅以下示例:

$ sudo -u test_no_pw sleep 999 &                                    
[1] 16657                  
$ ps -o comm,pid,ppid,ruid,rgid,euid,egid,suid,sgid,sid,pgid -t
COMMAND           PID  PPID  RUID  RGID  EUID  EGID  SUID  SGID   SID  PGID
zsh             15254 15253  1000  1000  1000  1000  1000  1000 15254 15254
sudo            16657 15254     0  1000     0  1000     0  1000 15254 16657
sleep           16658 16657  1002  1002  1002  1002  1002  1002 15254 16657
ps              16660 15254  1000  1000  1000  1000  1000  1000 15254 16660
$ fg
[1]  + running    sudo -u test_no_pw sleep 999
^C
$ # it was killed

在我中断之前,sudostrace在另一个终端上启动了它:

# strace -p 16657
Process 16657 attached
restart_syscall(<... resuming interrupted call ...>) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL, si_value={int=809122100, ptr=0x54552036303a3934}} ---
[...SNIP...]

所以发件人很SI_KERNEL有趣。我昨天在 IRC 频道和 Google 上询问过,但只得到了模糊或不正确的答案。大多数人说终端或 shell 会将 sudo 发送SINGINT到 sudo 但在我看来这不会发生,根据kill(2)

对于有权发送信号的进程,它必须具有特权(在 Linux 下:具有 CAP_KILL 功能),或者发送进程的真实或有效用户 ID 必须等于目标的真实或保存的设置用户 ID过程。在 SIGCONT 的情况下,当发送和接收进程属于同一会话时就足够了。 (从历史上看,规则是不同的;请参阅注释。)

我预测这与将一些带有 ASCII ETX(3) 的转义序列发送到伪终端有关,但我还远远没有理解它。 (为什么信号源自内核?)

相关但模糊/不正确:

我最感兴趣的是它在 Linux 上的工作原理。

答案1

(这是试图澄清和回答问题,但欢迎改进和纠正)。

首先,让我们从场景中删除sudo&+ fg- 因为它们不会影响电台(我假设您主要使用它们来获取 PID)。那么问题就变成了:1)运行在终端前台的进程如何接收SIGINT; 2)当终端是使用X11的伪终端(例如Xterm)时会发生什么变化。

  1. SIGINT(以及 SIGQUIT、SIGTSTP)的传递是由内核控制终端驱动程序在截获 CTRL-C 字符时生成的,这就是您将其视为SI_KERNEL源的原因。无论 X11 还是伪终端,都会发生这种情况。 “Unix 环境中的高级编程第二版 (APUE2)”,图 9.7,第 272 页对此进行了很好的说明(出于版权原因,我不会将其粘贴到此处,但我确信可以找到它)。第 275 页的“9.8 作业控制”部分对此进行了进一步解释。相关的Linux内核代码大概是这样的: http://lingrok.org/xref/linux-linus/drivers/tty/n_tty.c#1254

  2. 现在将伪终端添加到混合中:伪终端内核代码仍然使用标准终端代码(如上所述) - 因此当 PTY(X 终端)的“主”端接收到“的 X11 按键事件时CTRL-C”,并将其发送到从机 PTY,该字符由内核终端驱动器检测到,并将 SIGINT 发送到前台进程组(在您的情况下为 sudo )。 APUE2 第 676 页图 19.1 对此进行了说明。

在 APUE2 第 706 页中,有一个简短的段落“信号生成”提到信号可以由主 PTY 直接使用ioctl(2)(例如http://lingrok.org/xref/linux-linus/drivers/tty/pty.c#482),但我相信这里的情况并非如此。

欢迎评论。

相关内容