【发布时间】:2016-06-17 00:43:06
【问题描述】:
我要么完全忘记了我想知道的关于 C 的一切,要么出现了严重错误。我想将子进程(stdout 和 stderr)的输出重定向到文件。我是这样做的:
if ((pid = fork()) == 0)
{
get_host_date(today) ;
int fd = open(log_filename, O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) ;
dup2(fd, STDOUT_FILENO) ; // make stdout go to file
dup2(fd, STDERR_FILENO) ; // make stderr go to file
fprintf(stderr, "This is a message") ;
if ((status = execv(command, argv)) == -1)
{
printf("\n\nError: execve failed for %s", command) ;
perror("\nexecve failure: ") ;
exit(EXIT_FAILURE) ;
}
close(STDOUT_FILENO) ;
close(STDERR_FILENO) ;
}
日志文件按指定创建,但输出未转到该文件。我做了一些测试输出 (fprintf(stderr, "This is a message") ;),但这并没有出现在任何地方。 Wenn 我检查了变量 fd,我看到它的值是 1(紧接在 open 之后)。但是 1 不应该是预定义的输出文件描述符吗?
有人可以帮我吗?我尝试了一切,但没有结果。
非常感谢您 最良好的祝愿 约尔格
P.S.:我正在使用 RHEL 和 GNU-C。
好的,这里有一个不适合我的压缩代码:
int main(int argc,
char* argv[])
{
PROC_REC proc ;
strcpy(proc.command, "/home/islk/entw/v0816/exe/islk_server") ;
strcpy(proc.args[0], "ISLK_DB1_SERV01") ;
strcpy(proc.args[1], "") ;
strcpy(proc.env[0], "ISLKSERVER_NR=5") ;
strcpy(proc.env[1], "") ;
ISLK_start_single_process(&proc) ;
exit(EXIT_SUCCESS) ;
}
static long ISLK_start_single_process(PROC_REC *prec_ptr)
{
long i=0 ;
int status ;
char *argv[16] ;
char command[256], log_filename[128], today[DB_DATE_DOM] ;
pid_t pid ;
/* Set arguments */
for (i=0; i<16; i++)
{
if (strcmp(prec_ptr->args[i], "") != 0)
argv[i] = prec_ptr->args[i] ;
else
argv[i] = NULL ;
}
/*******************/
/* Set environment */
/*******************/
for (i=0; i<16; i++)
{
if (strcmp(prec_ptr->env[i], "") != 0)
putenv(prec_ptr->env[i]) ;
}
/*****************/
/* Start process */
/*****************/
if ((pid = fork()) == 0)
{
get_host_date(today) ;
bs_create_filename(log_filename, "islk$log", "", "%s_%8.8s.log",
prec_ptr->args[0], today) ;
int fd = open(log_filename, O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) ;
int fdo = dup2(fd, STDOUT_FILENO) ; // make stdout go to file
int fde = dup2(fd, STDERR_FILENO) ; // make stderr go to file
close(fd) ;
fprintf(stdout, "This is a message") ;
if ((status = execv(command, argv)) == -1)
{
printf("\n\nError: execv failed for %s", command) ;
perror("\nexecv failure: ") ;
exit(EXIT_FAILURE) ;
}
close(STDOUT_FILENO) ;
close(STDERR_FILENO) ;
}
else if (pid < 0)
{
printf("\n\nError: fork failed for %s", prec_ptr->args[0]) ;
perror("\nfork failure: ") ;
return ERROR ;
}
else
{
printf("\nProcess %d started for %s", pid, prec_ptr->args[0]) ;
prec_ptr->pid = pid ;
}
return NO_ERROR ;
}
尝试了以下方法:
dup2(fd, STDERR_FILENO) ;
dup2(fd, STDOUT_FILENO) ;
-> 到 stderr 的消息被写入文件,而不是到 stdout
dup2(fd, STDOUT_FILENO) ;
-> 到 stderr 的消息被写入终端,到 stdout 无处
dup2(fd, STDOUT_FILENO) ;
dup2(STDERR_FILENO, STDOUT_FILENO) ;
-> 到 stderr 的消息被写入文件,到终端上的标准输出
dup2(fd, STDERR_FILENO) ;
dup2(STDOUT_FILENO, STDERR_FILENO) ;
-> 到 stderr 的消息被写入文件,到终端上的标准输出
-> 标准输出似乎有问题!
【问题讨论】:
-
我无法重现您的问题。请提供minimal reproducible example。如果我添加“明显”位以使您的代码可以干净地编译,它会按预期运行。
-
也许使用
fileno来确定整数描述符。你也应该在dup2之后关闭 fd。而且我不确定您是否可以将一个文件用于两个流。 -
我认为你是对的,
fd == 1是问题的一部分。似乎stdout之前已被您的进程或其父母之一关闭,并且那里发生的任何事情也可能阻止您的重定向工作(例如dup2(1, 1);没有意义,但我不知道它是否会伤害) -
离题:
close()命令永远不会被执行。如果exec..()成功,它将永远不会返回,如果失败,您将在调用close()之前exit()ing -
总是检查错误。请为每个函数添加适当的检查,并报告您的发现(包括errno)
标签: c io-redirection