Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C如何从STDERR读取()函数?_C_Bash_Input_Pipe_Stderr - Fatal编程技术网

C如何从STDERR读取()函数?

C如何从STDERR读取()函数?,c,bash,input,pipe,stderr,C,Bash,Input,Pipe,Stderr,我得到了以下C代码: #include <stdio.h> #include <unistd.h> int main(int argc, char **argv){ char buf[10]; read(2,buf,4); } 在终端中,它会提示我键入输入,就像输入Stdin一样。为什么呢?如何在bash中使用管道将stderr发送到文件? 提前谢谢 因为当您直接从命令行运行程序时,它的stdin和stderr都连接到同一个文件(您的终

我得到了以下C代码:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv){
        char buf[10];
        read(2,buf,4);
}
在终端中,它会提示我键入输入,就像输入Stdin一样。为什么呢?如何在bash中使用管道将stderr发送到文件?
提前谢谢

因为当您直接从命令行运行程序时,它的stdin和stderr都连接到同一个文件(您的终端),该文件具有读取权限。因此,它只是从终端读取数据,但不一定是从其stderr读取数据。当你重定向它的stderr时,一切都失败了

这是我的测试

ibug@linux:~ $ cat t.c
#include <stdio.h>
#include <unistd.h>

int main(void){
        char b[10];
        printf("%ld\n", read(2, b, 10));
        return 0;
}
ibug@linux:~ $ gcc t.c
ibug@linux:~ $ ./a.out
abcdefg
8
ibug@linux:~ $ ./a.out 2>/dev/null
-1
ibug@linux:~ $ ./a.out 2>/dev/zero
-1
ibug@linux:~ $
ibug@linux:~$cat t.c
#包括
#包括
内部主(空){
charb[10];
printf(“%ld\n”,读作(2,b,10));
返回0;
}
ibug@linux:~$gcc t.c
ibug@linux:~$/a.out
abcdefg
8.
ibug@linux:~$/a.out 2>/dev/null
-1
ibug@linux:~$/a.out 2>/dev/zero
-1
ibug@linux:~ $
文件描述符 基于Unix系统的许多历史怪癖之一是,打开终端供会话使用的代码通常是这样工作的(实际上,忽略了错误检查):

成功后,
open()
系统调用将返回可用的最低文件描述符。关闭文件描述符0后,后续打开将打开文件描述符0(标准输入),并打开终端进行读写。然后从读/写描述符0复制文件描述符1(标准输出)和2(标准错误)。因此,默认情况下,所有三个标准文件描述符都是为读写而打开的。注意术语“文件描述符”的使用

因此,程序通常可以写入文件描述符0,并从文件描述符1或2(或两者)读取。如果使用文件流(
stdin
stdout
stderr
),可能会遇到问题,但底层文件描述符在连接到终端时通常是读写的

#include <stdio.h>
#include <unistd.h>
#include "stderr.h"

static void check_fd(int fd)
{
    char buffer[1024];

    err_remark("About to read from fd = %d\n", fd);
    ssize_t nbytes = read(fd, buffer, sizeof(buffer));
    if (nbytes < 0)
        err_sysrem("Failed to read fd = %d: ", fd);
    else if (nbytes == 0)
        err_remark("Got EOF (0 bytes read) on fd = %d\n", fd);
    else
    {
        err_remark("Got normal read of %d bytes on fd = %d\n", (int)nbytes, fd);
        printf("Data: [%.*s]\n", (int)nbytes - 1, buffer);
    }

    err_remark("About to write to fd = %d\n", fd);
    char message[] = "  'Twas brillig and the the slithy toves\n"
                     "  Did gyre and gimble in the wabe.\n"
                     "  All mimsy were the borogroves,\n"
                     "  And the mome raths outgrabe.\n";
    nbytes = write(fd, message, sizeof(message) - 1);
    if (nbytes < 0)
        err_sysrem("Failed to write to fd = %d: ", fd);
    else if (nbytes == (ssize_t)sizeof(message) - 1)
        err_remark("Successfully wrote %d bytes to fd = %d\n", (int)nbytes, fd);
    else
        err_remark("Got a short write (%d bytes written; %d expected) on fd = %d\n",
                   (int)nbytes, (int)(sizeof(message) - 1), fd);
}

