我想做这样的事情:
nc localhost 1234 | myapp
但我希望myapp能够看到从命令的第一部分传递的管道作为文件。
例如:
int main() {
File *fp;
fp = /* get pointer file which is the pipe passed as "nc localhost 1234" */
}
这可能吗?
感谢。
答案 0 :(得分:3)
当您的程序作为管道的一部分启动时,标准输出 以前的流程通过管道传输到程序的标准输入。所以你可以 做:
int main(void)
{
char line[1024];
fgets(line, sizeof line, stdin);
printf("First line is: %s\n", line);
return 0;
}
在POSIX系统上,您可以使用isatty
检查文件描述符是否属于
是指终端。例如:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
if(isatty(STDIN_FILENO))
puts("stdin connected to terminal");
else
puts("piped data to stdin");
return 0;
}
程序的标准行为是它们从stdin
读取并写入
stdout
。坚持这一点,你可以使用shell链接你的程序
管|
。
例如,如果没有传递文件,cat
期望从标准输入读取
作为一个论点。 cat的一个简单实现是:
int main(int argc, char **argv)
{
FILE *in = stdin;
if(argc == 2)
{
in = fopen(argv[1], "r");
if(in == NULL)
{
perror("fopen");
return 1;
}
}
int c;
while((c = fgetc(in)) != EOF)
fputc(c, stdout);
if(in != stdin)
fclose(in);
return 0;
}
作为一名程序员,我在阅读stdin
时是否真的不在意
用户键入终端中的输入,或输入是否是管道输入。相同
写给stdout
的事情是正确的。作为用户,我知道像cat
这样的程序
没有文件传递时从stdin
读取并写入stdout
。因为
我可以做的这种行为
$ echo "hi" | cat | sort
所以你也应该模仿这种行为。
当然,有时候知道是否涉及管道是件好事。例如
当您这样做时,git diff
会使用颜色和没有颜色的stdout
写入
git diff | more
。在这种情况下,可以检查stdout
的连接位置
写给stdout
的行为是一样的。
#include <stdio.h>
#include <unistd.h>
void print_colored_message(const char *msg)
{
printf("\x1b[31m%s\x1b[0m\n", msg);
}
void print_message(const char *msg)
{
if(isatty(STDOUT_FILENO))
print_colored_message(msg);
else
puts(msg);
}
int main(void)
{
print_message("Hello");
print_message("World");
return 0;
}
复制&amp;粘贴此程序并以./test
执行一次,./test | less
执行一次。
你会看到在第一个版本中,你得到一个彩色输出,而在
第二个版本,你没有。保持不变的是输出完成了
stdout
。
如果您不希望以这种方式链接您的程序,那么您必须告诉 您的用户不应该在这样的链中使用您的程序。
答案 1 :(得分:2)
您是否考虑使用命名管道?它们就像管道,一个方向,但它们有名字。如果你想要两个方向,你可以制作两个管道。你制作这样的管道:
mkfifo /dir/to_prog
mkfifo /dir/from_prog
然后一个程序的输出可以单独通过管道连接到第二个,管道名称可以像普通文件名一样使用:
nc localhost 1234 > /dir/to_prog
myapp -i /dir/to_prog -o /dir/from_prog
cat < /dir/from_prog
除了这三个命令甚至可以在三个单独的shell中发出。 myapp.c看起来像这样:
#include <stdio.h>
int
main(int argc, char *argv[])
{
int iFd, oFd, opt;
while (opt = getopt(argc, argv, "i:o:")) != -1) {
switch (opt) {
...
case 'i': iFd = open(optarg, O_RDONLY); break;
case 'o': oFd = open(optarg, O_WRONLY); break;
...
}
}
...
read(iFd, inBuf);
...
write(oFd, outBuf);
...
}
当我需要能够处理程序中的数据流时,我已经使用过这种方法几次,因为某些原因还需要保留它自己的STDIN或STDOUT。如果您希望myprog能够从两个程序写入的管道中读取数据,那么唯一棘手的部分就是:
cat afile > /dir/to_prog
cat anotherFile > /dir/to_prog
让myprog能够读取这两个文件。问题是,当第一只猫退出时,它会关闭/ dir / to_prog,而myprog会把它读作EOF。许多程序将EOF解释为“没有更多的数据时间退出!”但是在这种情况下,一旦第二只猫启动,myprog将能够从/ dir / to_prog中读取更多数据,它只需要知道在看到EOF时不要放弃阅读。当然,如果两个程序同时写入命名管道(或从中读取),它们的数据将被随机交错。
答案 2 :(得分:1)
从BASH您可以使用功能temporary fifo:
myapp <( nc localhost 1234 )
从C开始,如果你想将标准输入作为FILE指针读取,那么只需使用stdin
。
#include <stdio.h>
int main() {
FILE *fp;
fp = stdin;
}
如果要直接在C中重定向自定义命令的输出,请使用popen。