c - 在 execl() bash 返回 eio(输入/输出错误)后从标准输入读取

标签 c linux bash ssh execv

如果由 shell 执行,以下代码可以按预期运行。

但是如果我将此程序设置为用户的 shell 并通过 ssh 进入主机以将此程序作为 shell 执行,read(0, &buf123, 1); 将返回一个 EIO(Input/输出错误):

#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\37(\315\177::\n", 11)    = 11
exit_group(11)                          = ?
+++ exited with 11 +++

提前致谢!

最佳答案

我碰巧是因为你的子 shell 是一个登录交互式 shell,所以它控制了终端(将它设置为它的 session 控制终端)。然后您的进程与终端断开连接,无法再在上面读取。

当然,如果您使用非交互式 shell,它不需要对终端的控制,让您的进程保持原样。

阅读有关 POSIX 终端、 session 和进程组的信息。

关于c - 在 execl() bash 返回 eio(输入/输出错误)后从标准输入读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34824579/

相关文章:

linux - 使用命令行 Linux 远程服务器运行并启动 denodo 平台,无需 GUI

c++ - 获取/dev/video0的硬件信息

c - 将数组传递给函数形参

c - 如果我在分配指针之前不释放它会发生什么

无法使用 gcc 编译 ANSI C 代码

bash - 远程 SSH 和变量替换

linux - 按组名、用户名和上次登录 linux 管理用户帐户

谁能帮助我纠正这个程序的编写并运行这个程序?

linux - 使用 Bash shell 中内置的 'command'

regex - 如何在 bash 中合并两个参数(使用 pcgrep 或其他)