我有一个奇怪的问题。我不是很擅长C语言。我正在尝试创建一个守护进程来在Linux中执行我的基于bash脚本的服务。为了方便起见,我使代码变得简单。以下是我的代码。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <syslog.h>
int main(int argc, char* argv[])
{
pid_t process_id = 0;
pid_t sid = 0;
process_id = fork();
if (process_id < 0)
{
printf("fork failed!\n");
exit(1);
}
if (process_id > 0)
{
printf("daemon creatd with process id %d \n", process_id);
exit(0);
}
umask(0);
sid = setsid();
if(sid < 0)
{
fprintf(stderr, "Return error\n");
exit(1);
}
chdir("/");
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
int status = system("ls");
openlog("slog", LOG_PID|LOG_CONS, LOG_USER);
syslog(LOG_INFO, "Returned status is %d", status);
closelog();
return (0);
}
如您所见,上述程序将执行system
函数来执行ls
命令并将退出代码输出到系统日志。
编译程序并运行后,在日志中我可以看到状态代码是512.但如果我注释掉以下行,
close(STDOUT_FILENO);
然后它完美无缺,我可以在日志中看到状态代码为0,
我可能做错了什么?
更新
我的程序非常大,我在实际环境中没有使用ls
。我使程序简单,重现我面临的问题。另外,要查看程序的状态,我不是在查看输出,而是查看syslog中的状态代码。
答案 0 :(得分:2)
你的守护进程创建看起来很好。但是,遵循约定的守护进程没有控制终端,您可以通过关闭所有标准文件描述符来完成,并调用setsid()
来创建新会话以使守护进程成为会话领导者。因此,您无法使守护程序在stdout
流上生成任何输出。如果你不关闭stdout
流,它显然有效。
所以,你正在做的是尝试从终端向tty写东西。所以,你要么不需要为此目的守护进程,要么你需要写一个不同的文件(而不是stdout)。
答案 1 :(得分:2)
如果从其他评论和答案中不清楚,ls
将其输出写入stdout。如果它无法写入stdout,它会终止并且(显然)设置状态代码为512(在任何情况下都为非零)。
子进程将从父进程继承stdout,因此如果不在父进程中关闭stdout,则子进程将有一个stdout写入,命令将成功。如果你关闭stdout,那么孩子无处可写输出并发生错误。
所以,虽然ls
只是这个问题的一个例子,但是你的实际子进程正在写入stdout,导致同样的问题。
最简单的解决方法是假设你不想要孩子的输出,就是在命令行上重定向孩子的标准输出:
int status = system("ls >/dev/null 2>&1");
这会将stdout和stderr重定向到/dev/null
,有效地丢弃孩子的输出,同时仍然给它一个可写的位置。