安装配置好FastDFS之后,运行起来;
通过fdfs_monitor测试storage状态,正常状态必须是ACTIVE,否则无法上传、下载文件:
在Qt中编辑一下main函数,实现log的集成,做少量修改,log中重定向标准输出到log文件指定的路径中;
记错exec函数以为它会自动创建一个子进程执行系统命令,导致最后一直没有正确的log文件,导致exec后面的调试信息一直没有打印正确。
正好复习了 gdb调试,
注意的细节 1.要调试程序,必须在gcc编译时加 -g
2.多文件调试加断点方法: b main.c:23
3.当编译出来的可执行程序需要外部输入参数时,可以在调试过程中执行运行命令 r 时添加要加入的参数: r /etc/fdfs/client.config main.c
其他知识点:1.dup2函数是在全局有效的,即一旦执行修改,那么整个进程中标准输出一直被log文件的文件描述符覆盖。
2.
函数 l 参数表示参数列表;v表示参数是数组;
p --->PATH环境变量 e---->environ环境变量
什么都不加时,需要在参数中指定绝对路径;
execlp(cmd, cmd, arg1, arg2, NULL ); 参数是列表的函数(带有 l 选项)参数很特殊,前俩是重复的,最后参数列表要以 NULL 结束。
3.exec函数是将执行该函数的进程从执行代码的序列中跳出去执行系统命令,执行完后不会返回调用该函数的代码序列中;所以一般需要配合fork使用。
main.c如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "include/mylog.h"
/* 0 -- 没有日志
1 -- debug级别
2 -- info级别
3 -- warning级别
4 -- err级别
*/
int main(int argc,char* argv[])
{
printf("begin...\n");
My_Log(__FILE__,__LINE__, ELevel[2], 0, "%s", "main function start");
// char*file_conf = argv[1];
// char *file_upload = argv[2];
char* file_conf = "/etc/fdfs/client.conf";
char* file_upload = "main.c";
//execlp(cmd, cmd, arg1, arg2, ... );
//exec函数是将执行该函数的进程从执行代码的序列中跳出去执行系统命令,执行完后不会返回调用该函数的代码序列中;所以一般需要配合fork使用。
if(0 == fork())
{
int ret =0;
ret = execlp("fdfs_upload_file", "fdfs_upload_file", file_conf, file_upload, NULL);
if(ret ==-1)
{
My_Log(__FILE__,__LINE__, ELevel[4], ret, "%s,%s", "execlp function err",strerror(errno));
printf("*************************\n");
return -1;
}
exit(0);
}
wait(NULL);
printf("*************************\n");
My_Log(__FILE__,__LINE__, ELevel[2], 0, "%s", "execlp function OK");
return 0;
}
使用Qt编写linux代码,需要配合Makefile才可以在Qt环境下编译,下面为Makefile:
src = $(wildcard *.c)
obj = $(patsubst %.c, %.o, $(src))
target = a.out
all: $(target)
$(target):$(obj)
gcc $^ -o $@
$(obj): %.o: %.c
gcc -c $< -o $@
.PHONY: clean
clean:
-rm -rf $(target) $(obj)
include/mylog.h内容
#ifndef _MY_LOG_H_
#define _MY_LOG_H_
//实际使用的Level
extern int ELevel[5];
void My_Log(const char *file, int line, int level, int status, const char *fmt, ...);
#endif
mylog.c
#define _CRT_SECURE_NO_WARNINGS
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "include/mylog.h"
#define DEBUG_FILE "fdfs_client.log"
#define MAX_STRING_LEN 10240
//Level类别
#define NO_LOG_LEVEL 0
#define DEBUG_LEVEL 1
#define INFO_LEVEL 2
#define WARNING_LEVEL 3
#define ERROR_LEVEL 4
int ELevel[5] = {NO_LOG_LEVEL, DEBUG_LEVEL, INFO_LEVEL,WARNING_LEVEL,ERROR_LEVEL};
//Level的名称
char ELevelName[5][10] = {"NOLOG", "DEBUG", "INFO", "WARNING", "ERROR"};
static int Error_GetCurTime(char* strTime)
{
struct tm* tmTime = NULL;
size_t timeLen = 0;
time_t tTime = 0;
tTime = time(NULL);
tmTime = localtime(&tTime);
//timeLen = strftime(strTime, 33, "%Y(Y)%m(M)%d(D)%H(H)%M(M)%S(S)", tmTime);
timeLen = strftime(strTime, 33, "%Y.%m.%d %H:%M:%S", tmTime);
return timeLen;
}
static int Error_OpenFile(int* pf)
{
char fileName[1024];
memset(fileName, 0, sizeof(fileName));
#ifdef WIN32
sprintf(fileName, "c:\\Users\\BLACK007\\Desktop\\%s",DEBUG_FILE);
#else
sprintf(fileName, "%s/File of Test/2_4fdfs/log/%s", getenv("HOME"), DEBUG_FILE);
#endif
//File of Test/2_4fdfs/
*pf = open(fileName, O_WRONLY|O_CREAT|O_APPEND, 0666);
if(*pf < 0)
{
//printf("************open error\n");
return -1;
}
return 0;
}
static void Error_Core(const char *file, int line, int level, int status, const char *fmt, va_list args)
{
char str[MAX_STRING_LEN];
int strLen = 0;
char tmpStr[64];
int tmpStrLen = 0;
int pf = 0;
//初始化
memset(str, 0, MAX_STRING_LEN);
memset(tmpStr, 0, 64);
//加入LOG时间
tmpStrLen = Error_GetCurTime(tmpStr);
tmpStrLen = sprintf(str, "[%s] ", tmpStr);
strLen = tmpStrLen;
//加入LOG等级
tmpStrLen = sprintf(str+strLen, "[%s] ", ELevelName[level]);
strLen += tmpStrLen;
//加入LOG状态
if (status != 0)
{
tmpStrLen = sprintf(str+strLen, "[ERRNO is %d] ", status);
}
else
{
tmpStrLen = sprintf(str+strLen, "[SUCCESS] ");
}
strLen += tmpStrLen;
//加入LOG信息
tmpStrLen = vsprintf(str+strLen, fmt, args);
strLen += tmpStrLen;
//加入LOG发生文件
tmpStrLen = sprintf(str+strLen, " [%s]", file);
strLen += tmpStrLen;
//加入LOG发生行数
tmpStrLen = sprintf(str+strLen, " [%d]\n", line);
strLen += tmpStrLen;
//打开LOG文件
if(0 == Error_OpenFile(&pf))
{
dup2(pf,STDOUT_FILENO); //dup2函数是在全局有效的,即一旦执行修改,那么整个进程中标准输出一直被log文件的文件描述符覆盖。
return ;
}
//写入LOG文件
write(pf, str, strLen);
//Log_Error_WriteFile(str);
//关闭文件
close(pf);
return ;
}
void My_Log(const char *file, int line, int level, int status, const char *fmt, ...)
{
va_list args;
//判断是否需要写LOG
// if(level!=DEBUG_LEVEL && level!=INFO_LEVEL && level!=WARNING_LEVEL && level!=ERROR_LEVEL)
if(level == NO_LOG_LEVEL)
{
return ;
}
//调用核心的写LOG函数
va_start(args, fmt);
Error_Core(file, line, level, status, fmt, args);
va_end(args);
return ;
}