{
close(i);
}
实例如下:
void deamon_mode(FILE *fp)
{
pid_t pid;
pid = fork();
if(pid <0){
perror("Fail to fork");
exit(EXIT_FAILURE);
}
if(pid > 0){
exit(EXIT_SUCCESS);
}
//创建新会话
if(setsid() <0){
perror("Fail to fork");
exit(EXIT_FAILURE);
}
//重设文件掩码
umask(0);
//改变进程的工作目录
chdir("/");
//关闭不需要的文件描述符
close(0);
close(1);
close(2);
//重定向
dup2(fp->_fileno,0);
dup2(fp->_fileno,1);
dup2(fp->_fileno,2);
return;
}
//a.out 0(非守护进程) log.txt
//a..out 1(守护进程 ) log.txt
int main(int argc, const char *argv[])
{
int fd;
FILE *log_fp;
int mode;
if(argc <3){
fprintf(stderr,"Usage : %s !\n",argv[0]);
exit(EXIT_FAILURE);
}
mode = atoi(argv[1]);
if(mode){
log_fp = fopen(argv[2],"a");
if(log_fp == NULL){
fprintf(stderr,"Fail to open %s : %s!\n",argv[2],strerror(errno));
exit(EXIT_FAILURE);
}
deamon_mode(log_fp);
}else{
log_fp = stderr;
}
fd = open("test",O_WRONLY | O_TRUNC | O_CREAT,0666);
if(fd <0){
fprintf(log_fp,"Fail to open %s : %s!\n","test",strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(log_fp,"open success!\n");
fflush(log_fp);
while(1)
;
return 0;
}
以上主要实现一个打印日志的一个功能,如果是守护进程则,通过守护进程打印日志到log.txt,否则非守护进程,打印到屏幕
可能这儿有一个重定向dup2
首先看看man手册
dup 和 dup2 都可以用来复制一个现存的文件描述符。经常用来重新定向进程的 STDIN, STDOUT, STDERR。
int dup ( int filedes ) ;
函数返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝,若出错则返回 -1。由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。这函数返回的新文件描述符与参数 filedes 共享同一个文件数据结构。
int dup2( int filedes, int filedes2 )
同样,函数返回一个新的文件描述符,若出错则返回 -1。与 dup 不同的是,dup2 可以用 filedes2 参数指定新描述符的数值。如果 filedes2 已经打开,则先将其关闭。如若 filedes 等于 filedes2 , 则 dup2 返回 filedes2 , 而不关闭它。同样,返回的新文件描述符与参数 filedes 共享同一个文件数据结构。
int main(int argc, const char *argv[])
{
FILE *fp;
fp = fopen(argv[1],"a");
close(0);
close(1);
close(2);
#if 1
dup2(fp->_fileno,0);
dup2(fp->_fileno,1);
dup2(fp->_fileno,2);
#endif
printf("default hello !\n");
fprintf(stdout,"stdout hello !\n");
fprintf(stderr,"stderr hello !\n");
fflush(stdout);
while(1)
;
return 0;
}
编译并运行 a.out log.txt
查看 cat log.txt
可见本应该输出到控制终端的输出到了log.txt
其实对应的日志处理还有几个比较常用:
openlog/syslog/closelog,比较简单,查阅一下便知道!
探究守护进程及其错误日志处理