定时任务重启后执行策略_C语言操作时间函数time.ctime,实现定时执行某个任务小例子...

657eebc2c3f602ccd1f1a88956b33f23.png

时间操作函数在实际项目开发中会经常用到,最近做项目也正好用到就正好顺便整理一下。

时间概述

3260b14d20d23b00e737fa03b18ef4c5.png

由上图可知:

  1. 通过系统调用函数time()可以从内核获得一个类型为time_t的1个值,该值叫calendar时间,即从1970年1月1日的UTC时间从0时0分0妙算起到现在所经过的秒数。而该时间也用于纪念UNIX的诞生。
  2. 函数gmtime()、localtime()可以将calendar时间转变成struct tm结构体类型变量中。通过该结构体成员可以很方便的得到当前的时间信息。 我们也可以通过函数mktime将该类型结构体的变量转变成calendar时间。
struct tm{int tm_sec;/*秒数*/int tm_min; /*分钟*/int tm_hour;/*小时*/int tm_mday;/*日期*/int tm_mon; /*月份*/int tm_year; /*从1990年算起至今的年数*/int tm_wday; /*星期*/int tm_yday; /*从今年1月1日算起至今的天数*/int tm_isdst; /*日光节约时间的旗标*/
};
  1. asctime()和ctime()函数产生形式的26字节字符串,这与date命令的系统默认输出形式类似: Tue Feb 10 18:27:38 2020/n/0.
  2. strftime()将一个struct tm结构格式化为一个字符串。

常用时间函数及举例

1、time函数

头文件:time.h
函数定义:time_t time (time_t *t)
说明:返回从1970年1月1日的UTC时间从0时0分0妙算起到现在所经过的秒数。

举例如下:

#include<stdio.h>
#include<time.h>
int main(){time_t timep;long seconds = time(&timep);printf("%ldn",seconds);printf("%ldn",timep);return 0;
}

输出:

edc733c646ea2307920499a8c4bb536b.png

有兴趣的同学可以计算下,从1970年1月1日0时0分0秒到现在经历了多少秒。

附:time_t 一路追踪发现就是从long类型经过不断的typedef ,#define定义过来的。

2、ctime函数

定义:char *ctime(const time_t *timep);
说明:将参数所指的time_t结构中的信息转换成真实世界的时间日期表示方法,然后将结果以字符串形式返回。
注意这个是本地时间。

举例如下:

#include <stdio.h>
#include<time.h>
int main(void) {time_t timep;time(&timep);printf("%sn",ctime(&timep));return 0;
}

输出:

07fb5749b21adf0a327e9323ae01cccc.png

3、gmtime函数

定义:struct tm *gmtime(const time_t *timep);
说明:将参数timep所指的time_t结构中的信息转换成真实世界所使用的时间日期表示方法,然后将结果由结构tm返回。此函数返回的时间日期未经时区转换,而是UTC时间。

举例如下:

#include <stdio.h>
#include<time.h>int main(void) {char *wday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};time_t timep;struct tm *p;time(&timep);p = gmtime(&timep);printf("%d/%d/%d ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);printf("%s %d:%d:%dn",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);return 0;
}

输出:

9a1ebb3760a556dd07ea1a4f7d674024.png

4、 strftime函数

#include <time.h> 
定义:  
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);
说明:
类似于snprintf函数,我们可以根据format指向的格式字符串,将struct tm结构体中信息输出到s指针指向的字符串中,最多为max个字节。当然s指针指向的地址需提前分配空间,比如字符数组或者malloc开辟的堆空间。
其中,格式化字符串各种日期和时间的详细的确切表示方法有如下多种,我们可以根据需要来格式化各种各样的含时间字符串。%a 星期几的简写%A 星期几的全称%b 月分的简写%B 月份的全称%c 标准的日期的时间串%C 年份的前两位数字%d 十进制表示的每月的第几天%D 月/天/年%e 在两字符域中,十进制表示的每月的第几天%F 年-月-日%g 年份的后两位数字,使用基于周的年%G 年分,使用基于周的年%h 简写的月份名%H 24小时制的小时%I 12小时制的小时%j 十进制表示的每年的第几天%m 十进制表示的月份%M 十时制表示的分钟数%n 新行符%p 本地的AM或PM的等价显示%r 12小时的时间%R 显示小时和分钟:hh:mm%S 十进制的秒数%t 水平制表符%T 显示时分秒:hh:mm:ss%u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)%U 第年的第几周,把星期日做为第一天(值从0到53)%V 每年的第几周,使用基于周的年%w 十进制表示的星期几(值从0到6,星期天为0)%W 每年的第几周,把星期一做为第一天(值从0到53)%x 标准的日期串%X 标准的时间串%y 不带世纪的十进制年份(值从0到99)%Y 带世纪部分的十制年份%z,%Z 时区名称,如果不能得到时区名称则返回空字符。%% 百分号
返回值:
成功的话返回格式化之后s字符串的字节数,不包括null终止字符,但是返回的字符串包括null字节终止字符。否则返回0,s字符串的内容是未定义的。值得注意的是,这是libc4.4.4以后版本开始的。对于一些的老的libc库,比如4.4.1,如果给定的max较小的话,则返回max值。即返回字符串所能容纳的最大字节数。