int main(int argc, char **argv)
{
    if (argc != 0)
        err_setarg0(argv[0]);

    check_fd(STDIN_FILENO);
    check_fd(STDOUT_FILENO);
    check_fd(STDERR_FILENO);
    return 0;
}
以及:

$。/stdio11输出
stdio11:即将从fd读取=0
stdio11:在fd=0时获得EOF(读取0字节)
stdio11:即将写入fd=0
stdio11:无法写入fd=0:错误(9)错误的文件描述符
stdio11:即将从fd=1读取
stdio11:读取fd=1失败:错误(9)错误的文件描述符
stdio11:即将写入fd=1
stdio11:已成功将140字节写入fd=1
stdio11:即将从fd=2读取
标准错误仍然是终端,因此输入仍然可以在这里发生。
stdio11:在fd=2上正常读取了69个字节
stdio11:即将写入fd=2
“那是布里里格和那件紧身衣
在wabe中旋转和gimble。
所有的米姆西都是波罗格罗夫家族,
而这一时刻却被超越了。
stdio11:已成功将140字节写入fd=2
$cat输出
“那是布里里格和那件紧身衣
在wabe中旋转和gimble。
所有的米姆西都是波罗格罗夫家族,
而这一时刻却被超越了。
数据:[标准错误仍然是终端,因此输入仍然可以在这里发生。]
$
JFTR:上面的测试是在运行macOS High Sierra 10.13.3(并使用GCC 7.2.0)的MacBook Pro上完成的,但我希望在任何基于Unix的机器上都能得到相同的结果

文件流 标准I/O文件流使用文件描述符0、1、2,但它们未配置为允许在
stdin
上输出或在
stdout
stderr
上输入,这是给定流名称时所期望的

下面是使用文件流(
file*
)而不是描述符的类似测试代码:

/* SO 4844-3136 - file streams version A */
#include <unistd.h>
#include "stderr.h"

static void check_fp(FILE *fp, const char *name)
{
    char buffer[1024];

    err_remark("About to read from %s\n", name);
    size_t nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp);
    if (nbytes <= 0)
        err_sysrem("Failed to read %s: ", name);
    else
    {
        err_remark("Got normal read of %zu bytes on %s\n", nbytes, name);
        printf("Data: [%.*s]\n", (int)nbytes - 1, buffer);
    }

    err_remark("About to write to %s\n", name);
    char message[] = "  'Twas brillig and the the slithy toves\n"
                     "  Did gyre and gimble in the wabe.\n"
                     "  All mimsy were the borogroves,\n"
                     "  And the mome raths outgrabe.\n";
    nbytes = fwrite(message, sizeof(char), sizeof(message) - 1, fp);
    if (nbytes == 0)
        err_sysrem("Failed to write to %s: ", name);
    else if (nbytes == sizeof(message) - 1)
        err_remark("Successfully wrote %d bytes to %s\n", (int)nbytes, name);
    else
        err_remark("Got a short write (%zu bytes written; %zu expected) on %s\n",
                   nbytes, (sizeof(message) - 1), name);
}

int main(int argc, char **argv)
{
    if (argc != 0)
        err_setarg0(argv[0]);

    check_fp(stdin,  "stdin");
    check_fp(stdout, "stdout");
    check_fp(stderr, "stderr");
    return 0;
}
这非常清楚地表明,至少在Mac上,您无法写入
stdin
或读取
stdout
stderr

