我要么完全忘记了我想知道的关于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,“这是一条消息”);),但这并没有出现在任何地方。 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) ;
- &GT;发送到stderr的消息写入文件,不是stdout
dup2(fd, STDOUT_FILENO) ;
- &GT;发送到stderr的消息写在终端,到stdout无处
dup2(fd, STDOUT_FILENO) ;
dup2(STDERR_FILENO, STDOUT_FILENO) ;
- &GT;发送到stderr的消息写入文件,发送到终端上的stdout
dup2(fd, STDERR_FILENO) ;
dup2(STDOUT_FILENO, STDERR_FILENO) ;
- &GT;发送到stderr的消息写入文件,发送到终端上的stdout
- &GT; stdout似乎有些问题!
答案 0 :(得分:0)
我认为你在打开()&#34;之后立即检测到fd == 1
&#34;你几乎已经回答了这个问题。根据{{3}}:
dup2()系统调用执行与dup()相同的任务,而是执行相同的任务 使用编号最小的未使用文件描述符,它使用 newfd中指定的描述符号。如果描述符newfd是 以前打开,在重新使用之前它会默默关闭。
因此,如果fd == 1
并且您调用dup2( fd, STDOUT_FILENO );
,那么STDOUT_FILENO(也是1)将被关闭,重定向文件的描述符也是如此。如果您无法在程序环境中找到为什么标准输出关闭,那么您可以在致电dup2()
之前进行测试:
if( fd != STDOUT_FILENO )
dup2( fp, STDOUT_FILENO );
至少那应该是一个检查我是否正确的技巧。
答案 1 :(得分:0)
我现在更加重视我的计划:
int main(int argc,
char* argv[])
{
pid_t pid ;
int fd = open("main.log", O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) ;
dup2(fd, STDERR_FILENO) ; // make stdout go to file
dup2(fd, STDOUT_FILENO) ; // make stderr go to file
close(fd) ;
fprintf(stdout, "Main: This is an output message") ;
fprintf(stderr, "Main: This is an error message") ;
fflush(stdout) ;
fflush(stderr) ;
if ((pid = fork()) == 0)
{
fd = open("sub.log", O_RDWR | O_CREAT | O_APPEND,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) ;
dup2(fd, STDERR_FILENO) ; // make stdout go to file
dup2(fd, STDOUT_FILENO) ; // make stderr go to file
close(fd) ;
fprintf(stdout, "Sub: This is an output message") ;
fprintf(stderr, "Sub: This is an error message") ;
fflush(stdout) ;
fflush(stderr) ;
exit(0) ;
}
exit(EXIT_SUCCESS) ;
}
给了我
::::::::::::::
main.log
::::::::::::::
Main: This is an error messageMain: This is an output message
::::::::::::::
sub.log
::::::::::::::
Sub: This is an error messageSub: This is an output message
因此,调用过程中肯定存在问题。它输出到stdout,但是当作为子进程调用时,必须有一些阻碍他这样做的东西(交互式调用,stdout上有很多输出)。 如果有人知道可能是什么原因,我会感谢任何进一步的帮助。 非常感谢你们的帮助。
约克
答案 2 :(得分:0)
我们从外部供应商处调用库函数。在此调用之前,一切正常,之后, stdout 不再输出。
我现在联系供应商询问他们在那里做了什么。同时,这有助于:
int saved_stdout = dup(STDOUT_FILENO) ;
// vendor library call
dup2(saved_stdout, STDOUT_FILENO) ;
感谢大家的帮助
祝福,周末愉快
约克