举例如下:

  1 #include <stdio.h>2 #include <time.h>3 4 #define BUFLEN 2555 int main(int argc, char **argv)6 {7     time_t t = time( 0 );   8     char tmpBuf[BUFLEN];   9                                                                             10     strftime(tmpBuf, BUFLEN, "%Y%m%d%H%M%S", localtime(&t)); //format date a11     printf("%sn",tmpBuf);12     return 0;13 }

执行结果如下:

11fad03976fbd447edc6793ebbef302c.png

输出结果表示YYYYmmDDHHMMSS

5、 asctime函数

定义:
char *asctime(const struct tm *timeptr);
说明:将参数timeptr所指的struct tm结构中的信息转换成真实时间所使用的时间日期表示方法,结果以字符串形态返回。与ctime()函数不同之处在于传入的参数是不同的结构。
返回值:返回的也是UTC时间。

举例如下:

#include <stdio.h>
#include <stdlib.h>
#include<time.h>
int main(void) {time_t timep;time(&timep);printf("%sn",asctime(gmtime(&timep)));return EXIT_SUCCESS;
}

输出:

0ae7cb475ccbcb683b7759ede3006633.png

6、 localhost函数

struct tm *localhost(const time_t *timep);
取得当地目前的时间和日期

举例如下:

#include <stdio.h>
#include <stdlib.h>
#include<time.h>int main(void) {char *wday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};time_t timep;struct tm *p;time(&timep);p = localtime(&timep);printf("%d/%d/%d ",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);printf("%s %d:%d:%dn",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);return EXIT_SUCCESS;
}

输出:

1d18b6af94d527985bdbd7005004d7e3.png

7、mktime函数

定义:time_t mktime(struct tm *timeptr);
说明:用来将参数timeptr所指的tm结构数据转换成从1970年1月1日的UTC时间从0时0分0妙算起到现在所经过的秒数。

举例如下:

#include <stdio.h>
#include <stdlib.h>
#include<time.h>int main(void) {time_t timep;struct tm *p;time(&timep);printf("time():%ldn",timep);p = localtime(&timep);timep = mktime(p);printf("time()->localtime()->mktime():%ldn",timep);return EXIT_SUCCESS;
}

输出:

f808c4ea2a10057e9ebfafdd22034fa6.png

8、 gettimeofday函数

定义:
int gettimeofday(struct timeval *tv,struct timezone *tz);
说明:把目前的时间由tv所指的结构返回,当地时区信息则放到有tz所指的结构中,

结构体timeval 定义如下:

struct timeval{long tv_sec; /*秒*/long tv_usec; /*微秒*/
};

结构体timezone定义如下:

struct timezone{int tz_minuteswest; /*和greenwich时间差了多少分钟*/int tz_dsttime; /*日光节约时间的状态*/
}

举例如下:

#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#include<sys/time.h>int main(void) {
struct timeval tv;
struct timezone tz;
gettimeofday(&tv,&tz);
printf("tv_sec :%dn",tv.tv_sec);
printf("tv_usec: %dn",tv.tv_usec);
printf("tz_minuteswest:%dn",tz.tz_minuteswest);
printf("tz_dsttime:%dn",tz.tz_dsttime);
return EXIT_SUCCESS;
}

输出:

635489585729d5cf2a34fa7b326ab90c.png