您可以在GitHub的my(堆栈)中找到此代码 中的存储库
子目录。还有一个变体
stdio17.c
使用了
fgets()
fputs()
,但在某些方面不太令人满意,因为I/O函数不报告输入或输出的长度,这与
fread()
fwrite()
不同,但
fgets()
在第一行停止读取,与
fread()
不同,STDERR\u文件no是一个输出文件描述符。你不能从中阅读。如果您检查
read
返回的内容(您应该一直这样做!),您可能会收到错误(
-1
)或文件结尾(
0
)。你真正的问题是什么?为什么要读取标准错误?@Someprogrammerdude:在大多数类似UNIX的系统上,当相关的文件描述符连接到终端时,可以写入标准输入,读取标准输出和标准错误。试试看!你不是有意这么做的,但它通常是有效的。@Someprogrammerdude为插话感到抱歉(乔纳森·莱弗勒已经说过了),但是:你错了。(看起来至少还有其他人,他们对你的评论投了赞成票,也有同样的错误信念。)你可以在终端上输入;您可以运行
/your\u prog 2Sorry,以防我回复太晚。是的,这是一个谜,根据@JonathanLeffler的建议,我现在可以做:)为什么我重定向它的stderr时它才失败?@Wolfat不确定。从输出描述符本身读取是一种未定义的行为。无论如何,谢谢你:)
#include <stdio.h>
#include <unistd.h>
#include "stderr.h"

static void check_fd(int fd)
{
    char buffer[1024];

    err_remark("About to read from fd = %d\n", fd);
    ssize_t nbytes = read(fd, buffer, sizeof(buffer));
    if (nbytes < 0)
        err_sysrem("Failed to read fd = %d: ", fd);
    else if (nbytes == 0)
        err_remark("Got EOF (0 bytes read) on fd = %d\n", fd);
    else
    {
        err_remark("Got normal read of %d bytes on fd = %d\n", (int)nbytes, fd);
        printf("Data: [%.*s]\n", (int)nbytes - 1, buffer);
    }

    err_remark("About to write to fd = %d\n", fd);
    char message[] = "  'Twas brillig and the the slithy toves\n"
                     "  Did gyre and gimble in the wabe.\n"
                     "  All mimsy were the borogroves,\n"
                     "  And the mome raths outgrabe.\n";
    nbytes = write(fd, message, sizeof(message) - 1);
    if (nbytes < 0)
        err_sysrem("Failed to write to fd = %d: ", fd);
    else if (nbytes == (ssize_t)sizeof(message) - 1)
        err_remark("Successfully wrote %d bytes to fd = %d\n", (int)nbytes, fd);
    else
        err_remark("Got a short write (%d bytes written; %d expected) on fd = %d\n",
                   (int)nbytes, (int)(sizeof(message) - 1), fd);
}

int main(int argc, char **argv)
{
    if (argc != 0)
        err_setarg0(argv[0]);

    check_fd(STDIN_FILENO);
    check_fd(STDOUT_FILENO);
    check_fd(STDERR_FILENO);
    return 0;
}
/* SO 4844-3136 - file streams version A */
#include <unistd.h>
#include "stderr.h"

static void check_fp(FILE *fp, const char *name)
{
    char buffer[1024];

    err_remark("About to read from %s\n", name);
    size_t nbytes = fread(buffer, sizeof(char), sizeof(buffer), fp);
    if (nbytes <= 0)
        err_sysrem("Failed to read %s: ", name);
    else
    {
        err_remark("Got normal read of %zu bytes on %s\n", nbytes, name);
        printf("Data: [%.*s]\n", (int)nbytes - 1, buffer);
    }

    err_remark("About to write to %s\n", name);
    char message[] = "  'Twas brillig and the the slithy toves\n"
                     "  Did gyre and gimble in the wabe.\n"
                     "  All mimsy were the borogroves,\n"
                     "  And the mome raths outgrabe.\n";
    nbytes = fwrite(message, sizeof(char), sizeof(message) - 1, fp);
    if (nbytes == 0)
        err_sysrem("Failed to write to %s: ", name);
    else if (nbytes == sizeof(message) - 1)
        err_remark("Successfully wrote %d bytes to %s\n", (int)nbytes, name);
    else
        err_remark("Got a short write (%zu bytes written; %zu expected) on %s\n",
                   nbytes, (sizeof(message) - 1), name);
}

int main(int argc, char **argv)
{
    if (argc != 0)
        err_setarg0(argv[0]);

    check_fp(stdin,  "stdin");
    check_fp(stdout, "stdout");
    check_fp(stderr, "stderr");
    return 0;
}