历史文件清理

应用系统中可能会被要求保存一些文件记录,比如配置文件修改的备份,日志文件,备份文件。不过历史文件不一定是要求永久保留的,一般会有合规要求和业务要求,超过一定期限的可以删除,以释放空间,提高查询检索效率。

这个历史文件清理可以做成定时任务,将各种需要清理的文件分类,根据不同的文件生命周期要求进行清理。

下面的例程中,ftp下用户目录的文件夹按15天以上清理,filezilla服务器配置文件users.xml的备份文件按5天以上清理,上传文件临时目录按8小时以上清理

javascript 复制代码
const fs = require('fs')
const path = require("path");

var log4js = require('log4js');
log4js.configure({
	appenders: {
		Clean: { 
			type: "dateFile", 
			filename: "logs/clean", 
			pattern: 'yyyy-MM-dd.log',
			alwaysIncludePattern: true,
			numbackups:14,
			layout: { type: "pattern", pattern: "%d %p %c %m%n" }
			}
		},
	categories: { default: { appenders: ["Clean"], level: "info" } }
	});
const logger = log4js.getLogger("Clean");

const uploadlifetime=8; //8小时
const ftplifetime=15;  //15天
const fzlifetime=5;  //5天
const uploads=["e:/rdfile/upload/dest"];
const ftps=["e:/rdfile/ftp1root","e:/rdfile/ftp2root","e:/rdfile/ftp3root","e:/rdfile/ftp4root"];
const fzs=["c:/FZ1","c:/FZ2","c:/FZ3","c:/FZ4"]

function rmdirp(dir) {
	return new Promise((resolve, reject) => {
		fs.stat(dir, (err, status)=> {
			if (err) reject(err);
			if (status.isDirectory()) {
				fs.readdir(dir, (err, file)=> {
					if (err) reject(err);
					let res = file.map((item) => rmdirp(path.join(dir, item)))
					Promise.all(res).then( () => {
						fs.rmdir(dir, err=>{ if (err) reject(err); resolve(); });
						})
					})
				}
			else {
				fs.unlink(dir, err=>{ if (err) reject(err); resolve(); });
				}
			})
		})
}

function cleanupload(targetPath){
	return new Promise((resolve, reject) => {
		logger.info(targetPath+" clean start");
		fs.readdir(targetPath,(err,subdirs)=>{
			if (err) reject(err);
			let res = subdirs.map((item) => { 
				let fullpath=targetPath+"/"+item; 
				fs.stat(fullpath,(err,sds) =>{
					if (err) reject(err);
					let sdsage=(now-sds.birthtimeMs)/1000/3600; 
					if (sdsage>uploadlifetime) { rmdirp(fullpath); } 
					else { resolve(); }
					}) 
				})
			Promise.all(res).then( () => { resolve(); })
			});
		})
}

function cleanftp(targetPath){
	return new Promise((resolve, reject) => {
		logger.info(targetPath+" clean start");
		fs.readdir(targetPath,(err,userdirs)=>{
			if (err) reject(err);
			let res = userdirs.map((userdir) => { 
				let stat = fs.statSync(targetPath+"/"+userdir);
				if (stat.isDirectory()) {
					fs.readdir(targetPath+"/"+userdir,(err1,usersubdirs)=>{
						if (err1) reject(err1);
						let res1 = usersubdirs.map((usersubdir) => { 
							let fullpath=targetPath+"/"+userdir+"/"+usersubdir;
							fs.stat(fullpath,(err2,sds) =>{
								if (err2) reject(err2);
								let sdsage=(now-sds.birthtimeMs)/1000/3600/24; 
								if (sdsage>ftplifetime) { rmdirp(fullpath); } 
								else { resolve(); }
								}) 
							})
						Promise.all(res1).then( () => { resolve(); })
						});
					}
				else { resolve(); }
				})
			Promise.all(res).then( () => { resolve(); })
			});
		});
}

function cleanfz(targetPath){
	return new Promise((resolve, reject) => {
		logger.info(targetPath+" clean start");
		fs.readdir(targetPath,(err,items)=>{
			if (err) reject(err);
			let res = items.filter(itm=>itm.startsWith("users.20")).map((item) => { 
				let fullpath=targetPath+"/"+item; 
				fs.stat(fullpath,(err,sds) =>{
					if (err) reject(err);
					let sdsage=(now-sds.birthtimeMs)/1000/3600/24; 
					if (sdsage>fzlifetime) { fs.unlink(fullpath, err=>{ if (err) reject(err); resolve(); }); } 
					else { resolve(); }
					}) 
				})
			Promise.all(res).then( () => { resolve(); })
			});
		})
}

var now=new Date().getTime();

uploads.forEach(item=>{
	cleanupload(item).then((resolve) =>{ logger.info(item+" clean done"); });
	});

ftps.forEach(item=>{
	cleanftp(item).then((resolve) =>{ logger.info(item+" clean done"); });
	})

fzs.forEach(item=>{
	cleanfz(item).then((resolve) =>{ logger.info(item+" clean done"); });
	})
相关推荐
我登哥MVP3 分钟前
SpringCloud Alibaba 核心组件解析:服务注册与发现(Nacos)
java·spring boot·后端·spring·spring cloud·java-ee·maven
摇滚侠22 分钟前
SpringMVC 入门到实战 处理静态资源的过程 64
java·后端·spring·maven·intellij-idea
RoboWizard26 分钟前
一块硬盘上架前要闯多少关?
java·服务器·数据库
CDN36028 分钟前
【工程化进阶】Lerna太慢?用 Turborepo + pnpm 打造拓扑级增量构建大仓
运维开发
Liquad Li36 分钟前
ABP vNext 标准分层解决方案项目结构完整解析
后端
十六年开源服务商37 分钟前
2026社交媒体营销×WordPress运维:实战避坑指南
运维·媒体
MageGojo38 分钟前
用 Node.js 把聚合 API 平台封装成零依赖命令行工具:registry 驱动的工程实践
node.js·restful·api接口·命令行工具·cli
吴阿福|一人公司38 分钟前
深度解析 Python 类变量修改的命名空间隔离
java·服务器·数据结构
江南风月40 分钟前
Hermes Agent 接入WGCLOUD实战:打造团队 AI 智能运维解决方案
运维·zabbix·运维开发·prometheus
黄焖鸡能干四碗1 小时前
软件系统概要设计说明书模版(Word)
大数据·运维·数据库·架构·需求分析