我試圖從運行命令中捕獲輸出/bin/lsx -lah /
。
輸出應該是:bash: /bin/lsx: no such file or directory
但是,我只是在printf()
.
這是代碼
#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/lsx", "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;
}
我只是想知道為什么輸出沒有被捕獲并列印在底部printf()
。
uj5u.com熱心網友回復:
正如 John 指出的那樣,您只是在捕獲stdout
,而不是stderr
,格式良好的程式通常會將錯誤訊息發送到stderr
(die
您顯示的宏就是一個例子)。
一個快速的解決方案是通過另一個呼叫將子行程重定向stderr
到它的stdout
dup2
dup2(link[1], STDOUT_FILENO);
dup2(STDOUT_FILENO, STDERR_FILENO);
這會將兩個輸出流重定向到單個管道。
或者,用兩個管道捕獲兩個流,以在它們傳播時保持它們的分離。
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);
ssize_t push_through(const char *prefix,
FILE *out, int in,
char *buf, size_t bufsz)
{
ssize_t bytes = read(in, buf, bufsz);
if (bytes > 0)
fprintf(out, "%s: (%.*s)\n", prefix, (int) bytes, buf);
return bytes;
}
int main(void)
{
pid_t pid;
int stdout_pipe[2];
int stderr_pipe[2];
char buffer[4096];
if (pipe(stdout_pipe) == -1 || pipe(stderr_pipe) == -1)
die("pipe");
if ((pid = fork()) == -1)
die("fork");
if (pid == 0) {
close(stdout_pipe[0]);
close(stderr_pipe[0]);
dup2(stdout_pipe[1], STDOUT_FILENO);
dup2(stderr_pipe[1], STDERR_FILENO);
close(stdout_pipe[1]);
close(stderr_pipe[1]);
execl("/bin/lsx", "ls", "-1", (char *) NULL);
perror("execl failed because");
die("execl");
} else {
ssize_t outbytes, errbytes;
close(stdout_pipe[1]);
close(stderr_pipe[1]);
do {
outbytes = push_through("out", stdout, stdout_pipe[0],
buffer, sizeof buffer);
errbytes = push_through("err", stderr, stderr_pipe[0],
buffer, sizeof buffer);
} while (outbytes > 0 || errbytes > 0);
wait(NULL);
}
}
如果失敗,呼叫以列印更詳細的錯誤訊息execl
可能會很有用。perror
請注意,期待錯誤
bash: /bin/lsx: no such file or directory
可能會被誤導,因為exec*
函式僅在某些條件下服從 shell。
The only mention of a shell in man 3 exec
is with regards to execlp
, execvp
, and execvpe
:
If the header of a file isn't recognized (the attempted execve(2) failed with the error ENOEXEC), these functions will execute the shell (/bin/sh) with the path of the file as its first argument. (If this attempt fails, no further searching is done.)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/453563.html