在 execl() bash return 一个 eio(Input/output 错误之后从标准输入读取
reading from stdin after execl() bash return an eio(Input/output error)
如果由 shell.
执行,以下代码可以按预期运行
但是如果我将此程序设置为用户的 shell 并通过 ssh 进入主机以将此程序作为 shell 执行,read(0, &buf123, 1);
将 return 一个 EIO (Input/output 错误):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <regex.h>
#include <curl/curl.h>
#include <readline/readline.h>
int main() {
char *shell = "/bin/bash";
pid_t child;
if ((child = fork()) < 0) {
perror("vfork");
return;
}
if (child == 0) {
execl(shell, shell + 5, "-c", "exec /bin/bash --login", NULL);
perror("execl");
return;
}
wait(NULL);
char buf123[1024];
read(0, &buf123, 1);
printf("::%s::\n", buf123);
}
但如果将 execl(bash)
更改为非交互式 bash execl(bash -c "id")
或其他程序而不是 bash,则 read(0, &buf123, 1);
将成功。
所以要重现这个错误,需要满足两个条件:
1. execvl() an interactive bash(system() can also reproduce this error)
2. run as a user's shell using ssh
谁能帮我弄清楚为什么以及如何避免这种情况?
下面是strace
结果:
wait4(-1, NULL, 0, NULL) = 2
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2, si_status=0, si_utime=0, si_stime=0} ---
read(0, 0x7fff7a4c8cb0, 1) = -1 EIO (Input/output error)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcd281f3000
write(1, "::Xv(57::\n", 11) = 11
exit_group(11) = ?
+++ exited with 11 +++
提前致谢!
我碰巧是因为你的sub-shell是一个登录交互shell所以它控制了终端(将它设置为它的会话控制终端)。然后您的进程与终端断开连接,无法再在上面读取。
当然,如果您使用非交互式 shell,它不需要对终端的控制,让您的进程保持原样。
了解 POSIX 终端、会话和进程组。
如果由 shell.
执行,以下代码可以按预期运行但是如果我将此程序设置为用户的 shell 并通过 ssh 进入主机以将此程序作为 shell 执行,read(0, &buf123, 1);
将 return 一个 EIO (Input/output 错误):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <regex.h>
#include <curl/curl.h>
#include <readline/readline.h>
int main() {
char *shell = "/bin/bash";
pid_t child;
if ((child = fork()) < 0) {
perror("vfork");
return;
}
if (child == 0) {
execl(shell, shell + 5, "-c", "exec /bin/bash --login", NULL);
perror("execl");
return;
}
wait(NULL);
char buf123[1024];
read(0, &buf123, 1);
printf("::%s::\n", buf123);
}
但如果将 execl(bash)
更改为非交互式 bash execl(bash -c "id")
或其他程序而不是 bash,则 read(0, &buf123, 1);
将成功。
所以要重现这个错误,需要满足两个条件:
1. execvl() an interactive bash(system() can also reproduce this error)
2. run as a user's shell using ssh
谁能帮我弄清楚为什么以及如何避免这种情况?
下面是strace
结果:
wait4(-1, NULL, 0, NULL) = 2
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=2, si_status=0, si_utime=0, si_stime=0} ---
read(0, 0x7fff7a4c8cb0, 1) = -1 EIO (Input/output error)
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fcd281f3000
write(1, "::Xv(57::\n", 11) = 11
exit_group(11) = ?
+++ exited with 11 +++
提前致谢!
我碰巧是因为你的sub-shell是一个登录交互shell所以它控制了终端(将它设置为它的会话控制终端)。然后您的进程与终端断开连接,无法再在上面读取。
当然,如果您使用非交互式 shell,它不需要对终端的控制,让您的进程保持原样。
了解 POSIX 终端、会话和进程组。