综合实验

现在我们利用这些时间函数,来实现一个定时执行某个任务得功能。

功能

  1. 程序运行时要记录当前日志文件的最后修改时间;
  2. 每个10秒钟就检查下log文件是否被修改,如果没有被修改就休眠10秒钟;
  3. 如果log文件被修改了,就将当前的日志文件拷贝成备份文件,备份文件名字加上当前时间;
  4. 通过curl发送给ftp服务器;
  5. 删除备份文件,重复步骤2。

程序流程图如下:

429105eccf6ad8f7aa9e12e475cbe2e6.png

函数功能介绍

init()

首先记录当前log文件时间,并记录到全局变量last_mtime中。

check_file_change() 读取文件最后修改时间,并和last_mtime进行比较,如果相同就返回0,不同就返回1.

file_name_add_time() 将当前的日志文件拷贝成备份文件,备份文件名字加上当前时间。

stat()​

得到对应文件的属性信息,存放到struct stat结构体变量中。

运行截图:

第一步:

33f046ab4d1ab2b9a30ffff15ba0e913.png

因为log文件没有被修改过,所以程序不会上传。

第二步: 手动输入字符串 yikoulinux 到日志文件 t.log中。

9ff75cd114efaf8cf9b6954b55b9202c.png

第三步: 因为文件发生了改变,所以打印“file updated”,同时可以看到curl上传文件的log信息。

83ccedd75e718d5ea6645b3530a58f33.png

以下是FTP服务器的根目录,可以看到,上传的日志文件:t-2020-7-26-1-19-45.log

230142f46c92c0d190a5a63af068740e.png

【补充】

  1. 配置信息,直接在代码中写死,通常应该从配置文件中读取,为方便读者阅读,本代码没有增加该功能;
  2. FTP服务器搭建,本文没有说明,相关文件比较多,大家可以自行搜索,一口君用的是File zilla;

91b782b55a479f9e924b126597874cb6.png
  1. 通常这种需要长时间运行的程序,需要设置成守护进程,本文没有添加相应功能,读者可以自行搜索。如果强烈要求可以单开一篇详细介绍。
  2. 代码中time的管理函数,请读者自行搜索相关文章。
  3. curl也提供了相关的函数库curl.lib,如果要实现更灵活的功能可以使用对应的api。
  4. 之所以先把文件拷贝成备份文件,主要是考虑其他模块随时可能修改日志文件,起到一定保护作用。

代码如下

代码如下:

