从exec获取输出
我正试图编写一个C程序来获取命令输出,然后将其传递给另一个程序 我遇到了一个问题,我无法解决如何获取命令输出并存储它。下面是我所拥有的一个样本从exec获取输出,c,terminal,exec,fork,C,Terminal,Exec,Fork,我正试图编写一个C程序来获取命令输出,然后将其传递给另一个程序 我遇到了一个问题,我无法解决如何获取命令输出并存储它。下面是我所拥有的一个样本 if(fork() == 0){ execl("/bin/ls", "ls", "-1", (char *)0); /* do something with the output here */ } else{ //*other stuff goes here* } 因此,
if(fork() == 0){
execl("/bin/ls", "ls", "-1", (char *)0);
/* do something with the output here */
}
else{
//*other stuff goes here*
}
因此,基本上我想知道是否有任何方法可以从“execl”获取输出并将其传递给其他东西(例如,通过将其存储在某种缓冲区中)
建议非常好。您必须使用
pipe()
创建一个从父进程到子进程的管道。
然后必须使用dup
或dup2
将标准输出
(STDOUT\u FILENO)和错误输出
(STDERR\u FILENO)重定向到管道,并在父进程中从管道读取。
它应该会起作用
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);
int main() {
int link[2];
pid_t pid;
char foo[4096];
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execl("/bin/ls", "ls", "-1", (char *)0);
die("execl");
} else {
close(link[1]);
int nbytes = read(link[0], foo, sizeof(foo));
printf("Output: (%.*s)\n", nbytes, foo);
wait(NULL);
}
return 0;
}
#包括
#包括
#包括
#定义die(e)do{fprintf(stderr,“%s\n”,e);exit(exit_FAILURE);}while(0);
int main(){
int-link[2];
pid_t pid;
查富[4096];
如果(管道(连接)=-1)
模具(“管道”);
如果((pid=fork())=-1)
模具(“叉子”);
如果(pid==0){
dup2(链接[1],标准文件号);
关闭(链接[0]);
关闭(链接[1]);
execl(“/bin/ls”、“ls”、“-1”、(char*)0);
死亡(“执行”);
}否则{
关闭(链接[1]);
int nbytes=read(link[0],foo,sizeof(foo));
printf(“输出:(.*s)\n”,n字节,foo);
等待(空);
}
返回0;
}
打开一个管道,并更改标准输出以匹配该管道
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int pipes[2];
pipe(pipes); // Create the pipes
dup2(pipes[1],1); // Set the pipe up to standard output
现在,您可以像读取普通文件描述符一样读取输出。有关更多详细信息,请参阅谢谢Jonathan Leffler,我优化了上述代码,因为它不能一次读取所有响应
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);
int main() {
int link[2];
pid_t pid;
char foo[4096 + 1];
memset(foo, 0, 4096);
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execl("/bin/ls", "ls", "-1", (char *)0);
die("execl");
} else {
close(link[1]);
int nbytes = 0;
std::string totalStr;
while(0 != (nbytes = read(link[0], foo, sizeof(foo)))) {
totalStr = totalStr + foo;
printf("Output: (%.*s)\n", nbytes, foo);
memset(foo, 0, 4096);
}
wait(NULL);
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义die(e)do{fprintf(stderr,“%s\n”,e);exit(exit_FAILURE);}while(0);
int main(){
int-link[2];
pid_t pid;
查富[4096+1];
memset(foo,04096);
如果(管道(连接)=-1)
模具(“管道”);
如果((pid=fork())=-1)
模具(“叉子”);
如果(pid==0){
dup2(链接[1],标准文件号);
关闭(链接[0]);
关闭(链接[1]);
execl(“/bin/ls”、“ls”、“-1”、(char*)0);
死亡(“执行”);
}否则{
关闭(链接[1]);
int n字节=0;
std::字符串totalStr;
而(0!=(n字节=读取(链接[0],foo,sizeof(foo))){
totalStr=totalStr+foo;
printf(“输出:(.*s)\n”,n字节,foo);
memset(foo,04096);
}
等待(空);
}
返回0;
}
如果希望输出为字符串(char*),这里有一个选项(至少适用于Linux):
#包括
#包括
#包括
#包括
#包括
#包括
字符*qx(字符**cmd,内部有限公司){
国际标准普尔fds[2];
管道(标准管道);
国际标准与准则[2];
如果(!inc_stderr){
管道(标准管道);
}
常数pid_t pid=fork();
如果(!pid){
关闭(stdout_fds[0]);
dup2(stdout_fds[1],1);
如果(包括标准){
dup2(stdout_fds[1],2);
}
关闭(stdout_fds[1]);
如果(!inc_stderr){
关闭(stderru fds[0]);
dup2(stderr_fds[1],2);
关闭(stderr_fds[1]);
}
execvp(*cmd,cmd);
出口(0);
}
关闭(stdout_fds[1]);
const int buf_size=4096;
char*out=malloc(基本尺寸);
int out_size=buf_size;
int i=0;
做{
const ssize_t r=读取(标准输出fds[0],&out[i],单位大小);
如果(r>0){
i+=r;
}
如果(超出尺寸-i 0){
i+=r;
}
if(out_size-我感谢heaps!展示如何从中读取的伟大示例为您赢得了它。我可以阅读dup2、execl等上的手册页,其中解释了函数调用,但我不了解整体情况。有人能详细说明为什么我们需要fork吗?为什么我们在这样做时关闭链接,以及为什么等待(NULL)最后?实际上可能不需要fork。但如果您想在chile任务结束时执行操作,则必须fork一个新进程。等待确保父进程不会退出bedore child。我在我的副本第1.6节中找到了这一解释:“在子进程中,我们调用exec
来执行命令[…]。这将用新的程序文件替换子进程。fork
后跟exec
的组合称为在某些操作系统上生成新进程。在UNIX系统中,这两个部分分为单独的函数。“好的,现在一切都开始有意义了。从手册页上看:exec()
函数系列将当前进程映像替换为新的进程映像。“非常感谢伟大的awnser,很抱歉您没有获得胜利。在我看来,这是一个更清晰的答案,应该是最好的答案。”
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);
int main() {
int link[2];
pid_t pid;
char foo[4096 + 1];
memset(foo, 0, 4096);
if (pipe(link)==-1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if(pid == 0) {
dup2 (link[1], STDOUT_FILENO);
close(link[0]);
close(link[1]);
execl("/bin/ls", "ls", "-1", (char *)0);
die("execl");
} else {
close(link[1]);
int nbytes = 0;
std::string totalStr;
while(0 != (nbytes = read(link[0], foo, sizeof(foo)))) {
totalStr = totalStr + foo;
printf("Output: (%.*s)\n", nbytes, foo);
memset(foo, 0, 4096);
}
wait(NULL);
}
return 0;
}
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
char* qx(char** cmd, int inc_stderr) {
int stdout_fds[2];
pipe(stdout_fds);
int stderr_fds[2];
if (!inc_stderr) {
pipe(stderr_fds);
}
const pid_t pid = fork();
if (!pid) {
close(stdout_fds[0]);
dup2(stdout_fds[1], 1);
if (inc_stderr) {
dup2(stdout_fds[1], 2);
}
close(stdout_fds[1]);
if (!inc_stderr) {
close(stderr_fds[0]);
dup2(stderr_fds[1], 2);
close(stderr_fds[1]);
}
execvp(*cmd, cmd);
exit(0);
}
close(stdout_fds[1]);
const int buf_size = 4096;
char* out = malloc(buf_size);
int out_size = buf_size;
int i = 0;
do {
const ssize_t r = read(stdout_fds[0], &out[i], buf_size);
if (r > 0) {
i += r;
}
if (out_size - i <= 4096) {
out_size *= 2;
out = realloc(out, out_size);
}
} while (errno == EAGAIN || errno == EINTR);
close(stdout_fds[0]);
if (!inc_stderr) {
close(stderr_fds[1]);
do {
const ssize_t r = read(stderr_fds[0], &out[i], buf_size);
if (r > 0) {
i += r;
}
if (out_size - i <= 4096) {
out_size *= 2;
out = realloc(out, out_size);
}
} while (errno == EAGAIN || errno == EINTR);
close(stderr_fds[0]);
}
int r, status;
do {
r = waitpid(pid, &status, 0);
} while (r == -1 && errno == EINTR);
out[i] = 0;
return out;
}
int main() {
char* argv[3];
argv[0] = "ls";
argv[1] = "-la";
argv[2] = NULL;
char* out = qx(argv, 0);
printf("%s", out);
free(out);
}