这是二进制the_binary
:
#include <stdio.h>
int main(void){
char rbuf[10];
int ret;
if((ret = read(0, rbuf, 10)) < 0){
}
printf("read content:%s\n",rbuf);
return 0;
}
这是bash脚本:
#!/bin/bash
bash -ic "/bin/echo $$"
./the_binary
尝试一下,你会发现
➜ test ./the_script.sh # clarify: test is the part of prompt, but not the commmand, please ignore it
hello
[1] + 25407 suspended (tty input) ./bash.sh
据我所知,bash -ic "/bin/echo hello"
做了一些事情,让二进制文件向执行脚本的进程发送SIGTTIN
信号。
但是发生了什么? bash -ic
的语义是什么?
其他问题脚本是:
#!/bin/bash
bash -ic "/bin/echo hello"
bash -ic "/bin/echo hello"
和
#!/bin/bash
bash -ic "/bin/echo hello"
python -ic "print 'hello'"
已编辑:重命名二进制文件以澄清问题
答案 0 :(得分:3)
它试图做一些聪明的事情(再一次!我还记得shellshock。而here(中文)是另一个。)
strace -f
脚本,您会注意到SIGTTIN
是由bash而不是内核发送的。搜索源代码,您将在jobs.c中看到这一点:
if (shell_pgrp == 0)
{
shell_pgrp = getpid ();
setpgid (0, shell_pgrp);
tcsetpgrp (shell_tty, shell_pgrp);
}
while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
{
if (shell_pgrp != terminal_pgrp)
{
SigHandler *ottin;
ottin = set_signal_handler(SIGTTIN, SIG_DFL);
kill (0, SIGTTIN);
set_signal_handler (SIGTTIN, ottin);
continue;
}
break;
}
为什么第二个(以及第三个,如果你把它放在那里)bash发送SIGTTIN
而不是第一个?
因为第一次shell_pgrp == terminal_pgrp
(执行脚本的过程)。然后,交互式bash将自身设置为组进程和前台进程组。然后退出。
第二个(如果你有第三个)bash看到进程组是执行脚本的进程(这是一个新组),但终端的前台进程组仍然是退出的第一个bash(执行者没有做任何工作控制,因为它以非交互方式执行脚本)。因此,上面的shell_pgrp != terminal_pgrp
和kill
部分会执行。
man 4 tty_ioctl
和tcsetpgrp
。
zsh并不像这样杀人。
对于这个脚本:
#!/bin/bash
bash -ic "which mvn"
python -ic "print('hello')"
您没有收到SIGTTIN
。您会收到一个SIGTTOU
,因为Python尝试输出的内容虽然不是前台进程组(第一个是退出的bash)。 (如果确实收到SIGTTIN
,那么因为python -i
的定义,从终端读取。SIGTTOU
可能无法从内核发送,具体取决于您的终端设置。)