/***************************************************Copyright (C)  公众号: 一口linux  
***************************************************/
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>typedef struct stat ST;
unsigned long last_mtime;/*用户名密码暂时写死,实际应该保存在配置文件*/
char name[32]="user";
char pass[32] ="123456";
char ip[32]     ="192.168.43.117";
char filename[32]="t.log";
char dstfile[256]  ={0};int init(void)
{//准备结构体ST status;//调用stat函数int res = stat(filename,&status);if(-1 == res){perror("error:open file failn");return 0;}last_mtime = status.st_mtime;printf("init time:%s n",ctime(&last_mtime));return 1;
}int  check_file_change(void)
{//准备结构体ST status;//调用stat函数int res = stat(filename,&status);if(-1 == res){perror("error:open file failn");return 0;}
// printf("old:%s new:%s",ctime(&last_mtime),ctime(&status.st_mtime));if(last_mtime == status.st_mtime){printf("file not changen");return 0;}else{printf("file updatedn"); last_mtime = status.st_mtime;return 1;}}
void file_name_add_time(void)
{ST status;time_t t;  struct tm *tblock; char cmd[1024]={0};t = time(NULL);tblock = localtime(&t);sprintf(dstfile,"t-%d-%d-%d-%d-%d-%d.log",tblock->tm_year+1900,tblock->tm_mon,tblock->tm_mday,tblock->tm_hour,tblock->tm_min,tblock->tm_sec);sprintf(cmd,"cp %s %s",filename,dstfile);
// printf("cdm=%sn",cmd);system(cmd);
}
int main(void)
{char cmd[1024]={0};init();while(1){ if(check_file_change() == 1){file_name_add_time();sprintf(cmd,"curl -u %s:%s ftp://%s/ -T %s",name,pass,ip,dstfile);//  printf("cdm=%sn",cmd);system(cmd);unlink(dstfile);}sleep(10); }
}

请关注公众号「一口Linux」

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle入门(十四.20)之创建DML触发器:第一部分

一、什么是DML触发器&#xff1f;DML触发器是执行SQL DML语句&#xff08;INSERT&#xff0c;UPDATE或DELETE&#xff09;时自动触发&#xff08;执行&#xff09;的触发器。 您可以通过两种方法对DML触发器进行分类&#xff1a; •执行时间&#xff1a;BEFORE&#xff0c;AFTE…

IIS负载均衡-Application Request Route详解第四篇:使用ARR实现三层部署架构

本篇的主要目的是带领大家一起来使用ARR来实现一个三层部署架构。这里的三层部署架构主要是由&#xff1a;服务层&#xff0c;应用程序服务器层已经数据层实现。如下图所示&#xff1a; 每次一提到“层”这个字的时候&#xff0c;似乎感觉这个字特别的惹火。很多朋友开始讨论起…

c遗传算法的终止条件一般_KDD比赛之遗传算法(举例理解)

求最大值问题是这样的&#xff1a;求解函数 f(x) x 10*sin(5*x) 7*cos(4*x) 在区间[0,9]的最大值。这个函数大概长这样&#xff1a;那么如何应用遗传算法如何来找到这个奇怪的函数的最大值呢&#xff1f;事实上&#xff0c;不管一个函数的形状多么奇怪&#xff0c;遗传算法都…

6.elasticsearch查询与过滤上下文(query context与filter contenxt)以及term术语查询

【README】 1.本文总结自&#xff1a; Query and filter context | Elasticsearch Guide [7.2] | Elastichttps://www.elastic.co/guide/en/elasticsearch/reference/7.2/query-filter-context.html2.文档相关性分数是否被计算&#xff0c;取决于查询子句是在查询上下文&…

Oracle入门(十四.22)之创建DDL和数据库事件触发器

一、什么是DDL和数据库事件触发器&#xff1f;DDL语句触发DDL触发器&#xff1a;CREATE&#xff0c;ALTER或DROP。 数据库事件触发器由数据库中的非SQL事件触发&#xff0c;例如&#xff1a; •用户连接到数据库或与数据库断开连接。 •DBA启动或关闭数据库。•用户会话中引发了…

Visual Studio上开发Python?你不可不知道的六大功能!

Visual Studio 2013/2015 搭配 Python Tools for Visual Studio 扩充套件让 Visual Studio 能提供对 Python 程序语言高度整合的开发环境&#xff0c;并完整发挥 Visual Studio 强大的功能&#xff0c;协助您在 Visual Studio 内开发 Python 程序上如虎添翼&#xff0c;提升开发…

qt中sendevent_Qt中postEvent和sendEvent函数

Qt中postEvent和sendEvent函数部分内容参考http://blog.csdn.net/lvmengzou/article/details/65450908qt事件循环需要维护一个事件队列&#xff0c;在Qt的main函数中最后一般调用QApplication::exec()成员函数来保持程序对事件队列的处理&#xff0c;exec()的实质是不停调用pro…

IIS负载均衡-Application Request Route详解第五篇:使用ARR来配置试点项目

看到本篇的题目&#xff0c;大家可能感到有点奇怪&#xff01;下面&#xff0c;我们就来看看这到底是什么意思。 大家可能遇到过这样的一种情况&#xff1a;希望根据某些请求用户的特性&#xff0c;将用户的请求导向不同的站点&#xff08;请大家这里区分“亲缘性”的概念&…

Oracle入门(十四.23)之管理触发器

一、触发器需要特权要在模式中创建触发器&#xff0c;需要&#xff1a; •CREATE TRIGGER系统特权 •触发器主体中引用的其他架构中的对象的普通对象特权&#xff08;SELECT&#xff0c;UPDATE&#xff0c;EXECUTE等&#xff09; •与触发器关联的表或视图上的ALTER特权。触发器…

为什么哲学是最难的学科_什么是哲学哲学对大师来说可能非常理论化,没有一定哲学基础肯能很难 爱问知识人...

我的总结是科学哲学是从哲学角度考察科学的一门学科。它以科学活动和科学理论为研究对象&#xff0c;探讨科学的本质、科学知识的获得和检验、科学的逻辑结构等有关科学认识论和科学方法论的基本问题。哲学是什么&#xff1f;这是一个问题&#xff0c;一个既简单又复杂的问题。…

8.es更新文档通过版本号实现并发控制

【README】 1.本文介绍了es更新文档时的并发控制策略&#xff1b;2.通过版本号实现并发控制&#xff08;类似于mysql中基于版本号的乐观锁&#xff09;&#xff1b;3.Es为支持并发控制&#xff0c;为每篇文章设置了版本号_version。初始值为1&#xff0c;每更新1次加1。…

Oracle入门(十五)之数据库锁

一、锁的概念 锁是数据库用来控制共享资源并发访问的机制。锁用于保护正在被修改的数据直到提交或回滚了事务之后&#xff0c;其他用户才可以更新数据二、锁定的优点 一致性 - 一次只允许一个用户修改数据完整性 - 为所有用户提供正确的数据。如果一个用户进行了修改并保存&a…

.NET 和 Mono 的一点历史

提到微软公司研发 .NET Framework 的初衷&#xff0c;难免要提到 SUN 公司1995年推出的 Java 语言。由于 Java 在业界得到了广泛的支持而且迅速建立了庞大的生态系统&#xff0c;微软也不得不考虑如何加以应对&#xff0c;毕竟自己手里的 Visual Basic 和 Visual C 和 Java 一比…

lisp 角平分线_证明冯奥贝尔定理的3种方法

怎样证明冯奥贝尔定理&#xff1f;Von.Aubel定理: 以任意四边形ABCD的边为斜边作四个转向相同的等腰直角三角形ΔABE&#xff0c;ΔBCF&#xff0c;ΔCDG&#xff0c;ΔDAH。则:EGFH&#xff0c;EG⊥FH。关于上述定理的几点说明:(1)&#xff0c;条件是任意四边形&#xff0c;所…

java迭代实现二叉树先中后序遍历(非递归)

【README】 本文复习了通过java迭代实现 二叉树先序&#xff0c;中序&#xff0c;后序遍历&#xff1b; 本文引入了 栈&#xff0c;替换了递归&#xff0c;对二叉树进行遍历&#xff1b; 补充&#xff1a;使用递归遍历二叉树缺点&#xff1a; 众所周知&#xff0c;每次递归…

漫画:什么是分布式锁

转载自 漫画&#xff1a;什么是分布式锁分布式锁的实现有哪些&#xff1f;1.Memcached分布式锁利用Memcached的add命令。此命令是原子性操作&#xff0c;只有在key不存在的情况下&#xff0c;才能add成功&#xff0c;也就意味着线程得到了锁。2.Redis分布式锁和Memcached的方式…

程序员求职面试三部曲之一:选择合适的工作单位

前不久在知乎上看到一个话题&#xff0c;大概是说中国比国外好的有哪些方面&#xff0c;网友们例举了一大堆&#xff0c;其中有一条是说“在中国找工作比较容易”。 是的&#xff0c;特别对于我们IT从业者来说&#xff0c;找工作真的是小菜一碟&#xff1b;只要肯在网络上公开简…

处理api返回的数据_API 乐队指挥家,网关服务正式上线

随着知晓云小伙伴们业务的发展&#xff0c;对我们服务的支持又有了新的要求&#xff0c;比如在对接第三方服务时&#xff0c;需要自定义数据结构等。为此&#xff0c;经过 32 次的需求讨论会以及工程师们的紧张开发后&#xff0c;知晓云 API 网关诞生了。你可以通过可视化界面配…

数据结构排序总结

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析个人的学习心得体会&#xff0c;源代码均为原创&#xff1b; 0.2&#xff09; 本文列出了数据结构中基本上所有的数据结构排序算法&#xff0c; 整理了相关的博文&#xff08;源代码&#xff09;&#xff1b; 0.3…

IIS负载均衡-Application Request Route详解第六篇:使用失败请求跟踪规则来诊断ARR

失败请求跟踪规则&#xff08;FailedRequest Tracing Rules&#xff09;是IIS7中对请求处理进行诊断的强大的工具。我们本篇文章将会带领大家一步步的来配置失败请求跟踪规则&#xff0c;并且告诉大家如何使用这些信息来诊断ARR。 要真正的理解本篇文章要讲述的知识&#xff0c…