├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── doc └── images │ ├── BackupConfiguration.png │ ├── BackupConfigurationJob.png │ ├── EasyBackup.png │ ├── EasyBackupProperties.png │ ├── dashboard.png │ ├── dashboard_zh_CN.png │ └── mail.png ├── doc_en.md ├── doc_zh_CN.md ├── libs ├── easybackup_application │ ├── easybackup-application.jar │ ├── easybackup.properties │ ├── log4j.properties │ ├── readme.md │ ├── shutdown.bat │ ├── shutdown.sh │ ├── startup.bat │ ├── startup.sh │ └── template │ │ └── mail.tpl └── easybackup_engine_framework │ ├── easybackup-3.3.2-RELEASE-javadoc.jar │ ├── easybackup-3.3.2-RELEASE-sources.jar │ ├── easybackup-3.3.2-RELEASE.jar │ ├── easybackup-mysql-plugin-3.2.0-RELEASE-javadoc.jar │ ├── easybackup-mysql-plugin-3.2.0-RELEASE-sources.jar │ ├── easybackup-mysql-plugin-3.2.0-RELEASE.jar │ ├── easybackup.properties │ ├── readme.md │ └── template │ └── mail.tpl ├── projects ├── easybackup-mysql │ ├── easybackup.properties │ ├── pom.xml │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── cn │ │ │ └── easyproject │ │ │ └── easybackup │ │ │ └── mysql │ │ │ └── MySQLTargetFile.java │ └── template │ │ └── mail.tpl └── easybackup │ ├── easybackup.properties │ ├── pom.xml │ ├── src │ └── main │ │ ├── java │ │ └── cn │ │ │ └── easyproject │ │ │ └── easybackup │ │ │ ├── BackupRuntime.java │ │ │ ├── BackupType.java │ │ │ ├── EasyBackup.java │ │ │ ├── backup │ │ │ ├── BackupEngine.java │ │ │ ├── StdBackupEngine.java │ │ │ ├── file │ │ │ │ ├── BackupDir.java │ │ │ │ ├── BackupFile.java │ │ │ │ ├── TargetFile.java │ │ │ │ └── impl │ │ │ │ │ ├── DefaultBackupDir.java │ │ │ │ │ ├── DefaultBackupFile.java │ │ │ │ │ └── DefaultTargtFile.java │ │ │ ├── impls │ │ │ │ ├── Backup.java │ │ │ │ └── FileBackup.java │ │ │ └── interceptor │ │ │ │ ├── BackupAfter.java │ │ │ │ └── BackupBefore.java │ │ │ ├── configuration │ │ │ ├── BackupConfiguration.java │ │ │ └── GlobalConfiguration.java │ │ │ ├── job │ │ │ ├── BackupJob.java │ │ │ ├── JobManager.java │ │ │ └── ReloadConfigurationJob.java │ │ │ ├── sender │ │ │ ├── Sender.java │ │ │ └── mail │ │ │ │ └── MailSender.java │ │ │ └── util │ │ │ ├── CompressFileUtil.java │ │ │ ├── DecompressFileUtil.java │ │ │ ├── EasyUtil.java │ │ │ ├── FreemarkerUtil.java │ │ │ └── SpringUtil.java │ │ └── resources │ │ ├── applicationContext.xml │ │ └── log4j.properties │ └── template │ └── mail.tpl └── readme.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-language=Java 2 | 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['http://www.easyproject.cn/donation'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # maven ignore 2 | target/ 3 | *.war 4 | *.zip 5 | *.tar 6 | *.tar.gz 7 | 8 | # eclipse ignore 9 | .settings/ 10 | .project 11 | .classpath 12 | 13 | # idea ignore 14 | .idea/ 15 | *.ipr 16 | *.iml 17 | *.iws 18 | 19 | # temp ignore 20 | *.log 21 | *.cache 22 | *.diff 23 | *.patch 24 | *.tmp 25 | 26 | # system ignore 27 | .DS_Store 28 | Thumbs.db 29 | 30 | # else 31 | .springBeans 32 | projects/easybackup-application 33 | -------------------------------------------------------------------------------- /doc/images/BackupConfiguration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/BackupConfiguration.png -------------------------------------------------------------------------------- /doc/images/BackupConfigurationJob.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/BackupConfigurationJob.png -------------------------------------------------------------------------------- /doc/images/EasyBackup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/EasyBackup.png -------------------------------------------------------------------------------- /doc/images/EasyBackupProperties.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/EasyBackupProperties.png -------------------------------------------------------------------------------- /doc/images/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/dashboard.png -------------------------------------------------------------------------------- /doc/images/dashboard_zh_CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/dashboard_zh_CN.png -------------------------------------------------------------------------------- /doc/images/mail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/doc/images/mail.png -------------------------------------------------------------------------------- /doc_zh_CN.md: -------------------------------------------------------------------------------- 1 | # EasyBackup 2 | 3 | EasyBackup 是一个基于 Java 的免费开源跨平台内容备份压缩远程发送一体化任务调度应用及引擎框架。 4 | 5 | 能够为需要进行内容备份的程序场景提供一体化支持:集合了基于任务调度的内容备份,内容压缩,远程发送,命令执行等等功能。而这一切,仅需进行简单的配置管理即可完成。 6 | 7 | 请根据用途选择: 8 | - **EasyBackup Application**: 开箱即用版本,作为应用运行(`libs/easybackup_application`) 9 | - **EasyBackup Engine Framework**: 作为 Java 内容备份引擎框架扩展(`libs/easybackup_engine_framework`) 10 | 11 | 12 | ## TOC 13 | 14 | - [EasyBackup 特点](#easybackup-特点) 15 | - [EasyBackup 主要组件](#easybackup-主要组件) 16 | - [BackupConfiguration](#backupconfiguration) 17 | - [Properties](#properties) 18 | - [配置结构](#配置结构) 19 | - [全局配置(作为监控服务配置的全局默认值,可选)](#全局配置作为监控服务配置的全局默认值可选) 20 | - [备份服务配置(可以覆盖全局配置的默认值)](#备份服务配置可以覆盖全局配置的默认值) 21 | - [User 自定义配置说明](#user-自定义配置说明) 22 | - [变量使用](#变量使用) 23 | - [完全配置示例](#完全配置示例) 24 | - [邮件模板配置](#邮件模板配置) 25 | - [自定义模板配置](#自定义模板配置) 26 | - [模板内置变量](#模板内置变量) 27 | - [EasBackup Application](#easbackup-application) 28 | - [使用步骤](#使用步骤) 29 | - [EasyBackup Engine Framework](#easybackup-engine-framework) 30 | - [使用步骤](#使用步骤-1) 31 | - [自定义接口](#自定义接口) 32 | - [自定义配置文件和 freemarker 配置对象](#自定义配置文件和-freemarker-配置对象) 33 | - [运行时信息获取](#运行时信息获取) 34 | - [Plugins](#plugins) 35 | - [EasyBackup Web Manger](#easybackup-web-manger) 36 | - [End](#end) 37 | 38 | 39 | 40 | ## EasyBackup 特点 41 | 42 | - **开箱即用的内容压缩备份发送框架**。 43 | - **多种可选压缩格式**。支持 `ZIP`,`GZIP`,`TAR` 等格式 44 | - **备份远程发送**。支持将备份发送到邮箱,网络存储等等 45 | - **灵活的调度配置**。支持基于 `CronExpression` 的监控任务调度 46 | - **插件式扩展增强**。可扩展实现数据库备份等等;自定义目标文件来源(`TargetFile`)和备份文件对象(`BackupDir`, `BackupFile`),自定义备份实现(`Backup`),自定义拦截器(`Interceptor`),自定义发送器(`Sender`)。 47 | - **拦截器支持**。支持基于命令和自定义类的前置后置拦截器 48 | - **自定义通知模板**。基于 `freemarker` 的自定义通知模板,支持内置变量使用,更新模板自动重新加载 49 | - **热加载**。支持运行期间热修改 `easybackup.properties`,修改监控配置参数无需重启 EasyBackup 50 | - **多目录支持**。可同时将目标文件备份到多个目录 51 | - **多服务支持**。可同时运行多个备份压缩发送服务 52 | - **运行时信息反馈**。获得备份运行时状况 53 | - **配置简单灵活**。 54 | 55 | 56 | ## EasyBackup 主要组件 57 | 58 | - **Backup(备份)** 59 | 可以配置针对 `File`(文件备份), `USER`(用户自定义备份,如数据库备份等等) 两种类型的备份服务。备份方式支持文件直接备份和压缩备份。 60 | 61 | - **Compression(压缩)** 62 | 支持将目标文件压缩为 `ZIP`, `GZIP`, `TAR` 等格式。 63 | 64 | - **Sender(发送者)** 65 | 当备份完成,将备份结果发送到 `Email`、 `Web Storage` 等等,一个备份服务可以有多个 Sender。 66 | 67 | - **Commander&Class Interceptor(命令执行和拦截器)** 68 | 在备份开始前和完成后,自动执行相应拦截命令和类。 69 | 70 | - **Task Schedule(任务调度器)** 71 | 基于 `CronExpression` 的备份任务调度。 72 | 73 | ![EasyBackup principal components](doc/images/EasyBackup.png) 74 | 75 | 76 | 77 | ## BackupConfiguration 78 | 79 | - **备份术语**: 80 | 81 | - `targetFile`:待备份的目标文件 82 | 83 | - `dir`, `backupDir`:备份文件存储目录 84 | 85 | - `file`, `backupFile`:备份文件名 86 | 87 | 88 | - **BackupConfiguration 对象** 89 | 90 | 封装了每一项备份服务所需的相关数据和配置信息(`basic`),完全配置信息(`properties`),调度信息(`task schedure`),拦截器信息(`interceptor`),备份文件信息(`targetFile`, `backupDir`, `backupFile`),压缩信息(`compress`)和发送者(`senders`)。 91 | 92 | ![BackupConfiguration](doc/images/BackupConfiguration.png) 93 | 94 | - **BackupJob** 95 | 96 | EasyBackup 会根据 `BackupConfiguration` 对象,创建监控 Job。 97 | 98 | ![EasyBackup Job](doc/images/BackupConfigurationJob.png) 99 | 100 | ## Properties 101 | 102 | `easybackup.properties` 是 EasyBackup 的核心配置文件,配置了内容备份所需的所有信息。 103 | 104 | ### 配置结构 105 | 106 | ![EasyBackup Properties](doc/images/EasyBackupProperties.png) 107 | 108 | ### 全局配置(作为监控服务配置的全局默认值,可选) 109 | 110 | ```properties 111 | # Backup ON or OFF, default is ON 112 | # 备份服务默认是否打开,默认为 ON 113 | easybackup.enable=ON 114 | 115 | # Backup trigger Cron-Expressions 116 | # 备份服务的默认调度 Cron-Expressions; 默认为 '0 30 * * * ?' 117 | easybackup.cronexpression=0 30 * * * ? 118 | 119 | # Directory to store the backup file 120 | # You can specify more than one, separated by a ; 121 | # 文件备份目录,多个备份目录使用 ; 分隔 122 | easybackup.dir=/user/backup/ 123 | # backup file name under 'easybackup.backup.dir' directory 124 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 125 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime}, ${backupConfiguration.XXX} 126 | # 在文件备份目录下的备份的文件名 127 | # 默认为 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 128 | # 可以使用以下变量:${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 129 | easybackup.file= 130 | 131 | # Whether backup compression, default is OFF 132 | # 默认是否使用压缩备份,默认为 OFF 133 | easybackup.compress=OFF 134 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 135 | # 压缩备份使用的压缩方式,默认为 ZIP 136 | easybackup.compressType=ZIP 137 | # Comprssion encoding 138 | # 压缩文件使用的编码格式 139 | easybackup.compressEncoding= 140 | 141 | # Whether delete targetFile after backup complete, default is OFF 142 | # 备份完成后,是否删除已备份的目标文件,默认为 OFF 143 | easybackup.deleteTargetFile=OFF 144 | 145 | # Receive Backup file mail address 146 | # You can specify more than one, separated by a ; 147 | # 接收备份信息的邮箱列表,多个邮箱使用 ; 分隔 148 | easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 149 | 150 | # Send Mail Account Config 151 | # 邮箱发送者账户配置 152 | # Send Mail Account 153 | easybackup.mail.sender=sendermail@domain.com 154 | # Send Mail password 155 | # 邮箱发送者密码 156 | easybackup.mail.sender.passowrd=mailpassword 157 | # Send Mail SMTP host 158 | # 邮箱发送者 host 159 | easybackup.mail.sender.host=smtp.163.com 160 | # Send Mail SMTP port; default is 25 161 | # 邮箱发送者 host 端口 162 | easybackup.mail.sender.port=25 163 | # Send Mail Whether use SSL; default is false 164 | # 是否使用了 SSL 协议 165 | easybackup.mail.sender.ssl=false 166 | # Send Mail title 167 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 168 | # 邮件发送标题 169 | # 可以使用以下变量:${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 170 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 171 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 172 | # template 目录下的邮件发送模板,默认为 mail.tpl 173 | easybackup.mail.sender.template=mail.tpl 174 | 175 | # Auto delete when send email complete ON or OFF, default is OFF 176 | # 备份发送到邮箱后,是否删除备份文件,默认为 OFF 177 | easybackup.mail.deleteBackup=OFF 178 | 179 | # Execute Command when backup before or after 180 | # You can specify more than one, separated by a ; 181 | # 备份开始前或完成后执行的前置和后置命令脚本,多个命令脚本使用 ; 分隔 182 | easybackup.cmd.before= 183 | easybackup.cmd.after= 184 | 185 | # Execute Interceptor when backup before or after 186 | # You can specify more than one, separated by a ; 187 | # 备份开始前或完成后执行的前置和后置处理类,多个类完全限定名使用 ; 分隔 188 | easybackup.beforeClass= 189 | easybackup.afterClass= 190 | ``` 191 | 192 | ### 备份服务配置(可以覆盖全局配置的默认值) 193 | - **file** 文件备份服务配置 194 | - **user** 自定义备份服务配置 195 | 196 | `NAME` 是自定义的监控服务名称,每个监控服务由一组相同 `NAME` 的配置项组成。 197 | 198 | 199 | ```properties 200 | ######################## Backup Service configuration 201 | easybackup.[file|user].NAME=value 202 | easybackup.[file|user].NAME.enable=ON | OFF 203 | easybackup.[file|user].NAME.cronexpression=0/10 * * * * ? 204 | 205 | easybackup.[file|user].NAME.dir=/user/backup/;/user/backup2 206 | easybackup.[file|user].NAME.file= 207 | easybackup.[file|user].NAME.compress=ON | OFF 208 | easybackup.[file|user].NAME.compressType=ZIP | GZIP | TAR 209 | easybackup.[file|user].NAME.compressEncoding= 210 | easybackup.[file|user].NAME.deleteTargetFile=ON | OFF 211 | 212 | easybackup.user.NAME.targetFileClass=package.YourTargetFile 213 | easybackup.user.NAME.dirClass=package.YourBackupDir 214 | easybackup.user.NAME.fileClass=package.YourBackupFile 215 | easybackup.user.NAME.backupClass=package.YourBackup 216 | 217 | easybackup.[file|user].NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 218 | easybackup.[file|user].NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 219 | easybackup.[file|user].NAME.beforeClass=package.BackupBefore;package.BackupBefore2 220 | easybackup.[file|user].NAME.afterClass=package.BackupAfter;package.BackupAfter2 221 | 222 | easybackup.[file|user].NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 223 | 224 | easybackup.[file|user].NAME.mail.sender=sendermail@domain.com 225 | easybackup.[file|user].NAME.mail.sender.passowrd=sendermail_password 226 | easybackup.[file|user].NAME.mail.sender.host=sendermail_host 227 | easybackup.[file|user].NAME.mail.sender.port=sendermail_port 228 | easybackup.[file|user].NAME.mail.sender.ssl=sendermail_ssh 229 | easybackup.[file|user].NAME.mail.sender.title=sendermail_title 230 | easybackup.[file|user].NAME.mail.sender.template=mail.tpl 231 | easybackup.[file|user].NAME.mail.deleteBackup=ON | OFF 232 | 233 | easybackup.[file|user].NAME.senders=package.userSenderClass;package.userSenderClass2 234 | ``` 235 | 236 | ### User 自定义配置说明 237 | 238 | - `targetFileClass`:获取目标文件的自定义处理类,需要实现 `TargetFile` 接口,默认为 `cn.easyproject.easybackup.backup.file.impl.DefaultTargtFile` 239 | 240 | - `dirClass`:获取备份目录的自定义处理类,需要实现 `BackupDir` 接口,默认为 `cn.easyproject.easybackup.backup.file.impl.DefaultBackupDir` 241 | 242 | - `fileClass`:获取备份文件名的自定义处理类,需要实现 `BackupFile` 接口,默认为 `cn.easyproject.easybackup.backup.file.impl.DefaultBackupFile` 243 | 244 | - `backupClass`:完成备份实现的处理类,需要实现 `Badkup` 接口,默认为`cn.easyproject.easybackup.backup.impls.FileBackup` 245 | 246 | 247 | ### 变量使用 248 | 249 | - **备份文件名配置** 250 | 251 | 默认的备份文件名为 `${targetFileName}-yyyyMMddHHmmssS[.zip|tar|tar.gz]`,备份文件名可以包含以下 `Freemarker` 变量: 252 | 253 | ``` 254 | ${targetFileName}:目标文件名 255 | ${type}:备份类型(FILE、USER) 256 | ${name}:备份服务名称 257 | ${value}:备份服务值 258 | ${backuptime?string("yyyyMMddHHmmssS")}:备份时间 259 | ${backupConfiguration.XXX}:备份配置对象属性 260 | ``` 261 | 262 | 示例: 263 | 264 | ```properties 265 | easybackup.file=${targetFileName}-${type}-${backuptime?string("yyyyMMddHHmmss")}.bkp 266 | easybackup.[file|user].NAME.file=file-${backuptime?string("yyyyMMddHHmmss")}.bkp 267 | ``` 268 | 269 | 270 | 271 | 272 | - **邮件标题配置** 273 | 274 | 邮件标题可以包含以下 `Freemarker` 变量: 275 | 276 | ``` 277 | ${targetFileName}:目标文件名 278 | ${backupFileName}:备份文件名 279 | ${type}:备份类型(FILE、USER) 280 | ${name}:备份服务名称 281 | ${value}:备份服务值 282 | ${backuptime?datetime}:备份时间 283 | ${backupConfiguration.XXX}:备份配置对象属性 284 | ``` 285 | 286 | 示例: 287 | 288 | ```properties 289 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 290 | easybackup.[file|user].NAME.sender.title=Backup ${targetFileName}- EasyBackup 291 | ``` 292 | 293 | 294 | 295 | ## 完全配置示例 296 | ```properties 297 | ######################## Global Config(Optional) 全局配置(可选) 298 | 299 | # Backup ON or OFF, default is ON 300 | # 备份服务默认是否打开,默认为 ON 301 | easybackup.enable=ON 302 | 303 | # Backup trigger Cron-Expressions 304 | # 备份服务的默认调度 Cron-Expressions; 默认为 '0 30 * * * ?' 305 | easybackup.cronexpression=0 30 * * * ? 306 | 307 | # Directory to store the backup file 308 | # You can specify more than one, separated by a ; 309 | # 文件备份目录,多个备份目录使用 ; 分隔 310 | easybackup.dir=/user/backup/ 311 | # backup file name under 'easybackup.backup.dir' directory 312 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 313 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime}, ${backupConfiguration.XXX} 314 | # 在文件备份目录下的备份的文件名 315 | # 默认为 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 316 | # 可以使用以下变量:${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 317 | easybackup.file= 318 | 319 | # Whether backup compression, default is OFF 320 | # 默认是否使用压缩备份,默认为 OFF 321 | easybackup.compress=OFF 322 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 323 | # 压缩备份使用的压缩方式,默认为 ZIP 324 | easybackup.compressType=ZIP 325 | # Comprssion encoding 326 | # 压缩文件使用的编码格式 327 | easybackup.compressEncoding= 328 | 329 | # Whether delete targetFile after backup complete, default is OFF 330 | # 备份完成后,是否删除已备份的目标文件,默认为 OFF 331 | easybackup.deleteTargetFile=OFF 332 | 333 | # Receive Backup file mail address 334 | # You can specify more than one, separated by a ; 335 | # 接收备份信息的邮箱列表,多个邮箱使用 ; 分隔 336 | easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 337 | 338 | # Send Mail Account Config 339 | # 邮箱发送者账户配置 340 | # Send Mail Account 341 | easybackup.mail.sender=sendermail@domain.com 342 | # Send Mail password 343 | # 邮箱发送者密码 344 | easybackup.mail.sender.passowrd=mailpassword 345 | # Send Mail SMTP host 346 | # 邮箱发送者 host 347 | easybackup.mail.sender.host=smtp.163.com 348 | # Send Mail SMTP port; default is 25 349 | # 邮箱发送者 host 端口 350 | easybackup.mail.sender.port=25 351 | # Send Mail Whether use SSL; default is false 352 | # 是否使用了 SSL 协议 353 | easybackup.mail.sender.ssl=false 354 | # Send Mail title 355 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 356 | # 邮件发送标题 357 | # 可以使用以下变量:${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 358 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 359 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 360 | # template 目录下的邮件发送模板,默认为 mail.tpl 361 | easybackup.mail.sender.template=mail.tpl 362 | 363 | # Auto delete when send email complete ON or OFF, default is OFF 364 | # 备份发送到邮箱后,是否删除备份文件,默认为 OFF 365 | easybackup.mail.deleteBackup=OFF 366 | 367 | # Execute Command when backup before or after 368 | # You can specify more than one, separated by a ; 369 | # 备份开始前或完成后执行的前置和后置命令脚本,多个命令脚本使用 ; 分隔 370 | easybackup.cmd.before= 371 | easybackup.cmd.after= 372 | 373 | # Execute Interceptor when backup before or after 374 | # You can specify more than one, separated by a ; 375 | # 备份开始前或完成后执行的前置和后置处理类,多个类完全限定名使用 ; 分隔 376 | easybackup.beforeClass= 377 | easybackup.afterClass= 378 | 379 | 380 | ######################## Backup Service Configuration 监控配置 381 | 382 | ############ File Backup(can override global config) 383 | ## format: 384 | ## easybackup.file.NAME=value 385 | ## easybackup.file.NAME.enable=ON | OFF 386 | ## easybackup.file.NAME.cronexpression=0/10 * * * * ? 387 | ## easybackup.file.NAME.dir=/user/backup/;/user/backup2 388 | ## easybackup.file.NAME.file= 389 | ## easybackup.file.NAME.compress=ON | OFF 390 | ## easybackup.file.NAME.compressType=ZIP | GZIP | TAR 391 | ## easybackup.file.NAME.compressEncoding= 392 | ## easybackup.file.NAME.deleteTargetFile=ON | OFF 393 | ## easybackup.file.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 394 | ## easybackup.file.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 395 | ## easybackup.file.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 396 | ## easybackup.file.NAME.afterClass=package.BackupAfter;package.BackupAfter2 397 | ## easybackup.file.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 398 | ## easybackup.file.NAME.mail.sender=sendermail@domain.com 399 | ## easybackup.file.NAME.mail.sender.passowrd=sendermail_password 400 | ## easybackup.file.NAME.mail.sender.host=sendermail_host 401 | ## easybackup.file.NAME.mail.sender.port=sendermail_port 402 | ## easybackup.file.NAME.mail.sender.ssl=sendermail_ssh 403 | ## easybackup.file.NAME.mail.sender.title=sendermail_title 404 | ## easybackup.file.NAME.mail.sender.template=mail.tpl 405 | ## easybackup.file.NAME.mail.deleteBackup=ON | OFF 406 | ## easybackup.file.NAME.senders=package.userSenderClass;package.userSenderClass2 407 | 408 | 409 | 410 | # Example: 411 | easybackup.file.LOG=D:/log 412 | easybackup.file.LOG.enable=ON 413 | easybackup.file.LOG.dir=D:/backup/logfile/;E:/backup/logfile 414 | easybackup.file.LOG.cronexpression=0 30 * * * ? 415 | easybackup.file.LOG.compress=ON 416 | easybackup.file.LOG.compressType=ZIP 417 | #easybackup.file.LOG.mail.receiver=mail@domain.com 418 | 419 | 420 | ############ Port Monitor(can override global config) 421 | ## format: 422 | ## easybackup.user.NAME=value 423 | ## easybackup.user.NAME.enable=ON | OFF 424 | ## easybackup.user.NAME.cronexpression=0/10 * * * * ? 425 | ## easybackup.user.NAME.dir=/user/backup/;/user/backup2 426 | ## easybackup.user.NAME.file= 427 | ## easybackup.user.NAME.compress=ON | OFF 428 | ## easybackup.user.NAME.compressType=ZIP | GZIP | TAR 429 | ## easybackup.user.NAME.compressEncoding= 430 | ## easybackup.user.NAME.deleteTargetFile=ON | OFF 431 | ## easybackup.user.NAME.targetFileClass=package.YourTargetFile 432 | ## easybackup.user.NAME.dirClass=package.YourBackupDir 433 | ## easybackup.user.NAME.fileClass=package.YourBackupFile 434 | ## easybackup.user.NAME.backupClass=package.YourBackup 435 | ## easybackup.user.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 436 | ## easybackup.user.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 437 | ## easybackup.user.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 438 | ## easybackup.user.NAME.afterClass=package.BackupAfter;package.BackupAfter2 439 | ## easybackup.user.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 440 | ## easybackup.user.NAME.mail.sender=sendermail@domain.com 441 | ## easybackup.user.NAME.mail.sender.passowrd=sendermail_password 442 | ## easybackup.user.NAME.mail.sender.host=sendermail_host 443 | ## easybackup.user.NAME.mail.sender.port=sendermail_port 444 | ## easybackup.user.NAME.mail.sender.ssl=sendermail_ssh 445 | ## easybackup.user.NAME.mail.sender.title=sendermail_title 446 | ## easybackup.user.NAME.mail.sender.template=mail.tpl 447 | ## easybackup.user.NAME.mail.deleteBackup=ON | OFF 448 | ## easybackup.user.NAME.senders=package.userSenderClass;package.userSenderClass2 449 | 450 | # Example: 451 | easybackup.user.MySQL=mysqldump -uroot -proot demoDB 452 | easybackup.user.MySQL.targetFileClass=cn.easyproject.easybackup.mysql.MySQLTargetFile 453 | easybackup.user.MySQL.dir=D:/backup/;E:/backupdb 454 | # default targetFileName is 'demoDB-yyyyMMddHHmmssS.sql' 455 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 456 | easybackup.user.MySQL.file= demodb-${backuptime?string("yyyyMMddHHmmss")}-backup.sql 457 | easybackup.user.MySQL.compress=ON 458 | easybackup.user.MySQL.compressType=ZIP 459 | easybackup.user.MySQL.cronexpression=0 0 2 * * ? 460 | #easybackup.user.MySQL.mail.receiver=mail@domain.com 461 | ``` 462 | 463 | 464 | 465 | ## 邮件模板配置 466 | EasyBackup 使用了 `freemarker` 模板技术进行邮件内容渲染,模板必须存放在 `template` 目录下,默认使用 `mail.tpl` 模板。 467 | 468 | 469 | ![mail.tpl](doc/images/mail.png) 470 | 471 | 472 | ### 自定义模板配置 473 | 474 | 您可以直接修改模板内容,或者编写您自己的邮件发送模板。 475 | 476 | ```properties 477 | ### Global configuration 478 | easybackup.mail.sender.template=yourmail.tpl 479 | 480 | ### Monitor Service configuration 481 | easybackup.[file|user].NAME.mail.sender.template=yourmail.tpl 482 | ``` 483 | 484 | ### 模板内置变量 485 | ``` 486 | ${targetFileName}:备份的模板文件名 487 | ${type}:备份类型(FILE、USER) 488 | ${name}:备份服务名称 489 | ${value}:备份服务值 490 | ${backuptime}:备份时间 491 | ${backupConfiguration.XXX}:备份配置对象属性 492 | ``` 493 | 494 | 495 | ## EasBackup Application 496 | 497 | **EasBackup Application**(`libs/easybackup_application`) 是开箱即用的 EasBackup 备份应用。按需配置您的备份服务,启动即可。 498 | 499 | EasyBackup Application 已经包含了当前官方的而所有插件。如果您开发了新的插件,可以将插件的内容直接添加到 `easybackup-application.jar` 中。 500 | 501 | **内置插件**: 502 | 503 | - `easybackup-mysql-plugin-3.2.0-RELEASE.jar`: **MySQL 数据库备份插件** 504 | 505 | ### 使用步骤 506 | 507 | 1. **配置备份服务** 508 | 509 | 参考 `easybackup.properties` 中的示例,配置您的备份服务。 510 | 511 | 2. **运行 EasyBackup** 512 | 513 | - **Windows**(Sometimes you must '`Run as Administrator`') 514 | 515 | ``` 516 | Start: startup.bat 517 | Stop: shutdown.bat 518 | ``` 519 | 520 | - **Linux** 521 | 522 | ``` 523 | Start: ./startup.sh 524 | Stop: ./shutdown.sh 525 | ``` 526 | 527 | 3. **可选配置** 528 | 1. **邮件模板 Mail template** 529 | 530 | 修改 '`template/mail.tpl`' 定制您的邮件内容。 531 | 532 | 2. **日志 Logger** 533 | 534 | 配置 `log4j.properties` 日志输出。 535 | 536 | 537 | 538 | ## EasyBackup Engine Framework 539 | 540 | EasyBackup 同时是一个免费开源跨平台的 Java 内容备份引擎框架(**EasyBackup Engine Framework**)(`libs/easybackup_engine_framework`),提供统一规范的备份配置和核心调度。 541 | 542 | ### 使用步骤 543 | 544 | 1. Maven dependency 545 | 546 | ```XML 547 | 548 | cn.easyproject 549 | easybackup 550 | 3.3.2-RELEASE 551 | 552 | ``` 553 | 554 | 2. 自定义接口实现 555 | 556 | 3. 配置 `easybackup.properties` 557 | 558 | 4. 启动 559 | ```JAVA 560 | public static void main(String[] args) { 561 | new EasyBackup().start(); 562 | } 563 | ``` 564 | 565 | ### 自定义接口 566 | 567 | EasyBackup 提供了极大的灵活性,扩展以下接口,即可自定义您的备份内容: 568 | 569 | - **TargetFile 目标文件来源**(`cn.easyproject.easybackup.backup.file.TargetFile`) 570 | 571 | **返回值**: 自定义的 `java.io.File` 目标文件对象 572 | 573 | **配置**: `easybackup.user.NAME.targetFileClass` 574 | 575 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultTargtFile` 576 | 577 | - **BackupDir 备份文件目录**(`cn.easyproject.easybackup.backup.file.BackupDir`) 578 | 579 | **返回值**: 自定义的 `java.io.File` 备份目录对象 580 | 581 | **配置**: `easybackup.user.NAME.dirClass` 582 | 583 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupDir` 584 | 585 | - **BackupFile 备份文件名称**(`cn.easyproject.easybackup.backup.file.BackupFile`) 586 | 587 | **返回值**: 自定义的 `String` 备份文件名 588 | 589 | **配置**: `easybackup.user.NAME.fileClass` 590 | 591 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupFile` 592 | 593 | - **Backup 备份实现**(`cn.easyproject.easybackup.backup.impls.Backup`) 594 | 595 | **返回值**: 根据传入备份文件信息,自定义备份处理实现,返回是否备份成功 596 | 597 | **配置**: `easybackup.user.NAME.backupClass` 598 | 599 | **参数默认值**: `cn.easyproject.easybackup.backup.impls.FileBackup` 600 | 601 | - **BackupBefore 前置拦截器**(`cn.easyproject.easybackup.backup.interceptor.BackupBefore`) 602 | 603 | **返回值**: 返回是否继续备份 604 | 605 | **配置**: `easybackup.user.NAME.beforeClass` 606 | 607 | **参数默认值**: 608 | 609 | - **BackupAfter 后置拦截器**(`cn.easyproject.easybackup.backup.interceptor.BackupAfter`) 610 | 611 | **返回值**: 612 | 613 | **配置**: `easybackup.user.NAME.afterClass` 614 | 615 | **参数默认值**: 616 | 617 | - **Sender 发送器**(`cn.easyproject.easybackup.sender.Sender`) 618 | 619 | **返回值**: 620 | 621 | **配置**: `easybackup.[file|user].NAME.senders` 622 | 623 | **参数默认值**: 624 | 625 | 626 | ### 自定义配置文件和 freemarker 配置对象 627 | 为了提供更多灵活性,EasyBackup 允许在启动备份服务前自定义**配置文件对象 Properties File**(`easybackup.properties`) 和邮件发送时的 **freemarker 配置对象**(`Configuration`)。 628 | 629 | ```JAVA 630 | // 自定义配置文件对象 631 | EasyBackup.setPropertiesFile(java.io.File propertiesFile); 632 | 633 | // 自定义邮件发送的 freemarker 配置对象 634 | MailSender.setFreemarkerConfiguration(freemarker.template.Configuration configuration); 635 | ``` 636 | 637 | 示例: 638 | 639 | ```JAVA 640 | // Custom EasyBackup initialization Parameter 641 | 642 | // 自定义配置文件对象 643 | Resource res = new ServletContextResource(sce.getServletContext(), "/easybackup.properties"); 644 | try { 645 | // Properties File 646 | EasyBackup.setPropertiesFile(res.getFile()); 647 | } catch (IOException e) { 648 | e.printStackTrace(); 649 | } 650 | 651 | // 自定义邮件发送的 freemarker 配置对象 652 | Configuration cfg= new Configuration(Configuration.VERSION_2_3_23); 653 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 654 | cfg.setDefaultEncoding("UTF-8"); 655 | cfg.setServletContextForTemplateLoading(sce.getServletContext(), "/template"); 656 | // MailSender Configuration 657 | MailSender.setFreemarkerConfiguration(cfg); 658 | ``` 659 | 660 | ### 运行时信息获取 661 | 662 | `cn.easyproject.easybackup.BackupRuntime` 提供了备份运行时的信息。 663 | 664 | ``` 665 | # 备份控制 666 | start():启动 667 | stop():停止 668 | 669 | # 启动后的运行状态信息 670 | started: 是否启动 671 | allBackupsOnStartup:所有配置的服务 672 | errorJobBackupsOnStartup:任务启动失败的服务 673 | runningBackupsOnStartup:正在运行的服务 674 | 675 | # 配置信息 676 | getBackupNames():所有配置的服务名称 677 | getBackupsConfigurations():所有备份服务配置对象 678 | getEnableBackupsConfigurations():所有设为启用(enable=ON)的备份服务配置对象 679 | getGlobalBackupsConfiguration():全局备份配置对象 680 | getProperties():Properties对象 681 | getPropertiesFile():Properties File 对象 682 | ``` 683 | 684 | ## Plugins 685 | 686 | - `easybackup-mysql-plugin-3.2.0-RELEASE.jar` MySQL Databasse Backup plugin 687 | 688 | ## EasyBackup Web Manger 689 | 690 | [EasyBackup Web Manger](https://github.com/ushelp/EasyBackup-Web "移步 EasyBackup Web Manger") 是一个基于 EasyBackup 框架引擎的 Java Web 管理器,可以在 Web UI 下完成备份配置管理,备份启动,停止控制。 691 | 692 | ![EasyBackup web manager](doc/images/dashboard_zh_CN.png) 693 | 694 | 695 | ## End 696 | 697 | Email: 698 | 699 | [http://www.easyproject.cn](http://www.easyproject.cn "EasyProject Home") 700 | 701 | 702 | **Donation/捐助:** 703 | 704 | 705 | 
706 | 支付宝/微信/QQ/云闪付/PayPal 扫码支付 707 |
支付宝/微信/QQ/云闪付/PayPal
708 | 709 |
710 | 711 | 我们相信,每个人的点滴贡献,都将是推动产生更多、更好免费开源产品的一大步。 712 | 713 | **感谢慷慨捐助,以支持服务器运行和鼓励更多社区成员。** 714 | 715 | We believe that the contribution of each bit by bit, will be driven to produce more and better free and open source products a big step. 716 | 717 | **Thank you donation to support the server running and encourage more community members.** 718 | -------------------------------------------------------------------------------- /libs/easybackup_application/easybackup-application.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_application/easybackup-application.jar -------------------------------------------------------------------------------- /libs/easybackup_application/easybackup.properties: -------------------------------------------------------------------------------- 1 | ######################## Global Config(Optional) 2 | 3 | # Backup ON or OFF, default is ON 4 | easybackup.enable=ON 5 | 6 | # Backup trigger Cron-Expressions 7 | easybackup.cronexpression=0 30 * * * ? 8 | 9 | # Directory to store the backup file 10 | # You can specify more than one, separated by a ; 11 | easybackup.dir=/user/backup/ 12 | # backup file name under 'easybackup.backup.dir' directory 13 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 14 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime}, ${backupConfiguration.XXX} 15 | easybackup.file= 16 | 17 | # Whether backup compression, default is OFF 18 | easybackup.compress=OFF 19 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 20 | easybackup.compressType=ZIP 21 | # Comprssion encoding 22 | easybackup.compressEncoding= 23 | 24 | # Whether delete targetFile after backup complete, default is OFF 25 | easybackup.deleteTargetFile=OFF 26 | 27 | # Receive Backup file mail address 28 | # You can specify more than one, separated by a ; 29 | easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 30 | 31 | # Send Mail Account Config 32 | # Send Mail Account 33 | easybackup.mail.sender=sendermail@domain.com 34 | # Send Mail password 35 | easybackup.mail.sender.passowrd=mailpassword 36 | # Send Mail SMTP host 37 | easybackup.mail.sender.host=smtp.163.com 38 | # Send Mail SMTP port; default is 25 39 | easybackup.mail.sender.port=25 40 | # Send Mail Whether use SSL; default is false 41 | # \u662F\u5426\u4F7F\u7528\u4E86 SSL \u534F\u8BAE 42 | easybackup.mail.sender.ssl=false 43 | # Send Mail title 44 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 45 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 46 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 47 | easybackup.mail.sender.template=mail.tpl 48 | 49 | # Auto delete when send email complete ON or OFF, default is OFF 50 | easybackup.mail.deleteBackup=OFF 51 | 52 | # Execute Command when backup before or after 53 | # You can specify more than one, separated by a ; 54 | easybackup.cmd.before= 55 | easybackup.cmd.after= 56 | 57 | # Execute Interceptor when backup before or after 58 | # You can specify more than one, separated by a ; 59 | easybackup.beforeClass= 60 | easybackup.afterClass= 61 | 62 | 63 | ######################## Backup Service Configuration \u76D1\u63A7\u914D\u7F6E 64 | 65 | ############ File Backup(can override global config) 66 | ## format: 67 | ## easybackup.file.NAME=value 68 | ## easybackup.file.NAME.enable=ON | OFF 69 | ## easybackup.file.NAME.cronexpression=0/10 * * * * ? 70 | ## easybackup.file.NAME.dir=/user/backup/##/user/backup2 71 | ## easybackup.file.NAME.file= 72 | ## easybackup.file.NAME.compress=ON | OFF 73 | ## easybackup.file.NAME.compressType=ZIP | GZIP | TAR 74 | ## easybackup.file.NAME.compressEncoding= 75 | ## easybackup.file.NAME.deleteTargetFile=ON | OFF 76 | ## easybackup.file.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 77 | ## easybackup.file.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 78 | ## easybackup.file.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 79 | ## easybackup.file.NAME.afterClass=package.BackupAfter;package.BackupAfter2 80 | ## easybackup.file.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 81 | ## easybackup.file.NAME.mail.sender=sendermail@domain.com 82 | ## easybackup.file.NAME.mail.sender.passowrd=sendermail_password 83 | ## easybackup.file.NAME.mail.sender.host=sendermail_host 84 | ## easybackup.file.NAME.mail.sender.port=sendermail_port 85 | ## easybackup.file.NAME.mail.sender.ssl=sendermail_ssh 86 | ## easybackup.file.NAME.mail.sender.title=sendermail_title 87 | ## easybackup.file.NAME.mail.sender.template=mail.tpl 88 | ## easybackup.file.NAME.mail.deleteBackup=ON | OFF 89 | ## easybackup.file.NAME.senders=package.userSenderClass##package.userSenderClass2 90 | 91 | 92 | 93 | # Example: 94 | #easybackup.file.LOG=D:/log 95 | #easybackup.file.LOG.enable=ON 96 | #easybackup.file.LOG.dir=D:/backup/logfile/;E:/backup/logfile 97 | #easybackup.file.LOG.cronexpression=0 30 * * * ? 98 | #easybackup.file.LOG.compress=ON 99 | #easybackup.file.LOG.compressType=ZIP 100 | #easybackup.file.LOG.mail.receiver=mail@domain.com 101 | 102 | 103 | ############ Port Monitor(can override global config) 104 | ## format: 105 | ## easybackup.user.NAME=value 106 | ## easybackup.user.NAME.enable=ON | OFF 107 | ## easybackup.user.NAME.cronexpression=0/10 * * * * ? 108 | ## easybackup.user.NAME.dir=/user/backup/;/user/backup2 109 | ## easybackup.user.NAME.file= 110 | ## easybackup.user.NAME.compress=ON | OFF 111 | ## easybackup.user.NAME.compressType=ZIP | GZIP | TAR 112 | ## easybackup.user.NAME.compressEncoding= 113 | ## easybackup.user.NAME.deleteTargetFile=ON | OFF 114 | ## easybackup.user.NAME.targetFileClass=package.YourTargetFile 115 | ## easybackup.user.NAME.dirClass=package.YourBackupDir 116 | ## easybackup.user.NAME.fileClass=package.YourBackupFile 117 | ## easybackup.user.NAME.backupClass=package.YourBackup 118 | ## easybackup.user.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 119 | ## easybackup.user.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 120 | ## easybackup.user.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 121 | ## easybackup.user.NAME.afterClass=package.BackupAfter;package.BackupAfter2 122 | ## easybackup.user.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 123 | ## easybackup.user.NAME.mail.sender=sendermail@domain.com 124 | ## easybackup.user.NAME.mail.sender.passowrd=sendermail_password 125 | ## easybackup.user.NAME.mail.sender.host=sendermail_host 126 | ## easybackup.user.NAME.mail.sender.port=sendermail_port 127 | ## easybackup.user.NAME.mail.sender.ssl=sendermail_ssh 128 | ## easybackup.user.NAME.mail.sender.title=sendermail_title 129 | ## easybackup.user.NAME.mail.sender.template=mail.tpl 130 | ## easybackup.user.NAME.mail.deleteBackup=ON | OFF 131 | ## easybackup.user.NAME.senders=package.userSenderClass;package.userSenderClass2 132 | 133 | # Example: 134 | easybackup.user.MySQL=mysqldump -uroot -proot test 135 | easybackup.user.MySQL.targetFileClass=cn.easyproject.easybackup.mysql.MySQLTargetFile 136 | easybackup.user.MySQL.dir=D:/backup 137 | # default targetFileName is 'demoDB-yyyyMMddHHmmssS.sql' 138 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 139 | easybackup.user.MySQL.file= demodb-${backuptime?string("yyyyMMddHHmmss")}-backup.sql 140 | easybackup.user.MySQL.compress=ON 141 | easybackup.user.MySQL.compressType=ZIP 142 | easybackup.user.MySQL.cronexpression=0/5 * * * * ? 143 | easybackup.user.MySQL.mail.receiver= 144 | easybackup.user.MySQL.mail.sender= -------------------------------------------------------------------------------- /libs/easybackup_application/log4j.properties: -------------------------------------------------------------------------------- 1 | # Logger 2 | log4j.rootLogger=INFO,console 3 | 4 | ## file 5 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender 6 | log4j.appender.file.File=easybackup.log 7 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.file.layout.ConversionPattern= %d{yyyy MMM dd HH:mm:ss,SSS} %p - %m%n 9 | 10 | 11 | ## console 12 | log4j.appender.console=org.apache.log4j.ConsoleAppender 13 | log4j.appender.console.layout=org.apache.log4j.SimpleLayout 14 | 15 | -------------------------------------------------------------------------------- /libs/easybackup_application/readme.md: -------------------------------------------------------------------------------- 1 | # EasyBackup Application 2 | 3 | 4 | 5 | ## 中文 6 | 7 | 8 | **EasBackup Application** 是开箱即用的 EasBackup 备份应用。按需配置您的备份服务,启动即可。 9 | 10 | EasyBackup Application 已经包含了当前官方的而所有插件。如果您开发了新的插件,可以将插件的内容直接添加到 `easybackup-application.jar` 中。 11 | 12 | ### 内置插件: 13 | 14 | - `easybackup-mysql-plugin-3.2.0-RELEASE.jar`: **MySQL 数据库备份插件** 15 | 16 | 17 | ### 使用步骤 18 | 19 | 1. **配置备份服务** 20 | 21 | 参考 `easybackup.properties` 中的示例,配置您的备份服务。 22 | 23 | 2. **运行 EasyBackup** 24 | 25 | - **Windows**(Sometimes you must '`Run as Administrator`') 26 | 27 | ``` 28 | Start: startup.bat 29 | Stop: shutdown.bat 30 | ``` 31 | 32 | - **Linux** 33 | 34 | ``` 35 | Start: ./startup.sh 36 | Stop: ./shutdown.sh 37 | ``` 38 | 39 | 3. **可选配置** 40 | 1. **邮件模板 Mail template** 41 | 42 | 修改 '`template/mail.tpl`' 定制您的邮件内容。 43 | 44 | 2. **日志 Logger** 45 | 46 | 配置 `log4j.properties` 日志输出。 47 | 48 | 49 | 50 | ## English 51 | 52 | **EasBackup Application** can run as application. Configure your backup service as needed, can be activated. 53 | 54 | EasyBackup Application already contains the current official and all plug-ins. If you develop a new plug-in, plug-in content can be added directly to the `easybackup-X.X.X-RELEASE-APPLICATION.jar` in. 55 | 56 | ### Plugins: 57 | 58 | - `easybackup-mysql-plugin-3.2.0-RELEASE.jar`: **MySQL Database backup plugin** 59 | 60 | ### Steps for usage 61 | 62 | 1. **Configuration Backup Service** 63 | 64 | `easybackup.properties` the reference sample, configure your backup service. 65 | 66 | 2. **Run EasyBackup** 67 | 68 | - **Windows**(Sometimes you must '`Run as Administrator`') 69 | 70 | ``` 71 | Start: startup.bat 72 | Stop: shutdown.bat 73 | ``` 74 | 75 | - **Linux** 76 | 77 | ``` 78 | Start: ./startup.sh 79 | Stop: ./shutdown.sh 80 | ``` 81 | 82 | 3. **Optional** 83 | 1. **Mail template** 84 | 85 | edit '`template/mail.tpl`' to custom your mail content. 86 | 87 | 2. **Logger** 88 | 89 | configuration `log4j.properties` log out. 90 | 91 | 92 | 93 | ## End 94 | 95 | -------------------------------------------------------------------------------- /libs/easybackup_application/shutdown.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd /d %~dp0 3 | echo EasyBackup shutdown... 4 | rem jps -mlvV| findstr easybackup.*.jar |taskkill -F -PID 4468 5 | for /f "tokens=*" %%i in ('jps -mlvV ^| findstr easybackup.*.jar') do set value=%%i 6 | if "%value%"=="" (goto notrun ) else ( goto shutdown ) 7 | 8 | :shutdown 9 | rem echo %value% 10 | rem echo %value:~0,5% 11 | set pid=%value:~0,5% 12 | rem echo %pid% 13 | taskkill -F -PID %pid% | findstr x 14 | set value= 15 | set pid= 16 | goto end 17 | 18 | :notrun 19 | echo not runing 20 | 21 | :end 22 | echo EasyBackup stoped. 23 | pause 24 | -------------------------------------------------------------------------------- /libs/easybackup_application/shutdown.sh: -------------------------------------------------------------------------------- 1 | echo 'EasyBackup shutdown...' 2 | ps -ef|grep easybackup.*.jar | grep -v grep |awk '{print $2}' | xargs kill -9 3 | echo 'EasyBackup stoped.' 4 | -------------------------------------------------------------------------------- /libs/easybackup_application/startup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo EasyBackup starting... 3 | echo The log in easybackup.out 4 | cd /d %~dp0 5 | java -jar easybackup-application.jar 6 | echo EasyBackup started. -------------------------------------------------------------------------------- /libs/easybackup_application/startup.sh: -------------------------------------------------------------------------------- 1 | echo 'EasyBackup starting...' 2 | echo 'The log in easybackup.out' 3 | nohup java -jar easybackup-application.jar >/dev/null 2>&1 & 4 | echo 'EasyBackup started.' 5 | -------------------------------------------------------------------------------- /libs/easybackup_application/template/mail.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 |
14 | EasyBackup 15 |
16 | 17 |
18 |

Hello,

19 |

Your backup service is complete.

20 |

21 | Name: ${name} - [${type}] 22 |

23 |

24 | Target: ${value} 25 |

26 |

27 | Backup time: ${backuptime?datetime} 28 |

29 |

30 | Please check your E-mail attachments. 31 |

32 |
33 |
34 | EasyMonitor by easyproject.cn 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE-javadoc.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE-sources.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-3.3.2-RELEASE.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE-javadoc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE-javadoc.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE-sources.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE-sources.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ushelp/EasyBackup/6644401aeb454c3d2008566cfaf0cb6a9174ff0a/libs/easybackup_engine_framework/easybackup-mysql-plugin-3.2.0-RELEASE.jar -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/easybackup.properties: -------------------------------------------------------------------------------- 1 | ######################## Global Config(Optional) 2 | 3 | # Backup ON or OFF, default is ON 4 | easybackup.enable=ON 5 | 6 | # Backup trigger Cron-Expressions 7 | easybackup.cronexpression=0 30 * * * ? 8 | 9 | # Directory to store the backup file 10 | # You can specify more than one, separated by a ; 11 | easybackup.dir=/user/backup/ 12 | # backup file name under 'easybackup.backup.dir' directory 13 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 14 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime}, ${backupConfiguration.XXX} 15 | easybackup.file= 16 | 17 | # Whether backup compression, default is OFF 18 | easybackup.compress=OFF 19 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 20 | easybackup.compressType=ZIP 21 | # Comprssion encoding 22 | easybackup.compressEncoding= 23 | 24 | # Whether delete targetFile after backup complete, default is OFF 25 | easybackup.deleteTargetFile=OFF 26 | 27 | # Receive Backup file mail address 28 | # You can specify more than one, separated by a ; 29 | easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 30 | 31 | # Send Mail Account Config 32 | # Send Mail Account 33 | easybackup.mail.sender=sendermail@domain.com 34 | # Send Mail password 35 | easybackup.mail.sender.passowrd=mailpassword 36 | # Send Mail SMTP host 37 | easybackup.mail.sender.host=smtp.163.com 38 | # Send Mail SMTP port; default is 25 39 | easybackup.mail.sender.port=25 40 | # Send Mail Whether use SSL; default is false 41 | # \u662F\u5426\u4F7F\u7528\u4E86 SSL \u534F\u8BAE 42 | easybackup.mail.sender.ssl=false 43 | # Send Mail title 44 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 45 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 46 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 47 | easybackup.mail.sender.template=mail.tpl 48 | 49 | # Auto delete when send email complete ON or OFF, default is OFF 50 | easybackup.mail.deleteBackup=OFF 51 | 52 | # Execute Command when backup before or after 53 | # You can specify more than one, separated by a ; 54 | easybackup.cmd.before= 55 | easybackup.cmd.after= 56 | 57 | # Execute Interceptor when backup before or after 58 | # You can specify more than one, separated by a ; 59 | easybackup.beforeClass= 60 | easybackup.afterClass= 61 | 62 | 63 | ######################## Backup Service Configuration \u76D1\u63A7\u914D\u7F6E 64 | 65 | ############ File Backup(can override global config) 66 | ## format: 67 | ## easybackup.file.NAME=value 68 | ## easybackup.file.NAME.enable=ON | OFF 69 | ## easybackup.file.NAME.cronexpression=0/10 * * * * ? 70 | ## easybackup.file.NAME.dir=/user/backup/##/user/backup2 71 | ## easybackup.file.NAME.file= 72 | ## easybackup.file.NAME.compress=ON | OFF 73 | ## easybackup.file.NAME.compressType=ZIP | GZIP | TAR 74 | ## easybackup.file.NAME.compressEncoding= 75 | ## easybackup.file.NAME.deleteTargetFile=ON | OFF 76 | ## easybackup.file.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 77 | ## easybackup.file.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 78 | ## easybackup.file.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 79 | ## easybackup.file.NAME.afterClass=package.BackupAfter;package.BackupAfter2 80 | ## easybackup.file.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 81 | ## easybackup.file.NAME.mail.sender=sendermail@domain.com 82 | ## easybackup.file.NAME.mail.sender.passowrd=sendermail_password 83 | ## easybackup.file.NAME.mail.sender.host=sendermail_host 84 | ## easybackup.file.NAME.mail.sender.port=sendermail_port 85 | ## easybackup.file.NAME.mail.sender.ssl=sendermail_ssh 86 | ## easybackup.file.NAME.mail.sender.title=sendermail_title 87 | ## easybackup.file.NAME.mail.sender.template=mail.tpl 88 | ## easybackup.file.NAME.mail.deleteBackup=ON | OFF 89 | ## easybackup.file.NAME.senders=package.userSenderClass##package.userSenderClass2 90 | 91 | 92 | 93 | # Example: 94 | #easybackup.file.LOG=D:/log 95 | #easybackup.file.LOG.enable=ON 96 | #easybackup.file.LOG.dir=D:/backup/logfile/;E:/backup/logfile 97 | #easybackup.file.LOG.cronexpression=0 30 * * * ? 98 | #easybackup.file.LOG.compress=ON 99 | #easybackup.file.LOG.compressType=ZIP 100 | #easybackup.file.LOG.mail.receiver=mail@domain.com 101 | 102 | 103 | ############ Port Monitor(can override global config) 104 | ## format: 105 | ## easybackup.user.NAME=value 106 | ## easybackup.user.NAME.enable=ON | OFF 107 | ## easybackup.user.NAME.cronexpression=0/10 * * * * ? 108 | ## easybackup.user.NAME.dir=/user/backup/;/user/backup2 109 | ## easybackup.user.NAME.file= 110 | ## easybackup.user.NAME.compress=ON | OFF 111 | ## easybackup.user.NAME.compressType=ZIP | GZIP | TAR 112 | ## easybackup.user.NAME.compressEncoding= 113 | ## easybackup.user.NAME.deleteTargetFile=ON | OFF 114 | ## easybackup.user.NAME.targetFileClass=package.YourTargetFile 115 | ## easybackup.user.NAME.dirClass=package.YourBackupDir 116 | ## easybackup.user.NAME.fileClass=package.YourBackupFile 117 | ## easybackup.user.NAME.backupClass=package.YourBackup 118 | ## easybackup.user.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 119 | ## easybackup.user.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 120 | ## easybackup.user.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 121 | ## easybackup.user.NAME.afterClass=package.BackupAfter;package.BackupAfter2 122 | ## easybackup.user.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 123 | ## easybackup.user.NAME.mail.sender=sendermail@domain.com 124 | ## easybackup.user.NAME.mail.sender.passowrd=sendermail_password 125 | ## easybackup.user.NAME.mail.sender.host=sendermail_host 126 | ## easybackup.user.NAME.mail.sender.port=sendermail_port 127 | ## easybackup.user.NAME.mail.sender.ssl=sendermail_ssh 128 | ## easybackup.user.NAME.mail.sender.title=sendermail_title 129 | ## easybackup.user.NAME.mail.sender.template=mail.tpl 130 | ## easybackup.user.NAME.mail.deleteBackup=ON | OFF 131 | ## easybackup.user.NAME.senders=package.userSenderClass;package.userSenderClass2 132 | 133 | # Example: 134 | #easybackup.user.MySQL=mysqldump -uroot -proot demoDB 135 | #easybackup.user.MySQL.targetFileClass=cn.easyproject.easybackup.mysql.MySQLTargetFile 136 | #easybackup.user.MySQL.dir=D:/backup/;E:/backupdb 137 | # default targetFileName is 'demoDB-yyyyMMddHHmmssS.sql' 138 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 139 | #easybackup.user.MySQL.file= demodb-${backuptime?string("yyyyMMddHHmmss")}-backup.sql 140 | #easybackup.user.MySQL.compress=ON 141 | #easybackup.user.MySQL.compressType=ZIP 142 | #easybackup.user.MySQL.cronexpression=0 0 2 * * ? 143 | #easybackup.user.MySQL.mail.receiver=mail@domain.com -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/readme.md: -------------------------------------------------------------------------------- 1 | # EasyBackup Engine Framework 2 | 3 | 4 | 5 | ## 中文 6 | 7 | EasyBackup 同时是一个免费开源跨平台的 Java 内容备份引擎框架(**EasyBackup Engine Framework**),提供统一规范的备份配置和核心调度。 8 | 9 | ### 使用步骤 10 | 11 | 1. Maven dependency 12 | 13 | ```XML 14 | 15 | cn.easyproject 16 | easybackup 17 | 3.3.2-RELEASE 18 | 19 | ``` 20 | 21 | 2. 自定义接口实现 22 | 23 | 3. 配置 `easybackup.properties` 24 | 25 | 4. 启动 26 | ```JAVA 27 | public static void main(String[] args) { 28 | new EasyBackup().start(); 29 | } 30 | ``` 31 | 32 | ### 自定义接口 33 | 34 | EasyBackup 提供了极大的灵活性,扩展以下接口,即可自定义您的备份内容: 35 | 36 | - **TargetFile 目标文件来源**(`cn.easyproject.easybackup.backup.file.TargetFile`) 37 | 38 | **返回值**: 自定义的 `java.io.File` 目标文件对象 39 | 40 | **配置**: `easybackup.user.NAME.targetFileClass` 41 | 42 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultTargtFile` 43 | 44 | - **BackupDir 备份文件目录**(`cn.easyproject.easybackup.backup.file.BackupDir`) 45 | 46 | **返回值**: 自定义的 `java.io.File` 备份目录对象 47 | 48 | **配置**: `easybackup.user.NAME.dirClass` 49 | 50 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupDir` 51 | 52 | - **BackupFile 备份文件名称**(`cn.easyproject.easybackup.backup.file.BackupFile`) 53 | 54 | **返回值**: 自定义的 `String` 备份文件名 55 | 56 | **配置**: `easybackup.user.NAME.fileClass` 57 | 58 | **参数默认值**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupFile` 59 | 60 | - **Backup 备份实现**(`cn.easyproject.easybackup.backup.impls.Backup`) 61 | 62 | **返回值**: 根据传入备份文件信息,自定义备份处理实现,返回是否备份成功 63 | 64 | **配置**: `easybackup.user.NAME.backupClass` 65 | 66 | **参数默认值**: `cn.easyproject.easybackup.backup.impls.FileBackup` 67 | 68 | - **BackupBefore 前置拦截器**(`cn.easyproject.easybackup.backup.interceptor.BackupBefore`) 69 | 70 | **返回值**: 返回是否继续备份 71 | 72 | **配置**: `easybackup.user.NAME.beforeClass` 73 | 74 | **参数默认值**: 75 | 76 | - **BackupAfter 后置拦截器**(`cn.easyproject.easybackup.backup.interceptor.BackupAfter`) 77 | 78 | **返回值**: 79 | 80 | **配置**: `easybackup.user.NAME.afterClass` 81 | 82 | **参数默认值**: 83 | 84 | - **Sender 发送器**(`cn.easyproject.easybackup.sender.Sender`) 85 | 86 | **返回值**: 87 | 88 | **配置**: `easybackup.[file|user].NAME.senders` 89 | 90 | **参数默认值**: 91 | 92 | ### 自定义配置文件和 freemarker 配置对象 93 | 为了提供更多灵活性,EasyBackup 允许在启动备份服务前自定义**配置文件对象 Properties File**(`easybackup.properties`) 和邮件发送时的 **freemarker 配置对象**(`Configuration`)。 94 | 95 | ```JAVA 96 | // 自定义配置文件对象 97 | EasyBackup.setPropertiesFile(java.io.File propertiesFile); 98 | 99 | // 自定义邮件发送的 freemarker 配置对象 100 | MailSender.setFreemarkerConfiguration(freemarker.template.Configuration configuration); 101 | ``` 102 | 103 | 示例: 104 | 105 | ```JAVA 106 | // Custom EasyBackup initialization Parameter 107 | 108 | // 自定义配置文件对象 109 | Resource res = new ServletContextResource(sce.getServletContext(), "/easybackup.properties"); 110 | try { 111 | // Properties File 112 | EasyBackup.setPropertiesFile(res.getFile()); 113 | } catch (IOException e) { 114 | e.printStackTrace(); 115 | } 116 | 117 | // 自定义邮件发送的 freemarker 配置对象 118 | Configuration cfg= new Configuration(Configuration.VERSION_2_3_23); 119 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 120 | cfg.setDefaultEncoding("UTF-8"); 121 | cfg.setServletContextForTemplateLoading(sce.getServletContext(), "/template"); 122 | // MailSender Configuration 123 | MailSender.setFreemarkerConfiguration(cfg); 124 | ``` 125 | 126 | ### 运行时信息获取 127 | 128 | `cn.easyproject.easybackupBackupRuntime` 提供了备份运行时的信息。 129 | 130 | ``` 131 | # 备份控制 132 | start():启动 133 | stop():停止 134 | 135 | # 启动后的运行状态信息 136 | started: 是否启动 137 | allBackupsOnStartup:所有配置的服务 138 | errorJobBackupsOnStartup:任务启动失败的服务 139 | runningBackupsOnStartup:正在运行的服务 140 | 141 | # 配置信息 142 | getBackupNames():所有配置的服务名称 143 | getBackupsConfigurations():所有备份服务配置对象 144 | getEnableBackupsConfigurations():所有设为启用(enable=ON)的备份服务配置对象 145 | getGlobalBackupsConfiguration():全局备份配置对象 146 | getProperties():Properties对象 147 | getPropertiesFile():Properties File 对象 148 | ``` 149 | 150 | 151 | 152 | ## English 153 | 154 | EasyBackup is also a free open source cross-platform Java content backup engine frame (**EasyBackup Engine Framework**), to provide a unified and standard core configuration and backup scheduling. 155 | 156 | ### Steps for usage 157 | 158 | 1. Maven dependency 159 | 160 | ```XML 161 | 162 | cn.easyproject 163 | easybackup 164 | 3.3.2-RELEASE 165 | 166 | ``` 167 | 168 | 2. Custom interface 169 | 170 | 3. Configuration `easybackup.properties` 171 | 172 | 4. Start 173 | ```JAVA 174 | public static void main(String[] args) { 175 | new EasyBackup().start(); 176 | } 177 | ``` 178 | 179 | ### Custom Interface 180 | 181 | EasyBackup provides great flexibility, expandability following interfaces, you can customize your backup content: 182 | 183 | - **TargetFile target file source**(`cn.easyproject.easybackup.backup.file.TargetFile`) 184 | 185 | **return**: custom `java.io.File` target file 186 | 187 | **configuration**: `easybackup.user.NAME.targetFileClass` 188 | 189 | **default**: `cn.easyproject.easybackup.backup.file.impl.DefaultTargtFile` 190 | 191 | - **BackupDir backup directory**(`cn.easyproject.easybackup.backup.file.BackupDir`) 192 | 193 | **return**: custom `java.io.File` storage backup file directory 194 | 195 | **configuration**: `easybackup.user.NAME.dirClass` 196 | 197 | **default**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupDir` 198 | 199 | - **BackupFile backup file name**(`cn.easyproject.easybackup.backup.file.BackupFile`) 200 | 201 | **return**: custom `String` backup file name 202 | 203 | **configuration**: `easybackup.user.NAME.fileClass` 204 | 205 | **default**: `cn.easyproject.easybackup.backup.file.impl.DefaultBackupFile` 206 | 207 | - **Backup backup implement**(`cn.easyproject.easybackup.backup.impls.Backup`) 208 | 209 | **return**: According to information passed back up files, custom backup processing implementation, returns whether the backup was successful 210 | 211 | **configuration**: `easybackup.user.NAME.backupClass` 212 | 213 | **default**: `cn.easyproject.easybackup.backup.impls.FileBackup` 214 | 215 | - **BackupBefore before interceptor**(`cn.easyproject.easybackup.backup.interceptor.BackupBefore`) 216 | 217 | **return**: Returns whether to continue the backup 218 | 219 | **configuration**: `easybackup.user.NAME.beforeClass` 220 | 221 | **default**: 222 | 223 | - **BackupAfter after interceptor**(`cn.easyproject.easybackup.backup.interceptor.BackupAfter`) 224 | 225 | **return**: 226 | 227 | **configuration**: `easybackup.user.NAME.afterClass` 228 | 229 | **default**: 230 | 231 | - **Sender**(`cn.easyproject.easybackup.sender.Sender`) 232 | 233 | **return**: 234 | 235 | **configuration**: `easybackup.[file|user].NAME.senders` 236 | 237 | **default**: 238 | 239 | 240 | ### Custom Properties File and Freemarker Configuration object 241 | To provide more flexibility, EasyBackup permit before starting backup service ** custom Properties File object** ( `easybackup.properties`) and ** mail to send Freemarker Configuration object** (` Configuration`). 242 | 243 | 244 | ```JAVA 245 | // Custom Properties File 246 | EasyBackup.setPropertiesFile(java.io.File propertiesFile); 247 | 248 | // Custom mail to send Freemarker Configuration object 249 | MailSender.setFreemarkerConfiguration(freemarker.template.Configuration configuration); 250 | ``` 251 | 252 | Example: 253 | 254 | ```JAVA 255 | // Custom EasyBackup initialization Parameter 256 | 257 | // Custom Properties File 258 | Resource res = new ServletContextResource(sce.getServletContext(), "/easybackup.properties"); 259 | try { 260 | // Properties File 261 | EasyBackup.setPropertiesFile(res.getFile()); 262 | } catch (IOException e) { 263 | e.printStackTrace(); 264 | } 265 | 266 | // Custom mail to send Freemarker Configuration object 267 | Configuration cfg= new Configuration(Configuration.VERSION_2_3_23); 268 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 269 | cfg.setDefaultEncoding("UTF-8"); 270 | cfg.setServletContextForTemplateLoading(sce.getServletContext(), "/template"); 271 | // MailSender Configuration 272 | MailSender.setFreemarkerConfiguration(cfg); 273 | ``` 274 | 275 | ### Runtime access to information 276 | 277 | `cn.easyproject.easybackupBackupRuntime` providing information backup runtime. 278 | 279 | ``` 280 | # Backup controller 281 | start() 282 | stop() 283 | 284 | # Information when started 285 | started: Weather started 286 | allBackupsOnStartup 287 | runningBackupsOnStartup 288 | errorJobBackupsOnStartup 289 | 290 | # Configuration information 291 | getBackupNames(): All configuration names 292 | getBackupsConfigurations(): All configuration objects 293 | getEnableBackupsConfigurations():All enable(enable=ON) configuration objects 294 | getGlobalBackupsConfiguration(): Global Configuration object 295 | getProperties(): Properties object 296 | getPropertiesFile(): Properties File object 297 | ``` 298 | 299 | 300 | 301 | ## End 302 | 303 | -------------------------------------------------------------------------------- /libs/easybackup_engine_framework/template/mail.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 |
14 | EasyBackup 15 |
16 | 17 |
18 |

Hello,

19 |

Your backup service is complete.

20 |

21 | Name: ${name} - [${type}] 22 |

23 |

24 | Target: ${value} 25 |

26 |

27 | Backup time: ${backuptime?datetime} 28 |

29 |

30 | Please check your E-mail attachments. 31 |

32 |
33 |
34 | EasyMonitor by easyproject.cn 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /projects/easybackup-mysql/easybackup.properties: -------------------------------------------------------------------------------- 1 | ######################## Global Config(Optional) 2 | 3 | # Backup ON or OFF, default is ON 4 | easybackup.enable=ON 5 | 6 | # Backup trigger Cron-Expressions 7 | easybackup.cronexpression=0 30 * * * ? 8 | 9 | # Directory to store the backup file 10 | #easybackup.dir=/user/backup/ 11 | 12 | # backup file name under 'easybackup.backup.dir' directory 13 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 14 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmss")}, ${backupConfiguration.XXX} 15 | #easybackup.file= 16 | 17 | # Whether backup compression, default is ON 18 | easybackup.compress=ON 19 | 20 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 21 | easybackup.compressType=ZIP 22 | 23 | # Comprssion encoding 24 | easybackup.compressEncoding= 25 | 26 | # Whether delete targetFile after backup complete, default is OFF 27 | easybackup.deleteTargetFile=OFF 28 | 29 | # Receive backup file mail address 30 | # You can specify more than one, separated by a ; 31 | #easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 32 | 33 | # Send Mail Account Config 34 | # Send Mail Account 35 | easybackup.mail.sender=xxxxx@xxxx.cn 36 | # Send Mail password 37 | easybackup.mail.sender.passowrd=xxxxxxx 38 | # Send Mail SMTP host 39 | easybackup.mail.sender.host=smtp.xxxx.cn 40 | # Send Mail SMTP port; default is 25 41 | easybackup.mail.sender.port=25 42 | # Send Mail Whether use SSL; default is false 43 | easybackup.mail.sender.ssl=false 44 | # Send Mail title 45 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 46 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 47 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 48 | easybackup.mail.sender.template=mail.tpl 49 | 50 | # Auto delete when send email complete ON or OFF, default is OFF 51 | easybackup.mail.deleteBackup=OFF 52 | 53 | # Execute Command when backup before or after 54 | # You can specify more than one, separated by a ; 55 | easybackup.cmd.before= 56 | easybackup.cmd.after= 57 | 58 | # Execute Interceptor when backup before or after 59 | # You can specify more than one, separated by a ; 60 | easybackup.beforeClass= 61 | easybackup.afterClass= 62 | 63 | 64 | ############ User Backup(can override global config) 65 | ## format: 66 | ## easybackup.user.NAME= 67 | ## easybackup.user.NAME.targetFileClass= 68 | ## easybackup.user.NAME.backupClass= 69 | ## easybackup.user.NAME.enable=ON | OFF 70 | ## easybackup.user.NAME.dir=/user/backupdb/ 71 | ## easybackup.user.NAME.dirClass= 72 | ## easybackup.user.NAME.file=data.zip 73 | ## easybackup.user.NAME.fileClass= 74 | ## easybackup.user.NAME.compress=ON | OFF 75 | ## easybackup.user.NAME.compressType=ZIP | GZIP | TAR 76 | ## easybackup.user.NAME.compressEncoding= 77 | ## easybackup.user.NAME.cronexpression=0/10 * * * * ? 78 | ## easybackup.user.NAME.cmd.before=/user/backupBefore.sh 79 | ## easybackup.user.NAME.cmd.after=/user/backcAfter.sh 80 | ## easybackup.user.NAME.beforeClass= 81 | ## easybackup.user.NAME.afterClass= 82 | ## easybackup.user.NAME.mail.receiver=receivermail@domain.com 83 | ## easybackup.user.NAME.mail.sender=sendermail@domain.com 84 | ## easybackup.user.NAME.mail.sender.passowrd=sendermail_password 85 | ## easybackup.user.NAME.mail.sender.host=sendermail_host 86 | ## easybackup.user.NAME.mail.sender.port=sendermail_port 87 | ## easybackup.user.NAME.mail.sender.ssl=sendermail_ssh 88 | ## easybackup.user.NAME.mail.sender.title=sendermail_title 89 | ## easybackup.user.NAME.mail.sender.template=mail.tpl 90 | ## easybackup.user.NAME.mail.deleteBackup=ON | OFF 91 | ## easybackup.user.NAME.senders=userSenderClass;userSenderClass2 92 | 93 | 94 | easybackup.file.LOG=D:/log 95 | easybackup.file.LOG.enable=ON 96 | easybackup.file.LOG.dir=D:/backup/logfile/ 97 | easybackup.file.LOG.cronexpression=0/30 * * * * ? 98 | easybackup.file.LOG.compress=ON 99 | easybackup.file.LOG.compressType=ZIP 100 | 101 | 102 | easybackup.user.MySQL=mysqldump -uroot -proot demodb 103 | # default targetFileName is 'demodb-yyyyMMddHHmmssS.sql' 104 | easybackup.user.MySQL.targetFileClass=cn.easyproject.easybackup.mysql.MySQLTargetFile 105 | easybackup.user.MySQL.dir=D:/backup/;D:/backup/db 106 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmss")}, ${backupConfiguration.XXX} 107 | easybackup.user.MySQL.file= demodb-${backuptime?string("yyyyMMddHHmmssS")}.sql 108 | easybackup.user.MySQL.compress=ON 109 | easybackup.user.MySQL.compressType=ZIP 110 | easybackup.user.MySQL.cronexpression=0/20 * * * * ? 111 | easybackup.user.MySQL.mail.receiver=yyyy@yyyy.com 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /projects/easybackup-mysql/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | 7 | org.sonatype.oss 8 | oss-parent 9 | 9 10 | 11 | 12 | 13 | cn.easyproject 14 | easybackup-mysql-plugin 15 | 3.2.0-RELEASE 16 | jar 17 | 18 | easybackup-mysql-plugin 19 | http://easyproject.cn/easybackup 20 | 21 | The MySQL database plugin for EasyBckup. 22 | A free, open source, cross-platform content backup, content compression, remote sending task scheduling application integration framework and engine based on Java. 23 | 24 | 25 | The Apache Software License, Version 2.0 26 | http://www.apache.org/licenses/LICENSE-2.0.txt 27 | 28 | 29 | 30 | 31 | https://github.com/ushelp/EasyBackup.git 32 | scm:git:ssh://github.com/ushelp/EasyBackup.git 33 | easybackup 34 | 35 | 36 | 37 | Ray Yam 38 | inthinkcolor@gmail.com 39 | http://easyproject.cn 40 | +8 41 | 42 | 43 | 44 | 45 | 46 | UTF-8 47 | 3.2.0-RELEASE 48 | 4.11 49 | 1.7.21 50 | 4.3.1.RELEASE 51 | 1.5.5 52 | 2.3.23 53 | 2.2.3 54 | 1.12 55 | 56 | 57 | 58 | 59 | junit 60 | junit 61 | ${junit.version} 62 | test 63 | 64 | 65 | cn.easyproject 66 | easybackup 67 | ${easybackup.version} 68 | 69 | 70 | org.apache.commons 71 | commons-compress 72 | ${commonsCompress.version} 73 | 74 | 75 | org.springframework 76 | spring-context 77 | ${spring.version} 78 | 79 | 80 | org.springframework 81 | spring-aop 82 | ${spring.version} 83 | 84 | 85 | org.springframework 86 | spring-context-support 87 | ${spring.version} 88 | 89 | 90 | org.springframework 91 | spring-tx 92 | ${spring.version} 93 | 94 | 95 | 96 | org.slf4j 97 | slf4j-log4j12 98 | ${slf4jLog4j.version} 99 | 100 | 101 | 102 | com.sun.mail 103 | javax.mail 104 | ${javamail.version} 105 | 106 | 107 | org.freemarker 108 | freemarker 109 | ${freemarker.version} 110 | 111 | 112 | 113 | org.quartz-scheduler 114 | quartz 115 | ${quartz.version} 116 | 117 | 118 | 119 | org.quartz-scheduler 120 | quartz-jobs 121 | ${quartz.version} 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | release 133 | 134 | 135 | 136 | 137 | org.apache.maven.plugins 138 | maven-source-plugin 139 | 2.2.1 140 | 141 | 142 | package 143 | 144 | jar-no-fork 145 | 146 | 147 | 148 | 149 | 150 | 151 | org.apache.maven.plugins 152 | maven-javadoc-plugin 153 | 2.9.1 154 | 155 | UTF-8 156 | UTF-8 157 | UTF-8 158 | 159 | 160 | 161 | package 162 | 163 | jar 164 | 165 | 166 | 167 | 168 | 169 | 170 | org.apache.maven.plugins 171 | maven-gpg-plugin 172 | 1.5 173 | 174 | 175 | verify 176 | 177 | sign 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | maven-compiler-plugin 192 | 193 | 1.5 194 | 1.5 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /projects/easybackup-mysql/src/main/java/cn/easyproject/easybackup/mysql/MySQLTargetFile.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.mysql; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.BufferedWriter; 5 | import java.io.File; 6 | import java.io.FileWriter; 7 | import java.io.InputStreamReader; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import cn.easyproject.easybackup.backup.file.TargetFile; 12 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 13 | 14 | /** 15 | * MySQL database backup TargetFile 16 | * The plugin for EasyBakcup 17 | * 18 | * @author easyproject.cn 19 | * 20 | * @since 1.0.0 21 | */ 22 | public class MySQLTargetFile implements TargetFile { 23 | 24 | private static Logger logger = LoggerFactory.getLogger(MySQLTargetFile.class); 25 | 26 | public File getFile(BackupConfiguration configuration) { 27 | try { 28 | // 备份完成删除 SQL 源文件 29 | configuration.setDeleteTargetFile(true); 30 | // 导出文件 31 | String mysqldump=configuration.getValue(); 32 | int fileStartIndex=mysqldump.indexOf(" ", mysqldump.indexOf("-p")+2); 33 | // SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmssS"); 34 | // String sqlFileName=mysqldump.substring(fileStartIndex+1).trim().replace(" ", "_")+"-"+sdf.format(new Date())+".sql"; 35 | String sqlFileName=mysqldump.substring(fileStartIndex+1).trim().replace(" ", "_")+".sql"; 36 | 37 | File backDir=new File(configuration.getDir()[0]); 38 | 39 | if(!backDir.exists()){ 40 | backDir.mkdirs(); 41 | } 42 | 43 | File sqlTargetFile=new File(backDir,sqlFileName); //SQL文件 44 | 45 | BufferedReader br=null; 46 | BufferedWriter bw=null; 47 | try{ 48 | 49 | /* * 直接备份,执行过程为异步,java代码继续执行 50 | * Runtime.getRuntime().exec("cmd /c mysqldump -uroot -proot dbname>e:/bak/db_bak.sql"); 51 | * 52 | 53 | *同步备份代码 */ 54 | 55 | Process process=Runtime.getRuntime().exec(configuration.getValue()); //执行备份脚本 56 | br=new BufferedReader(new InputStreamReader(process.getInputStream())); 57 | bw=new BufferedWriter(new FileWriter(sqlTargetFile)); 58 | String s=null; 59 | 60 | while((s=br.readLine())!=null){ 61 | bw.write(s); 62 | bw.newLine(); 63 | } 64 | 65 | }catch(Exception e){ 66 | logger.error("Backup MySQL database error," 67 | + "please check your backup command: ["+configuration.getValue()+"]",e); 68 | }finally{ 69 | if(br!=null){ 70 | try { 71 | br.close(); 72 | } catch (Exception e2) { 73 | logger.error("BufferedReader close exception. ["+configuration.getValue()+"]",e2); 74 | } 75 | } 76 | if(bw!=null){ 77 | try { 78 | bw.flush(); 79 | } catch (Exception e2) { 80 | logger.error("BufferedWriter flush exception. ["+configuration.getValue()+"]",e2); 81 | } 82 | } 83 | if(bw!=null){ 84 | try { 85 | bw.close(); 86 | } catch (Exception e2) { 87 | logger.error("BufferedWriter close exception. ["+configuration.getValue()+"]",e2); 88 | } 89 | } 90 | } 91 | 92 | return sqlTargetFile; 93 | } catch (Exception e) { 94 | logger.error("Backup MySQL database error, " 95 | + "["+configuration.getValue()+"]",e); 96 | 97 | } 98 | return null; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /projects/easybackup-mysql/template/mail.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 |
14 | EasyBackup 15 |
16 | 17 |
18 |

Hello,

19 |

Your backup service is complete.

20 |

21 | Name: ${name} - [${type}] 22 |

23 |

24 | Target: ${value} 25 |

26 |

27 | Backup time: ${backuptime?datetime} 28 |

29 |

30 | Please check your E-mail attachments. 31 |

32 |
33 |
34 | EasyMonitor by easyproject.cn 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /projects/easybackup/easybackup.properties: -------------------------------------------------------------------------------- 1 | ######################## Global Config(Optional) 2 | 3 | # Backup ON or OFF, default is ON 4 | easybackup.enable=ON 5 | 6 | # Backup trigger Cron-Expressions 7 | easybackup.cronexpression=0 30 * * * ? 8 | 9 | # Directory to store the backup file 10 | # You can specify more than one, separated by a ; 11 | easybackup.dir=/user/backup/ 12 | # backup file name under 'easybackup.backup.dir' directory 13 | # If not specified, the automatically generated file name is 'targetFileName-yyyyMMddHHmmssS[.zip|tar|tar.gz]' 14 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 15 | easybackup.file= 16 | 17 | # Whether backup compression, default is OFF 18 | easybackup.compress=OFF 19 | # Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 20 | easybackup.compressType=ZIP 21 | # Comprssion encoding 22 | easybackup.compressEncoding= 23 | 24 | # Whether delete targetFile after backup complete, default is OFF 25 | easybackup.deleteTargetFile=OFF 26 | 27 | # Receive Backup file mail address 28 | # You can specify more than one, separated by a ; 29 | easybackup.mail.receiver=yourmail@domain.com;youmail2@domai2.org 30 | 31 | # Send Mail Account Config 32 | # Send Mail Account 33 | easybackup.mail.sender=sendermail@domain.com 34 | # Send Mail password 35 | easybackup.mail.sender.passowrd=mailpassword 36 | # Send Mail SMTP host 37 | easybackup.mail.sender.host=smtp.163.com 38 | # Send Mail SMTP port; default is 25 39 | easybackup.mail.sender.port=25 40 | # Send Mail Whether use SSL; default is false 41 | easybackup.mail.sender.ssl=false 42 | # Send Mail title 43 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?datetime}, ${backupConfiguration.XXX} 44 | easybackup.mail.sender.title=Backup ${targetFileName}- EasyBackup 45 | # The send mail content freemarker template in template directory, default is 'mail.tpl' 46 | easybackup.mail.sender.template=mail.tpl 47 | 48 | # Auto delete when send email complete ON or OFF, default is OFF 49 | easybackup.mail.deleteBackup=OFF 50 | 51 | # Execute Command when backup before or after 52 | # You can specify more than one, separated by a ; 53 | easybackup.cmd.before= 54 | easybackup.cmd.after= 55 | 56 | # Execute Interceptor when backup before or after 57 | # You can specify more than one, separated by a ; 58 | easybackup.beforeClass= 59 | easybackup.afterClass= 60 | 61 | 62 | ######################## Backup Service Configuration 63 | 64 | ############ File Backup(can override global config) 65 | ## format: 66 | ## easybackup.file.NAME=value 67 | ## easybackup.file.NAME.enable=ON | OFF 68 | ## easybackup.file.NAME.cronexpression=0/10 * * * * ? 69 | ## easybackup.file.NAME.dir=/user/backup/;/user/backup2 70 | ## easybackup.file.NAME.file= 71 | ## easybackup.file.NAME.compress=ON | OFF 72 | ## easybackup.file.NAME.compressType=ZIP | GZIP | TAR 73 | ## easybackup.file.NAME.compressEncoding= 74 | ## easybackup.file.NAME.deleteTargetFile=ON | OFF 75 | ## easybackup.file.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 76 | ## easybackup.file.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 77 | ## easybackup.file.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 78 | ## easybackup.file.NAME.afterClass=package.BackupAfter;package.BackupAfter2 79 | ## easybackup.file.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 80 | ## easybackup.file.NAME.mail.sender=sendermail@domain.com 81 | ## easybackup.file.NAME.mail.sender.passowrd=sendermail_password 82 | ## easybackup.file.NAME.mail.sender.host=sendermail_host 83 | ## easybackup.file.NAME.mail.sender.port=sendermail_port 84 | ## easybackup.file.NAME.mail.sender.ssl=sendermail_ssh 85 | ## easybackup.file.NAME.mail.sender.title=sendermail_title 86 | ## easybackup.file.NAME.mail.sender.template=mail.tpl 87 | ## easybackup.file.NAME.mail.deleteBackup=ON | OFF 88 | ## easybackup.file.NAME.senders=package.userSenderClass;package.userSenderClass2 89 | 90 | 91 | 92 | # Example: 93 | #easybackup.file.LOG=D:/log 94 | #easybackup.file.LOG.enable=ON 95 | #easybackup.file.LOG.dir=D:/backup/logfile/;E:/backup/logfile 96 | #easybackup.file.LOG.cronexpression=0 30 * * * ? 97 | #easybackup.file.LOG.compress=ON 98 | #easybackup.file.LOG.compressType=ZIP 99 | #easybackup.file.LOG.mail.receiver=mail@domain.com 100 | 101 | 102 | ############ Port Monitor(can override global config) 103 | ## format: 104 | ## easybackup.user.NAME=value 105 | ## easybackup.user.NAME.enable=ON | OFF 106 | ## easybackup.user.NAME.cronexpression=0/10 * * * * ? 107 | ## easybackup.user.NAME.dir=/user/backup/;/user/backup2 108 | ## easybackup.user.NAME.file= 109 | ## easybackup.user.NAME.compress=ON | OFF 110 | ## easybackup.user.NAME.compressType=ZIP | GZIP | TAR 111 | ## easybackup.user.NAME.compressEncoding= 112 | ## easybackup.user.NAME.deleteTargetFile=ON | OFF 113 | ## easybackup.user.NAME.targetFileClass=package.YourTargetFile 114 | ## easybackup.user.NAME.dirClass=package.YourBackupDir 115 | ## easybackup.user.NAME.fileClass=package.YourBackupFile 116 | ## easybackup.user.NAME.backupClass=package.YourBackup 117 | ## easybackup.user.NAME.cmd.before=/user/backupBefore.sh;/user/backupBefore2.sh 118 | ## easybackup.user.NAME.cmd.after=/user/backcAfter.sh;/user/backcAfter2.sh 119 | ## easybackup.user.NAME.beforeClass=package.BackupBefore;package.BackupBefore2 120 | ## easybackup.user.NAME.afterClass=package.BackupAfter;package.BackupAfter2 121 | ## easybackup.user.NAME.mail.receiver=receivermail@domain.com;receivermail1@domain.com 122 | ## easybackup.user.NAME.mail.sender=sendermail@domain.com 123 | ## easybackup.user.NAME.mail.sender.passowrd=sendermail_password 124 | ## easybackup.user.NAME.mail.sender.host=sendermail_host 125 | ## easybackup.user.NAME.mail.sender.port=sendermail_port 126 | ## easybackup.user.NAME.mail.sender.ssl=sendermail_ssh 127 | ## easybackup.user.NAME.mail.sender.title=sendermail_title 128 | ## easybackup.user.NAME.mail.sender.template=mail.tpl 129 | ## easybackup.user.NAME.mail.deleteBackup=ON | OFF 130 | ## easybackup.user.NAME.senders=package.userSenderClass;package.userSenderClass2 131 | 132 | # Example: 133 | #easybackup.user.MySQL=mysqldump -uroot -proot demoDB 134 | #easybackup.user.MySQL.targetFileClass=cn.easyproject.easybackup.mysql.MySQLTargetFile 135 | #easybackup.user.MySQL.dir=D:/backup/;E:/backupdb 136 | # default targetFileName is 'demoDB-yyyyMMddHHmmssS.sql' 137 | # you can use variable: ${targetFileName}, ${name}, ${type}, ${value}, ${backuptime?string("yyyyMMddHHmmssS")}, ${backupConfiguration.XXX} 138 | #easybackup.user.MySQL.file= demodb-${backuptime?string("yyyyMMddHHmmss")}-backup.sql 139 | #easybackup.user.MySQL.compress=ON 140 | #easybackup.user.MySQL.compressType=ZIP 141 | #easybackup.user.MySQL.cronexpression=0 0 2 * * ? 142 | #easybackup.user.MySQL.mail.receiver=mail@domain.com -------------------------------------------------------------------------------- /projects/easybackup/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | 7 | 8 | org.sonatype.oss 9 | oss-parent 10 | 9 11 | 12 | 13 | 14 | cn.easyproject 15 | 16 | easybackup 17 | 3.3.2-RELEASE 18 | jar 19 | 20 | easybackup 21 | http://easyproject.cn/easybackup 22 | 23 | 24 | 27 | 28 | 29 | 30 | The Apache Software License, Version 2.0 31 | http://www.apache.org/licenses/LICENSE-2.0.txt 32 | 33 | 34 | 35 | 36 | https://github.com/ushelp/EasyBackup.git 37 | scm:git:ssh://github.com/ushelp/EasyBackup.git 38 | easybackup 39 | 40 | 41 | 42 | Ray Yam 43 | inthinkcolor@gmail.com 44 | http://easyproject.cn 45 | +8 46 | 47 | 48 | 49 | 50 | 51 | UTF-8 52 | 1.12 53 | 54 | 4.11 55 | 1.7.21 56 | 4.3.1.RELEASE 57 | 1.5.5 58 | 2.3.23 59 | 2.2.3 60 | 61 | 62 | 63 | 64 | junit 65 | junit 66 | ${junit.version} 67 | test 68 | 69 | 70 | org.apache.commons 71 | commons-compress 72 | ${commonsCompress.version} 73 | 74 | 79 | 80 | org.springframework 81 | spring-context 82 | ${spring.version} 83 | 84 | 85 | org.springframework 86 | spring-aop 87 | ${spring.version} 88 | 89 | 90 | org.springframework 91 | spring-context-support 92 | ${spring.version} 93 | 94 | 95 | org.springframework 96 | spring-tx 97 | ${spring.version} 98 | 99 | 100 | 101 | org.slf4j 102 | slf4j-log4j12 103 | ${slf4jLog4j.version} 104 | 105 | 106 | 107 | com.sun.mail 108 | javax.mail 109 | ${javamail.version} 110 | 111 | 112 | org.freemarker 113 | freemarker 114 | ${freemarker.version} 115 | 116 | 117 | 118 | org.quartz-scheduler 119 | quartz 120 | ${quartz.version} 121 | 122 | 123 | 124 | org.quartz-scheduler 125 | quartz-jobs 126 | ${quartz.version} 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | release 138 | 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-source-plugin 144 | 2.2.1 145 | 146 | 147 | package 148 | 149 | jar-no-fork 150 | 151 | 152 | 153 | 154 | 155 | 156 | org.apache.maven.plugins 157 | maven-javadoc-plugin 158 | 2.9.1 159 | 160 | UTF-8 161 | UTF-8 162 | UTF-8 163 | 164 | 165 | 166 | package 167 | 168 | jar 169 | 170 | 171 | 172 | 173 | 174 | 175 | org.apache.maven.plugins 176 | maven-gpg-plugin 177 | 1.5 178 | 179 | 180 | verify 181 | 182 | sign 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | maven-compiler-plugin 197 | 198 | 1.5 199 | 1.5 200 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/BackupType.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup; 2 | 3 | /** 4 | * Backup Type enum 5 | * @author easyproject.cn 6 | * 7 | * @since 1.0.0 8 | */ 9 | public enum BackupType { 10 | /** 11 | * File backup 12 | */ 13 | FILE, 14 | /** 15 | * User define backup 16 | */ 17 | USER; 18 | } 19 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/EasyBackup.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.util.Properties; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.core.io.Resource; 11 | import org.springframework.core.io.ResourceLoader; 12 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 13 | 14 | import cn.easyproject.easybackup.backup.BackupEngine; 15 | import cn.easyproject.easybackup.backup.StdBackupEngine; 16 | import cn.easyproject.easybackup.job.ReloadConfigurationJob; 17 | 18 | /** 19 | * EasyBackup Run enter 20 | * 21 | * @author easyproject.cn 22 | * 23 | * @since 1.0.0 24 | */ 25 | public class EasyBackup { 26 | 27 | static Logger logger = LoggerFactory.getLogger(EasyBackup.class); 28 | 29 | /* 30 | * Properties information 31 | */ 32 | private static Properties properties=null; 33 | private static File propertiesFile; 34 | 35 | private static File userPropertiesFile; 36 | 37 | 38 | /** 39 | * 启动 EasyBackup 40 | */ 41 | public void start() { 42 | if (!BackupRuntime.started) { 43 | 44 | loadProperties(); // 加载初始化配置 45 | 46 | if(propertiesFile!=null){ 47 | BackupEngine stdBackup = new StdBackupEngine(); 48 | stdBackup.start(); 49 | } 50 | 51 | }else{ 52 | logger.info("EasyBackup is already started!"); 53 | } 54 | } 55 | 56 | /** 57 | * 默认配置文件 58 | */ 59 | private void loadProperties() { 60 | // 使用用户自定义 properties 配置文件 61 | if(EasyBackup.userPropertiesFile!=null){ 62 | // 使用用户自定义 properties 配置文件 63 | try { 64 | EasyBackup.properties = new Properties(); 65 | EasyBackup.properties.load(new FileInputStream(userPropertiesFile)); 66 | EasyBackup.propertiesFile=userPropertiesFile; 67 | ReloadConfigurationJob.propertiesLastModify = propertiesFile.lastModified(); 68 | } catch (IOException e) { 69 | logger.error("Read file:easybackup.properties error.", e); 70 | } 71 | return; 72 | } 73 | 74 | // 搜索默认配置文件(运行相对目录;classpath) 75 | ResourceLoader rl = new PathMatchingResourcePatternResolver(); 76 | Resource res = rl.getResource("file:easybackup.properties"); 77 | Resource res2 = rl.getResource("classpath:easybackup.properties"); 78 | 79 | if((!res.exists()) && (!res2.exists())){ 80 | logger.error("easybackup.properties not found."); 81 | return; 82 | }else{ 83 | boolean loadProperties=false; 84 | if (res.exists()) { 85 | try { 86 | EasyBackup.properties = new Properties(); 87 | EasyBackup.properties.load(res.getInputStream()); 88 | EasyBackup.propertiesFile=res.getFile(); 89 | ReloadConfigurationJob.propertiesLastModify = propertiesFile.lastModified(); 90 | loadProperties=true; 91 | } catch (IOException e) { 92 | logger.error("Read file:easybackup.properties error.", e); 93 | } 94 | } 95 | 96 | if(!loadProperties){ 97 | try { 98 | EasyBackup.properties = new Properties(); 99 | EasyBackup.properties.load(res2.getInputStream()); 100 | EasyBackup.propertiesFile=res2.getFile(); 101 | ReloadConfigurationJob.propertiesLastModify = propertiesFile.lastModified(); 102 | } catch (IOException e) { 103 | logger.error("Read classpath:easybackup.properties error.", e); 104 | } 105 | } 106 | 107 | } 108 | } 109 | 110 | 111 | 112 | 113 | /** 114 | * Set your properties file 115 | * @param userPropertiesFile easybackup.properties File 116 | */ 117 | public static void setPropertiesFile(File userPropertiesFile) { 118 | EasyBackup.userPropertiesFile = userPropertiesFile; 119 | } 120 | 121 | public static File getPropertiesFile() { 122 | return userPropertiesFile!=null?userPropertiesFile:propertiesFile; 123 | } 124 | 125 | 126 | 127 | public static Properties getProperties() { 128 | return properties; 129 | } 130 | 131 | // public static void setProperties(Properties properties) { 132 | // EasyBackup.properties = properties; 133 | // } 134 | 135 | 136 | 137 | public static void main(String[] args) { 138 | new EasyBackup().start(); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/BackupEngine.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup; 2 | 3 | /** 4 | * EasyBackup BackupEngine 5 | * @author easyproject.cn 6 | * 7 | * @since 1.0.0 8 | */ 9 | public interface BackupEngine { 10 | public void start(); 11 | } 12 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/StdBackupEngine.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Enumeration; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Properties; 8 | import java.util.Set; 9 | 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import cn.easyproject.easybackup.BackupRuntime; 14 | import cn.easyproject.easybackup.BackupType; 15 | import cn.easyproject.easybackup.EasyBackup; 16 | import cn.easyproject.easybackup.backup.file.BackupDir; 17 | import cn.easyproject.easybackup.backup.file.BackupFile; 18 | import cn.easyproject.easybackup.backup.file.TargetFile; 19 | import cn.easyproject.easybackup.backup.file.impl.DefaultBackupDir; 20 | import cn.easyproject.easybackup.backup.file.impl.DefaultBackupFile; 21 | import cn.easyproject.easybackup.backup.file.impl.DefaultTargtFile; 22 | import cn.easyproject.easybackup.backup.impls.Backup; 23 | import cn.easyproject.easybackup.backup.impls.FileBackup; 24 | import cn.easyproject.easybackup.backup.interceptor.BackupAfter; 25 | import cn.easyproject.easybackup.backup.interceptor.BackupBefore; 26 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 27 | import cn.easyproject.easybackup.configuration.GlobalConfiguration; 28 | import cn.easyproject.easybackup.job.JobManager; 29 | import cn.easyproject.easybackup.sender.Sender; 30 | import cn.easyproject.easybackup.sender.mail.MailSender; 31 | import cn.easyproject.easybackup.util.EasyUtil; 32 | import cn.easyproject.easybackup.util.SpringUtil; 33 | 34 | /** 35 | * EasyBackup standard implements for BackupEngine 36 | * @author easyproject.cn 37 | * 38 | * @since 1.0.0 39 | */ 40 | public class StdBackupEngine implements BackupEngine { 41 | static Logger logger=LoggerFactory.getLogger(StdBackupEngine.class); 42 | 43 | /** 44 | * 全局 EasyMonitor 配置 45 | */ 46 | private static GlobalConfiguration globalConfig; 47 | /** 48 | * 监控 Monitor 配置 49 | */ 50 | private static List backups; 51 | 52 | public static String getCompressType(String type){ 53 | type=type.trim().toUpperCase(); 54 | if(type.equals("ZIP")|| 55 | type.equals("TAR")|| 56 | type.equals("GZIP")){ 57 | return type; 58 | } 59 | return "ZIP"; 60 | } 61 | 62 | 63 | /** 64 | * 初始化配置数据 65 | */ 66 | @SuppressWarnings("rawtypes") 67 | public void initConfig(){ 68 | globalConfig=new GlobalConfiguration(); 69 | backups=new ArrayList(); 70 | 71 | Properties p=EasyBackup.getProperties(); 72 | 73 | /* 74 | * GlobalConfig init 75 | */ 76 | 77 | String globalEnable=p.getProperty("easybackup.enable", "ON"); 78 | String globalDeleteTargetFile=p.getProperty("easybackup.deleteTargetFile", "OFF"); 79 | String globalBackupDir=p.getProperty("easybackup.dir", null); 80 | String globalBackupFile=p.getProperty("easybackup.file", null); 81 | String globalCompress=p.getProperty("easybackup.compress", "OFF"); 82 | String globalCompressType=p.getProperty("easybackup.compressType", "ZIP"); 83 | String globalCompressEncoding=p.getProperty("easybackup.compressEncoding", null); 84 | String globalCronExpression=p.getProperty("easybackup.cronexpression", "0 30 * * * ?"); 85 | 86 | String globalCmdBefore=p.getProperty("easymonitor.cmd.before",null); 87 | String globalCmdAfter=p.getProperty("easymonitor.cmd.after",null); 88 | 89 | String globalBeforeClass=p.getProperty("easymonitor.beforeClass",null); 90 | String globalAfterClass=p.getProperty("easymonitor.afterClass",null); 91 | 92 | String globalMailReceiver=p.getProperty("easybackup.mail.receiver",null); 93 | String globalMailSender=p.getProperty("easybackup.mail.sender",null); 94 | String globalMailSenderPassword=p.getProperty("easybackup.mail.sender.passowrd",null); 95 | String globalMailSenderHost=p.getProperty("easybackup.mail.sender.host",null); 96 | String globalMailSenderSsl=p.getProperty("easybackup.mail.sender.ssl",null); 97 | String globalMailSenderTitle=p.getProperty("easybackup.mail.sender.title",null); 98 | String globalMailSenderTemplate=p.getProperty("easybackup.mail.sender.template",null); 99 | String globalDeleteBackup=p.getProperty("easybackup.mail.deleteBackup", "OFF"); 100 | 101 | Integer globalMailPort=25; 102 | try { 103 | globalMailPort = Integer.valueOf(p.getProperty("easybackup.mail.sender.port", "25")); 104 | } catch (NumberFormatException e) { 105 | logger.warn("'easybackup.mail.sender.port' is not a integer, use default 25."); 106 | } 107 | 108 | 109 | globalConfig.setEnable(EasyUtil.isTrue(globalEnable)); 110 | globalConfig.setCronExpression(globalCronExpression); 111 | globalConfig.setDir(EasyUtil.isNotEmpty(globalBackupDir)?globalBackupDir.split(";"):(globalBackupDir==null?null:new String[] {})); 112 | globalConfig.setFile(globalBackupFile); 113 | globalConfig.setCompress(EasyUtil.isTrue(globalCompress)); 114 | globalConfig.setCompressType(getCompressType(globalCompressType)); 115 | globalConfig.setCompressEncoding(globalCompressEncoding); 116 | globalConfig.setDeleteTargetFile(EasyUtil.isTrue(globalDeleteTargetFile)); 117 | 118 | globalConfig.setCmdBefore(EasyUtil.isNotEmpty(globalCmdBefore)?globalCmdBefore.split(";"):(globalCmdBefore==null?null:new String[] {})); 119 | globalConfig.setCmdAfter(EasyUtil.isNotEmpty(globalCmdAfter)?globalCmdAfter.split(";"):(globalCmdAfter==null?null:new String[] {})); 120 | globalConfig.setBeforeClass(EasyUtil.isNotEmpty(globalBeforeClass)?globalBeforeClass.split(";"):(globalBeforeClass==null?null:new String[] {})); 121 | globalConfig.setAfterClass(EasyUtil.isNotEmpty(globalAfterClass)?globalAfterClass.split(";"):(globalAfterClass==null?null:new String[] {})); 122 | 123 | globalConfig.setMailReceiver(EasyUtil.isNotEmpty(globalMailReceiver)?globalMailReceiver.split(";"):(globalMailReceiver==null?null:new String[] {})); 124 | globalConfig.setMailSender(globalMailSender); 125 | globalConfig.setMailSenderPassword(globalMailSenderPassword); 126 | globalConfig.setMailSenderHost(globalMailSenderHost); 127 | globalConfig.setMailSenderPort(globalMailPort); 128 | globalConfig.setMailSenderSsl(EasyUtil.isTrue(globalMailSenderSsl)); 129 | globalConfig.setMailSenderTitle(globalMailSenderTitle); 130 | globalConfig.setMailSenderTemplate(globalMailSenderTemplate); 131 | 132 | globalConfig.setMailDeleteBackup(EasyUtil.isTrue(globalDeleteBackup)); 133 | 134 | /* 135 | * Get Config Names 136 | */ 137 | Set configNames=new HashSet(); 138 | Enumeration names=p.propertyNames(); 139 | while(names.hasMoreElements()){ 140 | String key = (String) names.nextElement(); 141 | /* 142 | * Judgment Config TYPE 143 | */ 144 | if(key.startsWith("easybackup.file.")){ 145 | key=key.substring("easybackup.file.".length()); 146 | if(key.indexOf(".")==-1){ 147 | configNames.add("FILE:"+key); 148 | } 149 | }else if(key.startsWith("easybackup.user.")){ 150 | key=key.substring("easybackup.user.".length()); 151 | if(key.indexOf(".")==-1){ 152 | configNames.add("USER:"+key); 153 | } 154 | } 155 | } 156 | 157 | logger.debug("configNames: "+ configNames); 158 | 159 | 160 | /* 161 | * Init BackupConfig 162 | */ 163 | for (String name : configNames) { 164 | BackupConfiguration configuration=new BackupConfiguration(); 165 | /* 166 | * Judgment Config TYPE 167 | */ 168 | String startWith="easybackup.url."; 169 | if(name.startsWith("FILE:")){ 170 | startWith="easybackup.file."; 171 | name=name.substring("FILE:".length()); 172 | configuration.setType(BackupType.FILE); 173 | configuration.setBackup(new FileBackup()); 174 | 175 | 176 | }else if(name.startsWith("USER:")){ 177 | startWith="easybackup.user."; 178 | name=name.substring("USER:".length()); 179 | configuration.setType(BackupType.USER); 180 | // configuration.setBackup(new UserBackup()); 181 | } 182 | 183 | 184 | 185 | String value=startWith+name; 186 | String backupClass=startWith+name+".backupClass"; 187 | String enable=startWith+name+".enable"; 188 | String dir=startWith+name+".dir"; 189 | String file=startWith+name+".file"; 190 | String targetFileClass=startWith+name+".targetFileClass"; 191 | String dirClass=startWith+name+".dirClass"; 192 | String fileClass=startWith+name+".fileClass"; 193 | String compress=startWith+name+".compress"; 194 | String compressType=startWith+name+".compressType"; 195 | String compressEncoding=startWith+name+".compressEncoding"; 196 | String cronexpression=startWith+name+".cronexpression"; 197 | String deleteTargetFile=startWith+name+".deleteTargetFile"; 198 | 199 | String cmdBefore=startWith+name+".cmd.before"; 200 | String cmdAfter=startWith+name+".cmd.after"; 201 | String beforeClass=startWith+name+".beforeClass"; 202 | String afterClass=startWith+name+".afterClass"; 203 | 204 | String receiver=startWith+name+".mail.receiver"; 205 | String sender=startWith+name+".mail.sender"; 206 | String senderPassowrd=startWith+name+".mail.sender.passowrd"; 207 | String senderHost=startWith+name+".mail.sender.host"; 208 | String senderPort=startWith+name+".mail.sender.port"; 209 | String senderSsl=startWith+name+".mail.sender.ssl"; 210 | String senderTitle=startWith+name+".mail.sender.title"; 211 | String senderTemplate=startWith+name+".mail.sender.template"; 212 | String deleteBackup=startWith+name+".mail.deleteBackup"; 213 | String senders=startWith+name+".senders"; 214 | 215 | 216 | value=p.getProperty(value,null); 217 | backupClass=p.getProperty(backupClass,null); 218 | enable=p.getProperty(enable,null); 219 | dir=p.getProperty(dir,null); 220 | file=p.getProperty(file,null); 221 | targetFileClass=p.getProperty(targetFileClass,null); 222 | dirClass=p.getProperty(dirClass,null); 223 | fileClass=p.getProperty(fileClass,null); 224 | deleteTargetFile=p.getProperty(deleteTargetFile,null); 225 | 226 | compress=p.getProperty(compress,null); 227 | compressType=p.getProperty(compressType,null); 228 | compressEncoding=p.getProperty(compressEncoding,null); 229 | cronexpression=p.getProperty(cronexpression,null); 230 | 231 | cmdBefore=p.getProperty(cmdBefore,null); 232 | cmdAfter=p.getProperty(cmdAfter,null); 233 | beforeClass=p.getProperty(beforeClass,null); 234 | afterClass=p.getProperty(afterClass,null); 235 | 236 | receiver=p.getProperty(receiver,null); 237 | sender=p.getProperty(sender,null); 238 | senderPassowrd=p.getProperty(senderPassowrd,null); 239 | senderHost=p.getProperty(senderHost,null); 240 | senderPort=p.getProperty(senderPort,null); 241 | senderSsl=p.getProperty(senderSsl,null); 242 | senderTitle=p.getProperty(senderTitle,null); 243 | senderTemplate=p.getProperty(senderTemplate,null); 244 | deleteBackup=p.getProperty(deleteBackup,null); 245 | senders=p.getProperty(senders,null); 246 | 247 | // init 248 | 249 | Integer backupMailPort=globalConfig.getMailSenderPort(); 250 | if(senderPort!=null){ 251 | try { 252 | backupMailPort = Integer.valueOf(senderPort); 253 | } catch (NumberFormatException e) { 254 | logger.warn("'"+startWith+name+".mail.sender.interval' is not a integer, use default "+backupMailPort+".",e); 255 | } 256 | } 257 | if(backupMailPort==null){ 258 | backupMailPort=25; // default is 25 259 | } 260 | 261 | 262 | configuration.setName(name); 263 | configuration.setValue(value); 264 | configuration.setEnable(enable!=null?EasyUtil.isTrue(enable):globalConfig.getEnable()); 265 | configuration.setDeleteTargetFile(deleteTargetFile!=null?EasyUtil.isTrue(deleteTargetFile):globalConfig.isDeleteTargetFile()); 266 | configuration.setDir(dir!=null?dir.split(";"):globalConfig.getDir()); 267 | configuration.setFile(file!=null?file:globalConfig.getFile()); 268 | configuration.setCompress(compress!=null?EasyUtil.isTrue(compress):globalConfig.getCompress()); 269 | configuration.setCompressType(compressType!=null?getCompressType(compressType):globalConfig.getCompressType()); 270 | configuration.setCompressEncoding(compressEncoding!=null?compressEncoding:globalCompressEncoding); 271 | configuration.setCronExpression(cronexpression!=null?cronexpression:globalConfig.getCronExpression());; //cronexpression 272 | 273 | 274 | configuration.setMailReceiver(EasyUtil.isNotEmpty(receiver)?receiver.split(";"):(receiver==null?globalConfig.getMailReceiver():new String[] {})); //mailReceiver 275 | configuration.setMailSender(EasyUtil.isNotEmpty(sender)?sender:(sender==null?globalConfig.getMailSender():"")); //mailSender 276 | configuration.setMailSenderPassword(EasyUtil.isNotEmpty(senderPassowrd)?senderPassowrd:(senderPassowrd==null?globalConfig.getMailSenderPassword():"")); //password 277 | configuration.setMailSenderHost(EasyUtil.isNotEmpty(senderHost)?senderHost:(senderHost==null?globalConfig.getMailSenderHost():"")); //host 278 | configuration.setMailSenderPort(backupMailPort); //mailSender port 279 | configuration.setMailSenderSsl(EasyUtil.isNotEmpty(senderSsl)?EasyUtil.isTrue(senderSsl): (senderSsl==null?globalConfig.getMailSenderSsl():false)); //ssl 280 | configuration.setMailSenderTitle(EasyUtil.isNotEmpty(senderTitle)?senderTitle: (senderTitle==null?globalConfig.getMailSenderTitle():"")); //title 281 | configuration.setMailSenderTemplate(EasyUtil.isNotEmpty(senderTemplate)?senderTemplate: (senderTemplate==null?globalConfig.getMailSenderTemplate():"")); //template 282 | configuration.setMailDeleteBackup(EasyUtil.isNotEmpty(deleteBackup)?EasyUtil.isTrue(deleteBackup): (deleteBackup==null?globalConfig.getMailDeleteBackup():false)); //ssl 283 | 284 | configuration.setCmdBefore(EasyUtil.isNotEmpty(cmdBefore)?cmdBefore.split(";"): (cmdBefore==null?globalConfig.getCmdBefore():new String[] {})); 285 | configuration.setCmdAfter(EasyUtil.isNotEmpty(cmdAfter)?cmdAfter.split(";"):(cmdAfter==null?globalConfig.getCmdAfter():new String[] {})); 286 | configuration.setBeforeClass(EasyUtil.isNotEmpty(beforeClass)?beforeClass.split(";"): (beforeClass==null?globalConfig.getBeforeClass():new String[] {})); 287 | configuration.setAfterClass(EasyUtil.isNotEmpty(afterClass)?afterClass.split(";"): (afterClass==null?globalConfig.getAfterClass():new String[] {})); 288 | 289 | 290 | 291 | 292 | // before&after interceptor 293 | if(configuration.getBeforeClass()!=null&& configuration.getBeforeClass().length>0){ 294 | for (String cls : configuration.getBeforeClass()) { 295 | try { 296 | BackupBefore before=(BackupBefore) Class.forName(cls.trim()).newInstance(); 297 | configuration.getBefore().add(before); 298 | } catch (InstantiationException e) { 299 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 300 | +configuration.getValue() 301 | +"', the beforeClass ["+cls+"] is not implements 'cn.easyproject.easybackup.backup.interceptor.BackupBefore' interface.", 302 | e); 303 | } catch (IllegalAccessException e) { 304 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 305 | +configuration.getValue() 306 | +"', the beforeClass ["+cls+"] is IllegalAccessException.", 307 | e); 308 | } catch (ClassNotFoundException e) { 309 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 310 | +configuration.getValue() 311 | +"', the beforeClass ["+cls+"] is not found.", 312 | e); 313 | } 314 | } 315 | } 316 | 317 | if(configuration.getAfterClass()!=null&& configuration.getAfterClass().length>0){ 318 | for (String cls : configuration.getAfterClass()) { 319 | try { 320 | BackupAfter after=(BackupAfter) Class.forName(cls.trim()).newInstance(); 321 | configuration.getAfter().add(after); 322 | } catch (InstantiationException e) { 323 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 324 | +configuration.getValue() 325 | +"', the afterClass ["+cls+"] is not implements 'cn.easyproject.easybackup.backup.interceptor.BackupAfter' interface.", 326 | e); 327 | } catch (IllegalAccessException e) { 328 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 329 | +configuration.getValue() 330 | +"', the afterClass ["+cls+"] is IllegalAccessException.", 331 | e); 332 | } catch (ClassNotFoundException e) { 333 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 334 | +configuration.getValue() 335 | +"', the afterClass ["+cls+"] is not found.", 336 | e); 337 | } 338 | } 339 | } 340 | 341 | 342 | if(configuration.getType()==BackupType.FILE){ 343 | configuration.setTargetFile(new DefaultTargtFile()); 344 | configuration.setBackupDir(new DefaultBackupDir()); 345 | configuration.setBackupFile(new DefaultBackupFile()); 346 | configuration.setBackup(new FileBackup()); 347 | 348 | // 备份目录不存在,直接删除 349 | if((!EasyUtil.isNotEmpty(configuration.getValue())) ){ 350 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 351 | +configuration.getValue() 352 | +"Backup file value is empty, the backup is cancel.",new RuntimeException("Backup file value is empty!")); 353 | configuration.setTargetFile(null); // value不存在,目标备份设置为空 354 | // continue; 355 | } 356 | }else{ 357 | 358 | // 备份目录不存在,并且直接删除 359 | if((!EasyUtil.isNotEmpty(configuration.getValue())) && (!EasyUtil.isNotEmpty(configuration.getFileClass())) ){ 360 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 361 | +configuration.getValue() 362 | +"Backup file value is empty, the backup is cancel.",new RuntimeException("Backup file value is empty!")); 363 | // continue; 364 | } 365 | 366 | 367 | //USER 368 | // targetFileClass 369 | if(EasyUtil.isNotEmpty(targetFileClass)){ 370 | configuration.setTargetFileClass(targetFileClass); 371 | boolean flag=false; 372 | Exception e2=null; 373 | try { 374 | TargetFile targetFile=(TargetFile) Class.forName(targetFileClass.trim()).newInstance(); 375 | configuration.setTargetFile(targetFile); 376 | flag=true; 377 | } catch (InstantiationException e) { 378 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 379 | +configuration.getValue() 380 | +"', the targeFileClass ["+targetFileClass+"] is not implements 'cn.easyproject.easybackup.backup.file.TargetFile' interface.", 381 | e); 382 | e2=e; 383 | } catch (IllegalAccessException e) { 384 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 385 | +configuration.getValue() 386 | +"', the targeFileClass ["+targetFileClass+"] is IllegalAccessException.", 387 | e); 388 | e2=e; 389 | } catch (ClassNotFoundException e) { 390 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 391 | +configuration.getValue() 392 | +"', the targeFileClass ["+targetFileClass+"] is not found.", 393 | e); 394 | e2=e; 395 | } 396 | 397 | if(!flag){ 398 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 399 | +configuration.getValue() 400 | +"' targeFileClass ["+targetFileClass+"] error, the backup is cancel.",e2); 401 | // continue; 402 | } 403 | }else{ 404 | configuration.setTargetFile(new DefaultTargtFile()); 405 | } 406 | 407 | // backupClass 408 | if(EasyUtil.isNotEmpty(backupClass)){ 409 | configuration.setBackupClass(backupClass); 410 | boolean flag=false; 411 | Exception e2=null; 412 | try { 413 | Backup backup=(Backup) Class.forName(backupClass.trim()).newInstance(); 414 | configuration.setBackup(backup); 415 | flag=true; 416 | } catch (InstantiationException e) { 417 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 418 | +configuration.getValue() 419 | +"', the backupClass ["+backupClass+"] is not implements 'cn.easyproject.easybackup.backup.file.TargetFile' interface.", 420 | e); 421 | e2=e; 422 | } catch (IllegalAccessException e) { 423 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 424 | +configuration.getValue() 425 | +"', the backupClass ["+backupClass+"] is IllegalAccessException.", 426 | e); 427 | e2=e; 428 | } catch (ClassNotFoundException e) { 429 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 430 | +configuration.getValue() 431 | +"', the backupClass ["+backupClass+"] is not found.", 432 | e); 433 | e2=e; 434 | } 435 | 436 | if(!flag){ 437 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 438 | +configuration.getValue() 439 | +"' backupClass ["+backupClass+"] error, the backup is cancel.",e2); 440 | // continue; 441 | } 442 | }else{ 443 | configuration.setBackup(new FileBackup()); 444 | } 445 | 446 | // dirClass 447 | if(EasyUtil.isNotEmpty(dirClass)){ 448 | configuration.setDirClass(dirClass); 449 | boolean flag=false; 450 | Exception e2=null; 451 | try { 452 | BackupDir backupDir=(BackupDir) Class.forName(dirClass.trim()).newInstance(); 453 | configuration.setBackupDir(backupDir); 454 | flag=true; 455 | } catch (InstantiationException e) { 456 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 457 | +configuration.getValue() 458 | +"', the dirClass ["+dirClass+"] is not implements 'cn.easyproject.easybackup.backup.file.TargetFile' interface.", 459 | e); 460 | e2=e; 461 | } catch (IllegalAccessException e) { 462 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 463 | +configuration.getValue() 464 | +"', the dirClass ["+dirClass+"] is IllegalAccessException.", 465 | e); 466 | e2=e; 467 | } catch (ClassNotFoundException e) { 468 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 469 | +configuration.getValue() 470 | +"', the dirClass ["+dirClass+"] is not found.", 471 | e); 472 | e2=e; 473 | } 474 | 475 | if(!flag){ 476 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 477 | +configuration.getValue() 478 | +"' dirClass ["+dirClass+"] error, the backup is cancel.",e2); 479 | // continue; 480 | } 481 | }else{ 482 | configuration.setBackupDir(new DefaultBackupDir()); 483 | } 484 | 485 | // fileClass 486 | if(EasyUtil.isNotEmpty(fileClass)){ 487 | configuration.setFileClass(fileClass); 488 | boolean flag=false; 489 | Exception e2=null; 490 | try { 491 | BackupFile backupFile=(BackupFile) Class.forName(fileClass.trim()).newInstance(); 492 | configuration.setBackupFile(backupFile); 493 | flag=true; 494 | } catch (InstantiationException e) { 495 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 496 | +configuration.getValue() 497 | +"', the fileClass ["+fileClass+"] is not implements 'cn.easyproject.easybackup.backup.file.TargetFile' interface.", 498 | e); 499 | e2=e; 500 | } catch (IllegalAccessException e) { 501 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 502 | +configuration.getValue() 503 | +"', the fileClass ["+fileClass+"] is IllegalAccessException.", 504 | e); 505 | e2=e; 506 | } catch (ClassNotFoundException e) { 507 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 508 | +configuration.getValue() 509 | +"', the fileClass ["+fileClass+"] is not found.", 510 | e); 511 | e2=e; 512 | } 513 | 514 | if(!flag){ 515 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 516 | +configuration.getValue() 517 | +"' fileClass ["+fileClass+"] error, the backup is cancel.",e2); 518 | // continue; 519 | } 520 | }else{ 521 | configuration.setBackupFile(new DefaultBackupFile()); 522 | } 523 | 524 | 525 | } 526 | 527 | 528 | // 邮件模板检测,如果不存在默认加载mail.tpl 529 | if(!EasyUtil.isNotEmpty(configuration.getMailSenderTemplate())){ 530 | logger.warn("Not configuration '"+startWith+name+".mail.sender.template'. Use default 'mail.tpl'"); 531 | configuration.setMailSenderTemplate("mail.tpl"); 532 | } 533 | 534 | 535 | // 自定义Sender 536 | if(EasyUtil.isNotEmpty(senders)){ 537 | configuration.setSendersString(senders); 538 | String[] senderImpls=senders.split(";"); 539 | if(senderImpls.length>0){ 540 | for (String cls : senderImpls) { 541 | if(!"".equals(cls)){ 542 | // 加载自定义Sender 543 | try { 544 | Sender userSender=(Sender) Class.forName(cls).newInstance(); 545 | configuration.getSenders().add(userSender); 546 | } catch (InstantiationException e) { 547 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 548 | +configuration.getValue() 549 | +"', the Sender class ["+cls+"] is not implements 'cn.easyproject.easybackup.sender.Sender' interface.", 550 | e); 551 | } catch (IllegalAccessException e) { 552 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 553 | +configuration.getValue() 554 | +"', the Sender class ["+cls+"] is IllegalAccessException.", 555 | e); 556 | } catch (ClassNotFoundException e) { 557 | logger.error(configuration.getType().name()+"-"+configuration.getName()+": '" 558 | +configuration.getValue() 559 | +"', the Sender class ["+cls+"] is not found.", 560 | e); 561 | } 562 | 563 | } 564 | } 565 | } 566 | } 567 | 568 | // MailSender 569 | if(EasyUtil.isNotEmpty(configuration.getMailSender())&&configuration.getMailReceiver()!=null&&configuration.getMailReceiver().length!=0){ 570 | configuration.getSenders().add(new MailSender()); 571 | } 572 | 573 | backups.add(configuration); 574 | 575 | } 576 | 577 | } 578 | 579 | 580 | public void initJob(){ 581 | 582 | BackupRuntime.errorJobBackupsOnStartup.clear(); 583 | BackupRuntime.runningBackupsOnStartup.clear(); 584 | BackupRuntime.allBackupsOnStartup.clear(); 585 | 586 | // JobManager 587 | JobManager jobManager=SpringUtil.get("jobManager"); 588 | 589 | // Initial monitor job 590 | if(backups.size()==0){ 591 | logger.info("No running backup services"); 592 | }else{ 593 | // 所有备份 配置 594 | BackupRuntime.allBackupsOnStartup=backups; 595 | } 596 | 597 | for (BackupConfiguration configuration : backups) { 598 | logger.info(configuration.toString()); 599 | 600 | if(configuration.getEnable()){ 601 | try { 602 | jobManager.addJob(configuration); 603 | // 运行的 备份 Backup 配置 604 | BackupRuntime.runningBackupsOnStartup.add(configuration); 605 | } catch (Exception e) { 606 | logger.error("Add backup job error!",e); 607 | BackupRuntime.errorJobBackupsOnStartup.add(configuration); 608 | } 609 | } 610 | } 611 | 612 | // ReloadConfiguration job 613 | jobManager.reloadConfigurationJob(); 614 | } 615 | 616 | public void start() { 617 | // 初始化配置 618 | initConfig(); 619 | // 初始化Job 620 | initJob(); 621 | BackupRuntime.started=true; 622 | } 623 | 624 | } 625 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/BackupDir.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 7 | /** 8 | * Get BackupFile directory 9 | * @author easyproject.cn 10 | * 11 | * @since 1.0.0 12 | */ 13 | public interface BackupDir { 14 | public List getDir(BackupConfiguration configuration); 15 | } 16 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/BackupFile.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file; 2 | 3 | 4 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 5 | /** 6 | * Get BackupFile name 7 | * @author easyproject.cn 8 | * 9 | * @since 1.0.0 10 | */ 11 | public interface BackupFile { 12 | public String getFile(BackupConfiguration configuration); 13 | } 14 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/TargetFile.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file; 2 | 3 | import java.io.File; 4 | 5 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 6 | 7 | /** 8 | * Get TargetFile 9 | * @author easyproject.cn 10 | * 11 | * @since 1.0.0 12 | */ 13 | public interface TargetFile { 14 | public File getFile(BackupConfiguration configuration); 15 | } 16 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/impl/DefaultBackupDir.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file.impl; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import cn.easyproject.easybackup.backup.file.BackupDir; 8 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 9 | /** 10 | * Default get BackupFile directory 11 | * @author easyproject.cn 12 | * 13 | * @since 1.0.0 14 | */ 15 | public class DefaultBackupDir implements BackupDir { 16 | 17 | public List getDir(BackupConfiguration configuration) { 18 | 19 | List list=new ArrayList(); 20 | 21 | for (String dir : configuration.getDir()) { 22 | try { 23 | File backupDir=new File(dir); 24 | 25 | if(!backupDir.exists()){ 26 | backupDir.mkdirs(); 27 | } 28 | 29 | list.add(backupDir); 30 | } catch (Exception e) { 31 | e.printStackTrace(); 32 | } 33 | } 34 | 35 | return list; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/impl/DefaultBackupFile.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file.impl; 2 | 3 | 4 | import cn.easyproject.easybackup.backup.file.BackupFile; 5 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 6 | import cn.easyproject.easybackup.util.EasyUtil; 7 | /** 8 | * Default get BackupFile name 9 | * @author easyproject.cn 10 | * 11 | * @since 1.0.0 12 | */ 13 | public class DefaultBackupFile implements BackupFile{ 14 | 15 | 16 | 17 | 18 | public String getFile(BackupConfiguration configuration) { 19 | if(EasyUtil.isNotEmpty(configuration.getFile())){ 20 | return configuration.getFile(); 21 | } 22 | return null; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/file/impl/DefaultTargtFile.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.file.impl; 2 | 3 | import java.io.File; 4 | 5 | import cn.easyproject.easybackup.backup.file.TargetFile; 6 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 7 | /** 8 | * Default get TargetFile 9 | * @author easyproject.cn 10 | * 11 | * @since 1.0.0 12 | */ 13 | public class DefaultTargtFile implements TargetFile { 14 | 15 | public File getFile(BackupConfiguration configuration) { 16 | try { 17 | File file=new File(configuration.getValue()); 18 | return file; 19 | } catch (Exception e) { 20 | e.printStackTrace(); 21 | } 22 | return null; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/impls/Backup.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.impls; 2 | 3 | import java.io.File; 4 | 5 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 6 | 7 | /** 8 | * Backup implements 9 | * @author easyproject.cn 10 | * 11 | * @since 1.0.0 12 | */ 13 | public interface Backup { 14 | public boolean execute(File targetFile,File backupFile, BackupConfiguration configuration); 15 | } 16 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/impls/FileBackup.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.impls; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import org.springframework.util.FileSystemUtils; 7 | 8 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 9 | import cn.easyproject.easybackup.util.CompressFileUtil; 10 | 11 | /** 12 | * File implements 13 | * @author easyproject.cn 14 | * 15 | * @since 1.0.0 16 | */ 17 | public class FileBackup implements Backup { 18 | 19 | public boolean execute(File targetFile,File backupFile, BackupConfiguration configuration){ 20 | boolean res=false; 21 | // Need to compress 22 | if(configuration.getCompress()){ 23 | res=CompressFileUtil.compress( 24 | configuration.getCompressType(), 25 | targetFile, 26 | backupFile, 27 | configuration.getCompressEncoding() 28 | ); 29 | 30 | }else{ 31 | try { 32 | FileSystemUtils.copyRecursively(targetFile, backupFile); 33 | res=true; 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | return res; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/interceptor/BackupAfter.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.interceptor; 2 | 3 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 4 | 5 | /** 6 | * Backup after interceptor 7 | * @author easyproject.cn 8 | * 9 | * @since 1.0.0 10 | */ 11 | public interface BackupAfter { 12 | public void execute(BackupConfiguration configuration); 13 | } 14 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/backup/interceptor/BackupBefore.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.backup.interceptor; 2 | 3 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 4 | /** 5 | * Backup before interceptor 6 | * @author easyproject.cn 7 | * 8 | * @since 1.0.0 9 | */ 10 | public interface BackupBefore { 11 | /** 12 | * if return false, stop backup 13 | * @param configuration BackupConfiguration 14 | * @return whether execute backup 15 | */ 16 | public boolean execute(BackupConfiguration configuration); 17 | } 18 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/configuration/BackupConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.configuration; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import cn.easyproject.easybackup.BackupType; 9 | import cn.easyproject.easybackup.backup.file.BackupDir; 10 | import cn.easyproject.easybackup.backup.file.BackupFile; 11 | import cn.easyproject.easybackup.backup.file.TargetFile; 12 | import cn.easyproject.easybackup.backup.impls.Backup; 13 | import cn.easyproject.easybackup.backup.interceptor.BackupAfter; 14 | import cn.easyproject.easybackup.backup.interceptor.BackupBefore; 15 | import cn.easyproject.easybackup.sender.Sender; 16 | 17 | /** 18 | * BackupConfiguration 19 | * 20 | * @author easyproject.cn 21 | * 22 | * @since 1.0.0 23 | */ 24 | public class BackupConfiguration extends GlobalConfiguration implements Serializable{ 25 | 26 | /** 27 | * serialVersionUID 28 | */ 29 | private static final long serialVersionUID = 1L; 30 | 31 | 32 | /** 33 | * Backup Name 34 | */ 35 | protected String name; 36 | /** 37 | * Backup Type: BackupType 38 | */ 39 | protected BackupType type; 40 | 41 | /** 42 | * Backup value 43 | */ 44 | protected String value; 45 | 46 | /** 47 | * User Sender implements 48 | */ 49 | protected List senders=new ArrayList(); 50 | 51 | 52 | 53 | /** 54 | * Backup implements 55 | */ 56 | protected Backup backup; 57 | 58 | /** 59 | * BackupDir object 60 | */ 61 | protected BackupDir backupDir; 62 | 63 | /** 64 | * BackupFile object 65 | */ 66 | protected BackupFile backupFile; 67 | 68 | /** 69 | * TargetFile object 70 | */ 71 | protected TargetFile targetFile; 72 | 73 | /** 74 | * The targeFileClass 75 | */ 76 | protected String targetFileClass; 77 | 78 | /** 79 | * The backupClass 80 | */ 81 | protected String backupClass; 82 | 83 | /** 84 | * The dirClass 85 | */ 86 | protected String dirClass; 87 | 88 | /** 89 | * The fileClass 90 | */ 91 | protected String fileClass; 92 | 93 | /** 94 | * Backup before interceptors 95 | */ 96 | protected List before=new ArrayList(); 97 | 98 | /** 99 | * Backup after interceptors 100 | */ 101 | protected List after=new ArrayList(); 102 | 103 | protected String sendersString; 104 | 105 | public String getName() { 106 | return name; 107 | } 108 | 109 | public void setName(String name) { 110 | this.name = name; 111 | } 112 | 113 | public BackupType getType() { 114 | return type; 115 | } 116 | 117 | public void setType(BackupType type) { 118 | this.type = type; 119 | } 120 | 121 | public String getValue() { 122 | return value; 123 | } 124 | 125 | public void setValue(String value) { 126 | this.value = value; 127 | } 128 | 129 | public List getSenders() { 130 | return senders; 131 | } 132 | 133 | public void setSenders(List senders) { 134 | this.senders = senders; 135 | } 136 | 137 | public Backup getBackup() { 138 | return backup; 139 | } 140 | 141 | public void setBackup(Backup backup) { 142 | this.backup = backup; 143 | } 144 | 145 | public BackupDir getBackupDir() { 146 | return backupDir; 147 | } 148 | 149 | public void setBackupDir(BackupDir backupDir) { 150 | this.backupDir = backupDir; 151 | } 152 | 153 | public BackupFile getBackupFile() { 154 | return backupFile; 155 | } 156 | 157 | public void setBackupFile(BackupFile backupFile) { 158 | this.backupFile = backupFile; 159 | } 160 | 161 | public TargetFile getTargetFile() { 162 | return targetFile; 163 | } 164 | 165 | public void setTargetFile(TargetFile targetFile) { 166 | this.targetFile = targetFile; 167 | } 168 | 169 | public String getTargetFileClass() { 170 | return targetFileClass; 171 | } 172 | 173 | public void setTargetFileClass(String targetFileClass) { 174 | this.targetFileClass = targetFileClass; 175 | } 176 | 177 | public String getBackupClass() { 178 | return backupClass; 179 | } 180 | 181 | public void setBackupClass(String backupClass) { 182 | this.backupClass = backupClass; 183 | } 184 | 185 | public String getDirClass() { 186 | return dirClass; 187 | } 188 | 189 | public void setDirClass(String dirClass) { 190 | this.dirClass = dirClass; 191 | } 192 | 193 | public String getFileClass() { 194 | return fileClass; 195 | } 196 | 197 | public void setFileClass(String fileClass) { 198 | this.fileClass = fileClass; 199 | } 200 | 201 | 202 | 203 | public List getBefore() { 204 | return before; 205 | } 206 | 207 | public void setBefore(List before) { 208 | this.before = before; 209 | } 210 | 211 | public List getAfter() { 212 | return after; 213 | } 214 | 215 | public void setAfter(List after) { 216 | this.after = after; 217 | } 218 | 219 | public String getSendersString() { 220 | return sendersString; 221 | } 222 | 223 | public void setSendersString(String sendersString) { 224 | this.sendersString = sendersString; 225 | } 226 | 227 | @Override 228 | public String toString() { 229 | return "BackupConfiguration [name=" + name + ", type=" + type + ", value=" + value + ", senders=" + senders 230 | + ", backup=" + backup + ", backupDir=" + backupDir + ", backupFile=" + backupFile + ", targetFile=" 231 | + targetFile + ", targetFileClass=" + targetFileClass + ", backupClass=" + backupClass + ", dirClass=" 232 | + dirClass + ", fileClass=" + fileClass + ", before=" + before + ", after=" + after + ", sendersString=" 233 | + sendersString + ", enable=" + enable + ", cronExpression=" + cronExpression + ", dir=" 234 | + Arrays.toString(dir) + ", file=" + file + ", compress=" + compress + ", compressType=" + compressType 235 | + ", compressEncoding=" + compressEncoding + ", mailReceiver=" + Arrays.toString(mailReceiver) 236 | + ", mailSender=" + mailSender + ", mailSenderHost=" + mailSenderHost + ", mailSenderPort=" 237 | + mailSenderPort + ", mailSenderSsl=" + mailSenderSsl + ", mailSenderPassword=" + mailSenderPassword 238 | + ", mailSenderTitle=" + mailSenderTitle + ", mailSenderTemplate=" + mailSenderTemplate 239 | + ", mailDeleteBackup=" + mailDeleteBackup + ", cmdBefore=" + Arrays.toString(cmdBefore) + ", cmdAfter=" 240 | + Arrays.toString(cmdAfter) + ", beforeClass=" + Arrays.toString(beforeClass) + ", afterClass=" 241 | + Arrays.toString(afterClass) + ", deleteTargetFile=" + deleteTargetFile + ", lastBackupTime=" 242 | + lastBackupTime + ", lastSenderTime=" + lastSenderTime + ", lastBackupFileName=" + lastBackupFileName 243 | + ", lastBackupResult=" + lastBackupResult + "]"; 244 | } 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | } 264 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/configuration/GlobalConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.configuration; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Global BackupConfiguration 7 | * 8 | * @author easyproject.cn 9 | * 10 | * @since 1.0.0 11 | */ 12 | public class GlobalConfiguration { 13 | 14 | 15 | 16 | 17 | 18 | 19 | /** 20 | * Turn EasyBackup ON or OFF 21 | */ 22 | protected Boolean enable; 23 | /** 24 | * Backup trigger Cron-Expressions; default is '0/10 * * * * ?' 25 | */ 26 | protected String cronExpression; 27 | 28 | /** 29 | * Directory to store the backup file 30 | */ 31 | protected String[] dir; 32 | 33 | /** 34 | * backup file name under 'easybackup.backup.dir' directory 35 | * If not specified, the automatically generated file name is 'filename-yyyyMMddHHmmss.zip|tar|tar.gz' 36 | */ 37 | protected String file; 38 | 39 | /** 40 | * Whether backup compression, default is ON 41 | */ 42 | protected Boolean compress; 43 | 44 | /** 45 | * Compression format: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz), default is ZIP 46 | */ 47 | protected String compressType; 48 | 49 | /** 50 | * Compression encoding 51 | */ 52 | protected String compressEncoding; 53 | 54 | 55 | /** 56 | * Backup Mail receiver 57 | */ 58 | protected String[] mailReceiver; 59 | 60 | /** 61 | * Backup Mail sender 62 | */ 63 | protected String mailSender; 64 | /** 65 | * Backup Mail sender host(smtp.xxx.xxx) 66 | */ 67 | protected String mailSenderHost; 68 | 69 | /** 70 | * Backup Mail sender port, default is 25 71 | */ 72 | protected Integer mailSenderPort=25; 73 | 74 | /** 75 | * Backup Mail sender whether ssl, default is false 76 | */ 77 | protected Boolean mailSenderSsl=false; 78 | /** 79 | * Backup Mail sender password 80 | */ 81 | protected String mailSenderPassword; 82 | /** 83 | * Backup Mail sender title 84 | */ 85 | protected String mailSenderTitle; 86 | /** 87 | * Backup Mail sender template 88 | */ 89 | protected String mailSenderTemplate; 90 | 91 | /** 92 | * Auto delete when send email complete ON or OFF 93 | */ 94 | protected Boolean mailDeleteBackup; 95 | 96 | 97 | /** 98 | * Execute Command when backup before 99 | */ 100 | protected String[] cmdBefore; 101 | /** 102 | * Execute Command when backup after 103 | */ 104 | protected String[] cmdAfter; 105 | 106 | /** 107 | * Execute Command when backup before 108 | */ 109 | protected String[] beforeClass; 110 | /** 111 | * Execute Command when backup after 112 | */ 113 | protected String[] afterClass; 114 | 115 | 116 | /** 117 | * Whether delete targetFile after backup complete. 118 | */ 119 | protected boolean deleteTargetFile; 120 | 121 | /** 122 | * The time of last backup 123 | */ 124 | protected Date lastBackupTime; 125 | 126 | /** 127 | * The time of last sender notify 128 | */ 129 | protected Date lastSenderTime; 130 | 131 | /** 132 | * The name of last backup file 133 | */ 134 | protected String lastBackupFileName; 135 | 136 | /** 137 | * The result of last backup file 138 | */ 139 | protected boolean lastBackupResult; 140 | 141 | 142 | 143 | public Boolean getEnable() { 144 | return enable; 145 | } 146 | 147 | public void setEnable(Boolean enable) { 148 | this.enable = enable; 149 | } 150 | 151 | public String getCronExpression() { 152 | return cronExpression; 153 | } 154 | 155 | public void setCronExpression(String cronExpression) { 156 | this.cronExpression = cronExpression; 157 | } 158 | 159 | 160 | 161 | public String[] getDir() { 162 | return dir; 163 | } 164 | 165 | public void setDir(String[] dir) { 166 | this.dir = dir; 167 | } 168 | 169 | public String getFile() { 170 | return file; 171 | } 172 | 173 | public void setFile(String file) { 174 | this.file = file; 175 | } 176 | 177 | public Boolean getCompress() { 178 | return compress; 179 | } 180 | 181 | public void setCompress(Boolean compress) { 182 | this.compress = compress; 183 | } 184 | 185 | public String getCompressType() { 186 | return compressType; 187 | } 188 | 189 | public void setCompressType(String compressType) { 190 | this.compressType = compressType; 191 | } 192 | 193 | public String[] getMailReceiver() { 194 | return mailReceiver; 195 | } 196 | 197 | public void setMailReceiver(String[] mailReceiver) { 198 | this.mailReceiver = mailReceiver; 199 | } 200 | 201 | public String getMailSender() { 202 | return mailSender; 203 | } 204 | 205 | public void setMailSender(String mailSender) { 206 | this.mailSender = mailSender; 207 | } 208 | 209 | public String getMailSenderHost() { 210 | return mailSenderHost; 211 | } 212 | 213 | public void setMailSenderHost(String mailSenderHost) { 214 | this.mailSenderHost = mailSenderHost; 215 | } 216 | 217 | public Integer getMailSenderPort() { 218 | return mailSenderPort; 219 | } 220 | 221 | public void setMailSenderPort(Integer mailSenderPort) { 222 | this.mailSenderPort = mailSenderPort; 223 | } 224 | 225 | public Boolean getMailSenderSsl() { 226 | return mailSenderSsl; 227 | } 228 | 229 | public void setMailSenderSsl(Boolean mailSenderSsl) { 230 | this.mailSenderSsl = mailSenderSsl; 231 | } 232 | 233 | public String getMailSenderPassword() { 234 | return mailSenderPassword; 235 | } 236 | 237 | public void setMailSenderPassword(String mailSenderPassword) { 238 | this.mailSenderPassword = mailSenderPassword; 239 | } 240 | 241 | public String getMailSenderTitle() { 242 | return mailSenderTitle; 243 | } 244 | 245 | public void setMailSenderTitle(String mailSenderTitle) { 246 | this.mailSenderTitle = mailSenderTitle; 247 | } 248 | 249 | public String getMailSenderTemplate() { 250 | return mailSenderTemplate; 251 | } 252 | 253 | public void setMailSenderTemplate(String mailSenderTemplate) { 254 | this.mailSenderTemplate = mailSenderTemplate; 255 | } 256 | 257 | public Boolean getMailDeleteBackup() { 258 | return mailDeleteBackup; 259 | } 260 | 261 | public void setMailDeleteBackup(Boolean mailDeleteBackup) { 262 | this.mailDeleteBackup = mailDeleteBackup; 263 | } 264 | 265 | public String[] getCmdBefore() { 266 | return cmdBefore; 267 | } 268 | 269 | public void setCmdBefore(String[] cmdBefore) { 270 | this.cmdBefore = cmdBefore; 271 | } 272 | 273 | public String[] getCmdAfter() { 274 | return cmdAfter; 275 | } 276 | 277 | public void setCmdAfter(String[] cmdAfter) { 278 | this.cmdAfter = cmdAfter; 279 | } 280 | 281 | public String[] getBeforeClass() { 282 | return beforeClass; 283 | } 284 | 285 | public void setBeforeClass(String[] beforeClass) { 286 | this.beforeClass = beforeClass; 287 | } 288 | 289 | public String[] getAfterClass() { 290 | return afterClass; 291 | } 292 | 293 | public void setAfterClass(String[] afterClass) { 294 | this.afterClass = afterClass; 295 | } 296 | 297 | 298 | 299 | public Date getLastBackupTime() { 300 | return lastBackupTime; 301 | } 302 | 303 | public void setLastBackupTime(Date lastBackupTime) { 304 | this.lastBackupTime = lastBackupTime; 305 | } 306 | 307 | public Date getLastSenderTime() { 308 | return lastSenderTime; 309 | } 310 | 311 | public void setLastSenderTime(Date lastSenderTime) { 312 | this.lastSenderTime = lastSenderTime; 313 | } 314 | 315 | public String getLastBackupFileName() { 316 | return lastBackupFileName; 317 | } 318 | 319 | public void setLastBackupFileName(String lastBackupFileName) { 320 | this.lastBackupFileName = lastBackupFileName; 321 | } 322 | 323 | public boolean isLastBackupResult() { 324 | return lastBackupResult; 325 | } 326 | 327 | public void setLastBackupResult(boolean lastBackupResult) { 328 | this.lastBackupResult = lastBackupResult; 329 | } 330 | 331 | public String getCompressEncoding() { 332 | return compressEncoding; 333 | } 334 | 335 | public void setCompressEncoding(String compressEncoding) { 336 | this.compressEncoding = compressEncoding; 337 | } 338 | 339 | public boolean isDeleteTargetFile() { 340 | return deleteTargetFile; 341 | } 342 | 343 | public void setDeleteTargetFile(boolean deleteTargetFile) { 344 | this.deleteTargetFile = deleteTargetFile; 345 | } 346 | 347 | 348 | 349 | 350 | 351 | 352 | } 353 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/job/BackupJob.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.job; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.text.SimpleDateFormat; 6 | import java.util.ArrayList; 7 | import java.util.Date; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.quartz.DisallowConcurrentExecution; 13 | import org.quartz.JobDataMap; 14 | import org.quartz.JobExecutionContext; 15 | import org.quartz.JobExecutionException; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.scheduling.quartz.QuartzJobBean; 19 | 20 | import cn.easyproject.easybackup.backup.interceptor.BackupAfter; 21 | import cn.easyproject.easybackup.backup.interceptor.BackupBefore; 22 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 23 | import cn.easyproject.easybackup.sender.Sender; 24 | import cn.easyproject.easybackup.util.FreemarkerUtil; 25 | import cn.easyproject.easybackup.util.SpringUtil; 26 | 27 | /** 28 | * EasyMonitor Job execute 29 | * @author easyproject.cn 30 | * 31 | * @since 1.0.0 32 | */ 33 | @DisallowConcurrentExecution 34 | public class BackupJob extends QuartzJobBean { 35 | private static Logger logger = LoggerFactory.getLogger(BackupJob.class); 36 | 37 | 38 | @Override 39 | protected void executeInternal(JobExecutionContext context) throws JobExecutionException { 40 | long start=System.currentTimeMillis(); 41 | // 配置信息 42 | JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); 43 | BackupConfiguration configuration = (BackupConfiguration) jobDataMap.get("configuration"); 44 | // 必须是有效配置 45 | if(configuration==null){ 46 | return; 47 | } 48 | 49 | // 如果备份对象不完全,取消备份 50 | if(configuration.getTargetFile()==null 51 | || configuration.getBackupDir()==null 52 | || configuration.getBackupFile()==null 53 | || configuration.getBackup()==null 54 | ){ 55 | return; 56 | } 57 | 58 | // 任务对象 59 | JobManager jobManager = SpringUtil.get("jobManager"); 60 | 61 | // 准备备份,暂停定时任务 62 | jobManager.pauseJob(context); 63 | 64 | // Command&Interceptor before 65 | commandExecute(configuration, configuration.getBeforeClass()); 66 | 67 | if(configuration.getBefore().size()>0){ 68 | for (BackupBefore before : configuration.getBefore()) { 69 | logger.debug(configuration.getType().name() 70 | + 71 | "-" 72 | + configuration.getName() 73 | + " execute before interceptor ["+before.getClass().getName()+"]."); 74 | boolean res=before.execute(configuration); 75 | if(!res){ 76 | logger.info( 77 | configuration.getType().name() 78 | + 79 | "-" 80 | + configuration.getName() 81 | + " BackupBefore interceptor class ["+before.getClass().getName()+"] " 82 | + " return false, the backup cancel."); 83 | // 恢复定时任务 84 | jobManager.resumeJob(context); 85 | 86 | return; 87 | } 88 | } 89 | } 90 | 91 | 92 | 93 | File targetFile=configuration.getTargetFile().getFile(configuration); 94 | 95 | if(targetFile==null){ 96 | logger.error(configuration.getType().name() 97 | + 98 | "-" 99 | + configuration.getName() 100 | + " cancel backup, the file ["+targetFile+"] you want backup is null."); 101 | // 恢复定时任务 102 | jobManager.resumeJob(context); 103 | return; 104 | } 105 | if(!targetFile.exists()){ 106 | logger.warn(configuration.getType().name() 107 | + 108 | "-" 109 | + configuration.getName() 110 | + " cancel backup, he file ["+targetFile+"] you want backup is not exists."); 111 | // 恢复定时任务 112 | jobManager.resumeJob(context); 113 | return; 114 | } 115 | 116 | 117 | 118 | 119 | 120 | 121 | // 获得备份文件和目录 122 | List backupDirs=configuration.getBackupDir().getDir(configuration); 123 | 124 | 125 | if(backupDirs.size()==0){ 126 | logger.error(configuration.getType().name() 127 | + 128 | "-" 129 | + configuration.getName() 130 | + " backup dir ["+configuration.getDir()+"] is empty."); 131 | // 恢复定时任务 132 | jobManager.resumeJob(context); 133 | return; 134 | } 135 | 136 | 137 | 138 | String backupFileName=configuration.getBackupFile().getFile(configuration); 139 | 140 | // 如果文件名为null,则自动生成文件名 141 | if(backupFileName==null){ 142 | SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddHHmmssS"); 143 | backupFileName="${targetFileName}-"+sdf.format(new Date()); 144 | } 145 | 146 | // 如果存在压缩需求,则备份为压缩文件 147 | if(configuration.getCompress()){ 148 | if(configuration.getCompressType().equalsIgnoreCase("gzip")){ 149 | backupFileName+=".tar.gz"; 150 | }else{ 151 | backupFileName+="."+configuration.getCompressType().toLowerCase(); 152 | } 153 | } 154 | 155 | Map data=new HashMap(); 156 | data.put("targetFileName", targetFile.getName()); 157 | data.put("name", configuration.getName()); 158 | data.put("type", configuration.getType()); 159 | data.put("value", configuration.getValue()); 160 | data.put("backuptime", new Date()); 161 | data.put("backupConfiguration", configuration); 162 | 163 | backupFileName=FreemarkerUtil.formatTemplate(backupFileName, data); 164 | 165 | data.put("backupFileName", backupFileName); 166 | 167 | // Backup 168 | // 记录最后备份时间 169 | configuration.setLastBackupTime(new Date()); 170 | // 记录最后备份文件名 171 | configuration.setLastBackupFileName(backupFileName); 172 | 173 | // start backup 174 | 175 | boolean backupRes=true; 176 | 177 | List backupFiles=new ArrayList(); 178 | 179 | for (File backupDir : backupDirs) { 180 | File backupFile=new File(backupDir, backupFileName); 181 | backupFiles.add(backupFile); 182 | } 183 | 184 | 185 | for (File backupFile : backupFiles) { 186 | if(targetFile.equals(backupFile)){ 187 | logger.warn(configuration.getType().name() 188 | + 189 | "-" 190 | + configuration.getName() 191 | + " Your targetFile equals backupFile, " 192 | + "backup success." 193 | ); 194 | configuration.setLastBackupResult(true); 195 | }else{ 196 | boolean res=configuration.getBackup().execute(targetFile, backupFile, configuration); 197 | backupRes=backupRes&&res; 198 | } 199 | } 200 | 201 | configuration.setLastBackupResult(backupRes); 202 | 203 | if(configuration.isLastBackupResult()){ 204 | logger.info(configuration.getType().name() 205 | + 206 | "-" 207 | + configuration.getName() 208 | + " backup success." 209 | + " last backup file name: "+configuration.getLastBackupFileName() 210 | + ", last backup file time: "+configuration.getLastBackupTime() 211 | + ", last backup file result: "+configuration.isLastBackupResult() 212 | ); 213 | 214 | if(configuration.isDeleteTargetFile()){ 215 | 216 | // 检测备份文件是否与原文件相同 217 | boolean isDelete=true; 218 | for (File backupFile : backupFiles) { 219 | // 相同,不删除 220 | if(targetFile.equals(backupFile)){ 221 | isDelete=false; 222 | break; 223 | } 224 | } 225 | 226 | if(isDelete){ 227 | logger.info(configuration.getType().name() 228 | + 229 | "-" 230 | + configuration.getName() 231 | + " delete targetFile" 232 | ); 233 | 234 | boolean delRes=targetFile.delete(); 235 | if(!delRes){ 236 | logger.info(configuration.getType().name() 237 | + 238 | "-" 239 | + configuration.getName() 240 | + " delete targetFile failure. maybe the file is locked, please delete manual." 241 | ); 242 | } 243 | } 244 | 245 | } 246 | 247 | }else{ 248 | logger.warn(configuration.getType().name() 249 | + 250 | "-" 251 | + configuration.getName() 252 | + " backup failure." 253 | + " last backup file name: "+configuration.getLastBackupFileName() 254 | + ", last backup file time: "+configuration.getLastBackupTime() 255 | + ", last backup file result: "+configuration.isLastBackupResult() 256 | ); 257 | } 258 | 259 | 260 | // Command&Interceptor after 261 | commandExecute(configuration, configuration.getBeforeClass()); 262 | 263 | if(configuration.getAfter().size()>0){ 264 | for (BackupAfter after : configuration.getAfter()) { 265 | logger.debug(configuration.getType().name() 266 | + 267 | "-" 268 | + configuration.getName() 269 | + " execute after interceptor ["+after.getClass().getName()+"]."); 270 | after.execute(configuration); 271 | } 272 | } 273 | 274 | // Senders 275 | if (configuration.getSenders().size()>0) { 276 | // 邮件标题 277 | configuration.setMailSenderTitle(FreemarkerUtil.formatTemplate(configuration.getMailSenderTitle(), data)); 278 | 279 | // 记录最后发送时间 280 | configuration.setLastBackupTime(new Date()); 281 | } 282 | for (Sender sender : configuration.getSenders()) { 283 | sender.send(targetFile, backupFiles, configuration); 284 | } 285 | 286 | 287 | long end=System.currentTimeMillis(); 288 | // 记录备份时长 289 | logger.info(configuration.getType().name() 290 | + 291 | "-" 292 | + configuration.getName() 293 | + " backup completed, cost in "+(end-start)+" ms"); 294 | 295 | // 恢复任务 296 | jobManager.resumeJob(context); 297 | } 298 | 299 | 300 | /** 301 | * 执行命令 302 | * @param configuration 配置对象 303 | * @return 是否成功 304 | */ 305 | private boolean commandExecute(BackupConfiguration configuration, String[] cmds){ 306 | boolean res=false; 307 | if(cmds==null || cmds.length==0){ 308 | return true; 309 | } 310 | 311 | for (String cmd : cmds) { 312 | try { 313 | logger.debug(configuration.getType().name() 314 | + 315 | "-" 316 | + configuration.getName() 317 | + " execute command ["+cmds+"]."); 318 | Process proc = Runtime.getRuntime().exec(cmd); 319 | proc.waitFor(); 320 | } catch (IOException e) { 321 | logger.error( 322 | configuration.getType().name() + "-" + configuration.getName() 323 | + " execute command ["+cmd+"] error.", 324 | e); 325 | } catch (InterruptedException e) { 326 | logger.error( 327 | configuration.getType().name() + "-" + configuration.getName() 328 | + " execute command ["+cmd+"] error.", 329 | e); 330 | } 331 | } 332 | 333 | return res; 334 | } 335 | 336 | 337 | 338 | 339 | 340 | } 341 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/job/JobManager.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.job; 2 | 3 | import java.util.Date; 4 | 5 | import org.quartz.CronScheduleBuilder; 6 | import org.quartz.CronTrigger; 7 | import org.quartz.JobBuilder; 8 | import org.quartz.JobDetail; 9 | import org.quartz.JobExecutionContext; 10 | import org.quartz.JobKey; 11 | import org.quartz.Scheduler; 12 | import org.quartz.SchedulerException; 13 | import org.quartz.SimpleScheduleBuilder; 14 | import org.quartz.Trigger; 15 | import org.quartz.TriggerBuilder; 16 | import org.quartz.TriggerKey; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 21 | 22 | /** 23 | * Easy Job Manager 24 | * 25 | * @author easyproject.cn 26 | * 27 | * @since 1.0.0 28 | */ 29 | public class JobManager { 30 | 31 | static Logger logger = LoggerFactory.getLogger(JobManager.class); 32 | 33 | // Scheduler 34 | Scheduler scheduler; 35 | 36 | 37 | private int reloadIntervalInSeconds=3; 38 | /** 39 | * 配置文件热加载任务 40 | */ 41 | public void reloadConfigurationJob() { 42 | String jobGroup = "ReloadConfiguraion"; 43 | String jobName = "EasyBackup"; 44 | 45 | // JobDetail 46 | JobKey jobKey = new JobKey(jobName, jobGroup); 47 | try { 48 | if (scheduler.checkExists(jobKey)) { 49 | scheduler.deleteJob(jobKey); 50 | } 51 | } catch (SchedulerException e1) { 52 | logger.error("delete job [" + jobKey + "] error.", e1); 53 | } 54 | 55 | try { 56 | if (scheduler.checkExists(jobKey)) { 57 | jobKey = new JobKey(jobName + "_" + new Date().getTime(), jobGroup); 58 | } 59 | } catch (SchedulerException e1) { 60 | jobKey = new JobKey(jobName + "_" + new Date().getTime(), jobGroup); 61 | } 62 | 63 | // JobDetail 64 | JobDetail jobDetail = JobBuilder.newJob(ReloadConfigurationJob.class).withIdentity(jobKey).build(); 65 | 66 | TriggerKey triggerKey = new TriggerKey(jobKey.getName(), jobKey.getGroup()); 67 | 68 | // Trigger 69 | // Trigger the job to run now, and then repeat every 40 seconds 70 | Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).startNow() 71 | .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(reloadIntervalInSeconds).repeatForever()).build(); 72 | 73 | // Tell quartz to schedule the job using our trigger 74 | try { 75 | scheduler.scheduleJob(jobDetail, trigger); 76 | } catch (SchedulerException e) { 77 | logger.error("ReloadConfiguration Job can not fire!", e); 78 | } 79 | } 80 | 81 | /** 82 | * 根据监控配置添加新的监控 83 | * 84 | * @param configuration 85 | * 监控配置对象 86 | */ 87 | public void addJob(BackupConfiguration configuration) { 88 | if (configuration.getEnable()) { 89 | 90 | String jobGroup = configuration.getType().name(); 91 | String jobName = jobGroup + "_" + configuration.getName(); 92 | 93 | // JobDetail 94 | JobKey jobKey = new JobKey(jobName, jobGroup); 95 | try { 96 | if (scheduler.checkExists(jobKey)) { 97 | scheduler.deleteJob(jobKey); 98 | } 99 | } catch (SchedulerException e1) { 100 | logger.error("delete job [" + jobKey + "] error.", e1); 101 | } 102 | 103 | try { 104 | if (scheduler.checkExists(jobKey)) { 105 | jobKey = new JobKey(jobName + "_" + new Date().getTime(), jobGroup); 106 | } 107 | } catch (SchedulerException e1) { 108 | jobKey = new JobKey(jobName + "_" + new Date().getTime(), jobGroup); 109 | } 110 | 111 | JobDetail jobDetail = JobBuilder.newJob(BackupJob.class).withIdentity(jobKey).build(); 112 | 113 | TriggerKey triggerKey = new TriggerKey(jobKey.getName(), jobKey.getGroup()); 114 | 115 | // Trigger 定义触发器 116 | CronTrigger trigger = TriggerBuilder.newTrigger() 117 | .withIdentity(triggerKey).withSchedule(CronScheduleBuilder 118 | .cronSchedule(configuration.getCronExpression()).withMisfireHandlingInstructionDoNothing()) 119 | .build(); 120 | 121 | // JobDataMap 122 | jobDetail.getJobDataMap().put("configuration", configuration); 123 | 124 | try { 125 | scheduler.scheduleJob(jobDetail, trigger); 126 | } catch (SchedulerException e) { 127 | logger.error("Your Job can not fire! [" + configuration + "]", e); 128 | } 129 | 130 | } 131 | } 132 | 133 | /** 134 | * Pause Job 135 | * 136 | * @param context 137 | * JobExecutionContext 138 | */ 139 | public void pauseJob(JobExecutionContext context) { 140 | // 暂停定时任务 141 | JobKey key = context.getJobDetail().getKey(); 142 | // 暂停任务 143 | try { 144 | context.getScheduler().pauseJob(key); 145 | } catch (SchedulerException e) { 146 | logger.error("Your Job pause failure! [" + key + "]", e); 147 | } 148 | } 149 | 150 | /** 151 | * Resume Job 152 | * 153 | * @param context 154 | * JobExecutionContext 155 | */ 156 | public void resumeJob(JobExecutionContext context) { 157 | // 暂停定时任务 158 | JobKey key = context.getJobDetail().getKey(); 159 | // 暂停任务 160 | try { 161 | context.getScheduler().resumeJob(key); 162 | } catch (SchedulerException e) { 163 | logger.error("Your Job pause failure! [" + key + "]", e); 164 | } 165 | } 166 | 167 | /** 168 | * Delete Job 169 | * 170 | * @param context 171 | * JobExecutionContext 172 | */ 173 | public void deleteJob(JobExecutionContext context) { 174 | // 暂停定时任务 175 | JobKey key = context.getJobDetail().getKey(); 176 | // 暂停任务 177 | try { 178 | context.getScheduler().deleteJob(key); 179 | } catch (SchedulerException e) { 180 | logger.error("Your Job delete failure! [" + key + "]", e); 181 | } 182 | } 183 | 184 | /** 185 | * Clear all Job 186 | */ 187 | public void clear() { 188 | try { 189 | scheduler.clear(); 190 | } catch (SchedulerException e) { 191 | logger.error("Can not reload properties, clear job failure!", e); 192 | } 193 | 194 | } 195 | 196 | public void setScheduler(Scheduler scheduler) { 197 | this.scheduler = scheduler; 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/job/ReloadConfigurationJob.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.job; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.IOException; 5 | import org.quartz.JobExecutionContext; 6 | import org.quartz.JobExecutionException; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.scheduling.quartz.QuartzJobBean; 10 | 11 | import cn.easyproject.easybackup.EasyBackup; 12 | import cn.easyproject.easybackup.backup.StdBackupEngine; 13 | import cn.easyproject.easybackup.util.SpringUtil; 14 | 15 | 16 | /** 17 | * Auto reload the backup job when easybackup.properties update 18 | * @author easyproject.cn 19 | * 20 | * @since 1.0.0 21 | */ 22 | public class ReloadConfigurationJob extends QuartzJobBean { 23 | 24 | static Logger logger=LoggerFactory.getLogger(ReloadConfigurationJob.class); 25 | 26 | public static long propertiesLastModify; 27 | 28 | @Override 29 | protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { 30 | // 检测配置文件是否修改 31 | 32 | if(EasyBackup.getPropertiesFile()!=null){ 33 | try { 34 | long lastModify=EasyBackup.getPropertiesFile().lastModified(); 35 | // 如果配置文件被修改,则停止所有任务,重新加载 36 | if(lastModify!=ReloadConfigurationJob.propertiesLastModify){ 37 | EasyBackup.getProperties().load(new FileInputStream(EasyBackup.getPropertiesFile())); 38 | 39 | ReloadConfigurationJob.propertiesLastModify=lastModify; 40 | 41 | JobManager jobManager = SpringUtil.get("jobManager"); 42 | jobManager.clear(); 43 | 44 | StdBackupEngine stdBackup=new StdBackupEngine(); 45 | stdBackup.start(); 46 | logger.info("the EasyBackup properties file ["+EasyBackup.getPropertiesFile().getName()+"] already reload." ); 47 | } 48 | 49 | } catch (IOException e) { 50 | logger.error("Read EasyBackup properties file ["+EasyBackup.getPropertiesFile().getName()+"] error.",e ); 51 | } 52 | }else{ 53 | logger.error("easybackup.properties file not found."); 54 | } 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/sender/Sender.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.sender; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 7 | 8 | /** 9 | * EasyBackup Sender 10 | * @author easyproject.cn 11 | * 12 | * @since 1.0.0 13 | */ 14 | public interface Sender { 15 | public void send(File targetFile,List backupFiles, BackupConfiguration configuration); 16 | } 17 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/sender/mail/MailSender.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.sender.mail; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.util.Arrays; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Properties; 10 | 11 | import javax.mail.MessagingException; 12 | import javax.mail.internet.MimeMessage; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.mail.MailException; 17 | import org.springframework.mail.javamail.JavaMailSenderImpl; 18 | import org.springframework.mail.javamail.MimeMessageHelper; 19 | import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; 20 | import org.springframework.util.FileSystemUtils; 21 | 22 | import cn.easyproject.easybackup.configuration.BackupConfiguration; 23 | import cn.easyproject.easybackup.sender.Sender; 24 | import cn.easyproject.easybackup.util.CompressFileUtil; 25 | import cn.easyproject.easybackup.util.EasyUtil; 26 | import freemarker.cache.ClassTemplateLoader; 27 | import freemarker.cache.FileTemplateLoader; 28 | import freemarker.cache.MultiTemplateLoader; 29 | import freemarker.cache.TemplateLoader; 30 | import freemarker.template.Configuration; 31 | import freemarker.template.Template; 32 | import freemarker.template.TemplateException; 33 | import freemarker.template.TemplateExceptionHandler; 34 | /** 35 | * EasyBackup MailSender 36 | * @author easyproject.cn 37 | * 38 | * @since 1.0.0 39 | */ 40 | public class MailSender implements Sender { 41 | 42 | static Logger logger = LoggerFactory.getLogger(MailSender.class); 43 | 44 | private static Configuration freemarkerConfiguration ; 45 | 46 | 47 | /** 48 | * 加载默认的 Freemarker 配置文件 49 | */ 50 | private void loadFreemarkerConfiguration(){ 51 | // 加载默认的 Freemarker 配置文件 52 | if(freemarkerConfiguration==null){ 53 | freemarkerConfiguration= new Configuration(Configuration.VERSION_2_3_23); 54 | freemarkerConfiguration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); 55 | freemarkerConfiguration.setDefaultEncoding("UTF-8"); 56 | try { 57 | FileTemplateLoader ftl1 = new FileTemplateLoader(new File("template")); 58 | ClassTemplateLoader ctl = new ClassTemplateLoader(MailSender.class, "/template"); 59 | TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ctl }; 60 | MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); 61 | freemarkerConfiguration.setTemplateLoader(mtl); 62 | } catch (IOException e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | 68 | 69 | 70 | private JavaMailSenderImpl sender = new JavaMailSenderImpl(); 71 | 72 | public void send(File targetFile,List backupFiles, BackupConfiguration configuration) { 73 | loadFreemarkerConfiguration(); 74 | System.out.println(configuration.getMailSender()); 75 | System.out.println(Arrays.toString(configuration.getMailReceiver())); 76 | System.out.println(configuration.getMailReceiver().length); 77 | 78 | if(!EasyUtil.isNotEmpty(configuration.getMailSender())||configuration.getMailReceiver()==null||configuration.getMailReceiver().length==0){ 79 | logger.warn("You are not configuration Mail Sender or Receiver. Please Check your mail sender and recevier."); 80 | return; 81 | } 82 | 83 | 84 | try { 85 | 86 | logger.info(configuration.getType().name() + "-" + configuration.getName() 87 | + ", start send backup file ["+backupFiles+"] to mail[" + Arrays.toString(configuration.getMailReceiver()) + "]"); 88 | sender.setUsername(configuration.getMailSender()); 89 | sender.setPassword(configuration.getMailSenderPassword()); 90 | sender.setHost(configuration.getMailSenderHost()); 91 | sender.setPort(configuration.getMailSenderPort()); 92 | 93 | Properties senderProperties = new Properties(); 94 | senderProperties.setProperty("mail.smtp.auth", "true"); 95 | if (configuration.getMailSenderSsl()) { 96 | senderProperties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 97 | } 98 | sender.setJavaMailProperties(senderProperties); 99 | 100 | // SimpleMailMessage smm=new SimpleMailMessage(); 101 | MimeMessage mm = sender.createMimeMessage(); 102 | MimeMessageHelper smm = new MimeMessageHelper(mm, true,"utf-8");// 设置true,multipart消息 103 | 104 | smm.setFrom(configuration.getMailSender()); // 发件人,必须和Spring中配置的sender的名字保持一致 105 | smm.setTo(configuration.getMailReceiver()); // 收件人 106 | smm.setReplyTo(configuration.getMailSender()); // 回复地址,当点击回复的时候会回复到该地址 107 | smm.setSubject(configuration.getMailSenderTitle()); // 主题 108 | 109 | 110 | Template template = freemarkerConfiguration.getTemplate(configuration.getMailSenderTemplate()); 111 | 112 | 113 | 114 | Map data = new HashMap(); // 通过Map传递动态数据 115 | // 动态数据的名字和模板标签中指定属性相匹配 116 | data.put("targetFileName", targetFile.getName()); 117 | data.put("backupFileName",configuration.getLastBackupFileName()); 118 | data.put("type", configuration.getType().name()); 119 | data.put("name", configuration.getName()); 120 | data.put("value", configuration.getValue()); 121 | data.put("backuptime", configuration.getLastBackupTime()); 122 | data.put("backupConfiguration", configuration); 123 | 124 | // 解析模板并替换动态数据,产生最终的内容 125 | String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, data); 126 | smm.setText(text, true); // 内容 127 | 128 | File backupFile=backupFiles.get(0); 129 | 130 | if(backupFile.isFile()){ 131 | smm.addAttachment(backupFile.getName(), backupFile); 132 | sender.send(mm); //发送 133 | }else{ 134 | File zipFile=new File(backupFile.getParent(),backupFile.getName()+".zip"); 135 | CompressFileUtil.compressToZip(backupFile, zipFile); 136 | smm.addAttachment(zipFile.getName(), zipFile); 137 | sender.send(mm); //发送 138 | zipFile.delete(); 139 | } 140 | 141 | 142 | // mail.delete.backup 143 | if(configuration.getMailDeleteBackup()){ 144 | logger.info(configuration.getType().name() 145 | + 146 | "-" 147 | + configuration.getName() 148 | + " send over, delete backup file." 149 | ); 150 | FileSystemUtils.deleteRecursively(backupFile); 151 | } 152 | 153 | 154 | logger.info(configuration.getType().name() 155 | + 156 | "-" 157 | + configuration.getName() 158 | + " already send mail to [" + Arrays.toString(configuration.getMailReceiver())+"." 159 | + " last backup file name: "+configuration.getLastBackupFileName() 160 | + ", last backup file time: "+configuration.getLastBackupTime() 161 | + ", last backup file result: "+configuration.isLastBackupResult() 162 | ); 163 | } catch (MailException e) { 164 | logger.error(configuration.getType().name() + "-" + configuration.getName() 165 | + " send mail error, please check you sender configuration", e); 166 | } catch (MessagingException e) { 167 | logger.error(configuration.getType().name() + "-" + configuration.getName() 168 | + " send mail error, please check you sender configuration", e); 169 | } catch (IOException e) { 170 | logger.error(configuration.getType().name() + "-" + configuration.getName() 171 | + " send mail error, please check you sender configuration", e); 172 | } catch (TemplateException e) { 173 | logger.error(configuration.getType().name() + "-" + configuration.getName() 174 | + " send mail template error, please check you mail.tpl configuration", e); 175 | } catch (Exception e) { 176 | logger.error(configuration.getType().name() + "-" + configuration.getName() 177 | + " send mail error, please check you sender configuration", e); 178 | } 179 | 180 | } 181 | /** 182 | * 设置默认的 freemarker 模板配置文件 183 | * @param freemarkerConfiguration 设置默认的 freemarker 模板配置文件 184 | */ 185 | public static void setFreemarkerConfiguration(Configuration freemarkerConfiguration) { 186 | MailSender.freemarkerConfiguration = freemarkerConfiguration; 187 | } 188 | 189 | 190 | } 191 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/util/CompressFileUtil.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.util; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.util.Enumeration; 10 | 11 | import org.apache.commons.compress.archivers.ArchiveStreamFactory; 12 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 13 | import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; 14 | import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; 15 | import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; 16 | import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; 17 | import org.apache.commons.compress.archivers.zip.ZipFile; 18 | import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 19 | import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; 20 | import org.apache.commons.compress.utils.IOUtils; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * CompressFile Util 26 | * @author easyproject.cn 27 | * 28 | * @since 1.0.0 29 | */ 30 | public class CompressFileUtil { 31 | /** 32 | * Logger for this class 33 | */ 34 | private static final Logger logger = LoggerFactory.getLogger(CompressFileUtil.class); 35 | 36 | 37 | /** 38 | * Compress File 39 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 40 | * @param srcFile source file 41 | * @param compressFile compress file 42 | * @param encoding encoding 43 | * @return compress result 44 | */ 45 | public static boolean compress(String compressType,File srcFile, File compressFile, String encoding){ 46 | compressType=compressType.toUpperCase(); 47 | if(compressType.equals("ZIP")){ 48 | return compressToZip(srcFile, compressFile); 49 | }else if(compressType.equals("TAR")){ 50 | return compressToTar(srcFile, compressFile, encoding); 51 | }else if(compressType.equals("GZIP")||compressType.equals("TAR.GZ")){ 52 | return compressToGzip(srcFile, compressFile, encoding); 53 | }else{ 54 | throw new RuntimeException("compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz)"); 55 | } 56 | } 57 | /** 58 | * Compress File 59 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 60 | * @param srcFile source file 61 | * @param compressFile compress file 62 | * @return compress result 63 | */ 64 | public static boolean compress(String compressType,File srcFile, File compressFile){ 65 | return compress(compressType, srcFile, compressFile, null); 66 | } 67 | 68 | 69 | /** 70 | * 将新文件添加进压缩的TAR文件 71 | * 72 | * @param newFile 73 | * 新文件 74 | * @param tarFile 75 | * 压缩TAR文件 76 | * @return 是否压缩成功 77 | */ 78 | public static boolean addNewFileToGzip(File newFile, File tarFile) { 79 | return addNewFileToGzip(newFile, tarFile, null); 80 | } 81 | 82 | /** 83 | * 将新文件添加进压缩的TAR文件 84 | * 85 | * @param newFile 86 | * 新文件 87 | * @param gzipFile 88 | * 压缩GZIP文件 89 | * @param encoding 90 | * 压缩编码 91 | * @return 是否压缩成功 92 | */ 93 | public static boolean addNewFileToGzip(File newFile, File gzipFile, String encoding) { 94 | boolean res = false; 95 | 96 | // 创建压缩临时文件 97 | File temp_file = new File(gzipFile.getParent(), gzipFile.getName()+".temp" ); 98 | 99 | while (temp_file.exists()) { // 存在同名文件则重新创建 100 | String temp_file_name = temp_file.getName()+".temp"; 101 | temp_file = new File(gzipFile.getParent(), temp_file_name); 102 | } 103 | 104 | TarArchiveOutputStream tos = null; 105 | TarArchiveInputStream in = null; 106 | BufferedInputStream bis=null; 107 | boolean flag = false; 108 | try { 109 | 110 | if (encoding != null && (!encoding.equals(""))) { 111 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(temp_file))), encoding); 112 | in = new TarArchiveInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(gzipFile))), encoding); 113 | } else { 114 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(temp_file)))); 115 | in = new TarArchiveInputStream(new GzipCompressorInputStream(new BufferedInputStream(new FileInputStream(gzipFile)))); 116 | } 117 | tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 118 | 119 | TarArchiveEntry zae = null; 120 | 121 | while ((zae = in.getNextTarEntry()) != null) { 122 | 123 | tos.putArchiveEntry(zae); 124 | if (!zae.isDirectory()) { 125 | 126 | IOUtils.copy(in, tos); // 3写入 127 | } 128 | tos.closeArchiveEntry(); 129 | } 130 | 131 | /* 132 | * 追加压缩文件 133 | */ 134 | if (newFile.isDirectory()) { // 压缩目录 135 | tarDirectory(tos, newFile, newFile.getAbsolutePath()); 136 | } else { // 压缩文件 137 | zae = new TarArchiveEntry(newFile.getName());// 1创建 138 | zae.setSize(newFile.length()); 139 | tos.putArchiveEntry(zae); // 2放入 140 | bis=new BufferedInputStream(new FileInputStream(newFile)); 141 | IOUtils.copy(bis, tos); // 3写入 142 | tos.closeArchiveEntry(); // 4关闭 143 | bis.close(); 144 | } 145 | flag = true; 146 | } catch (Exception e) { 147 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 148 | } finally { 149 | if(bis!=null){ 150 | try { 151 | bis.close(); 152 | } catch (IOException e) { 153 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 154 | } 155 | } 156 | if (in != null) { 157 | try { 158 | in.close(); // 关闭流 159 | } catch (Exception e) { 160 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 161 | } 162 | } 163 | if (tos != null) { 164 | try { 165 | tos.close(); // 关闭流 166 | } catch (Exception e) { 167 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 168 | } 169 | } 170 | 171 | } 172 | 173 | if (flag) { 174 | gzipFile.delete(); // 删除源压缩文件 175 | temp_file.renameTo(gzipFile); // 重命名回原压缩文件名 176 | res = true; 177 | }else{ 178 | temp_file.delete(); 179 | } 180 | return res; 181 | } 182 | 183 | 184 | /** 185 | * 将新文件添加进压缩的TAR文件 186 | * 187 | * @param newFile 188 | * 新文件 189 | * @param tarFile 190 | * 压缩TAR文件 191 | * @return 是否压缩成功 192 | */ 193 | public static boolean addNewFileToTar(File newFile, File tarFile) { 194 | return addNewFileToTar(newFile, tarFile, null); 195 | } 196 | 197 | 198 | /** 199 | * 将新文件添加进压缩的TAR文件 200 | * 201 | * @param newFile 202 | * 新文件 203 | * @param tarFile 204 | * 压缩TAR文件 205 | * @param encoding 206 | * 压缩编码 207 | * @return 是否压缩成功 208 | */ 209 | public static boolean addNewFileToTar(File newFile, File tarFile, String encoding) { 210 | boolean res = false; 211 | 212 | // 创建压缩临时文件 213 | File temp_file = new File(tarFile.getParent(), tarFile.getName()+".temp" ); 214 | 215 | while (temp_file.exists()) { // 存在同名文件则重新创建 216 | String temp_file_name = temp_file.getName()+".temp"; 217 | temp_file = new File(tarFile.getParent(), temp_file_name); 218 | } 219 | 220 | TarArchiveOutputStream tos = null; 221 | TarArchiveInputStream in = null; 222 | BufferedInputStream bis=null; 223 | boolean flag = false; 224 | try { 225 | 226 | if (encoding != null && (!encoding.equals(""))) { 227 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(temp_file)), encoding); 228 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile)), encoding); 229 | } else { 230 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(temp_file))); 231 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile))); 232 | } 233 | tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 234 | 235 | TarArchiveEntry zae = null; 236 | 237 | while ((zae = in.getNextTarEntry()) != null) { 238 | 239 | tos.putArchiveEntry(zae); 240 | if (!zae.isDirectory()) { 241 | 242 | IOUtils.copy(in, tos); // 3写入 243 | } 244 | tos.closeArchiveEntry(); 245 | } 246 | 247 | /* 248 | * 追加压缩文件 249 | */ 250 | if (newFile.isDirectory()) { // 压缩目录 251 | tarDirectory(tos, newFile, newFile.getAbsolutePath()); 252 | } else { // 压缩文件 253 | zae = new TarArchiveEntry(newFile.getName());// 1创建 254 | zae.setSize(newFile.length()); 255 | tos.putArchiveEntry(zae); // 2放入 256 | bis=new BufferedInputStream(new FileInputStream(newFile)); 257 | IOUtils.copy(bis, tos); // 3写入 258 | tos.closeArchiveEntry(); // 4关闭 259 | } 260 | 261 | flag = true; 262 | } catch (Exception e) { 263 | logger.error("addNewFileToTar error.", e); //$NON-NLS-1$ 264 | } finally { 265 | if(bis!=null){ 266 | try { 267 | bis.close(); 268 | } catch (IOException e) { 269 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 270 | } 271 | } 272 | if (in != null) { 273 | try { 274 | in.close(); // 关闭流 275 | } catch (Exception e) { 276 | logger.error("addNewFileToTar error.", e); //$NON-NLS-1$ 277 | } 278 | } 279 | if (tos != null) { 280 | try { 281 | tos.close(); // 关闭流 282 | } catch (Exception e) { 283 | logger.error("addNewFileToTar error.", e); //$NON-NLS-1$ 284 | } 285 | } 286 | 287 | } 288 | 289 | if (flag) { 290 | tarFile.delete(); // 删除源压缩文件 291 | temp_file.renameTo(tarFile); // 重命名回原压缩文件名 292 | res = true; 293 | }else{ 294 | temp_file.delete(); 295 | } 296 | return res; 297 | } 298 | 299 | /** 300 | * 将新文件添加进压缩的ZIP文件 301 | * 302 | * @param newFile 303 | * 新文件 304 | * @param zipFile 305 | * 压缩ZIP文件 306 | * @return whether success 307 | */ 308 | public static boolean addNewFileToZip(File newFile, File zipFile) { 309 | boolean res=false; 310 | // 创建压缩临时文件 311 | File temp_file = new File(zipFile.getParent(),zipFile.getName()+".temp"); 312 | 313 | while (temp_file.exists()) { // 存在同名文件则重新创建 314 | String temp_file_name = temp_file.getName()+".temp"; 315 | temp_file = new File(zipFile.getParent(), temp_file_name); 316 | } 317 | ZipFile zf = null; //ZipFile对象用来提取文件 318 | 319 | ZipArchiveOutputStream zos = null; //压缩输出 320 | BufferedInputStream bis=null; 321 | boolean flag=false; 322 | try { 323 | zf = new ZipFile(zipFile); // 获得zip文件 324 | zos = new ZipArchiveOutputStream(temp_file); 325 | Enumeration ze = zf.getEntries(); //获得所有压缩选项 326 | 327 | /* 328 | * 写入源压缩条目 329 | */ 330 | while (ze.hasMoreElements()) { //循环写出压缩文件 331 | ZipArchiveEntry zae = ze.nextElement(); 332 | zos.putArchiveEntry(zae); 333 | if (!zae.isDirectory()) { 334 | IOUtils.copy(zf.getInputStream(zae), zos); // 3写入 335 | } 336 | zos.closeArchiveEntry(); // 4关闭 337 | } 338 | /* 339 | * 追加压缩文件 340 | */ 341 | if (newFile.isDirectory()) { // 压缩目录 342 | zipDirectory(zos, newFile, newFile.getAbsolutePath()); 343 | } else { // 压缩文件 344 | ZipArchiveEntry zae = new ZipArchiveEntry(newFile.getName());// 1创建 345 | zos.putArchiveEntry(zae); // 2放入 346 | bis=new BufferedInputStream(new FileInputStream(newFile)); 347 | IOUtils.copy(bis, zos); // 3写入 348 | zos.closeArchiveEntry(); // 4关闭 349 | } 350 | 351 | flag=true; 352 | } catch (Exception e) { 353 | logger.error("addNewFileToZip error.", e); //$NON-NLS-1$ 354 | } finally { 355 | if(bis!=null){ 356 | try { 357 | bis.close(); 358 | } catch (IOException e) { 359 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 360 | } 361 | } 362 | if(zf!=null){ 363 | try{ 364 | zf.close(); // 关闭流 365 | }catch (Exception e) { 366 | logger.error("addNewFileToZip error.", e); //$NON-NLS-1$ 367 | } 368 | } 369 | if(zos!=null){ 370 | try{ 371 | zos.close(); // 关闭流 372 | }catch (Exception e) { 373 | logger.error("addNewFileToZip error.", e); //$NON-NLS-1$ 374 | } 375 | } 376 | 377 | } 378 | 379 | if(flag){ 380 | zipFile.delete(); // 删除源压缩文件 381 | temp_file.renameTo(zipFile); // 重命名回原压缩文件名 382 | res=true; 383 | }else{ 384 | temp_file.delete(); 385 | } 386 | return res; 387 | } 388 | 389 | 390 | 391 | /** 392 | * 将文件或目录压缩为TAR文件,输出到tarfile指定的压缩文件 393 | * 394 | * @param srcFile 395 | * 源文件或目录路径 396 | * @param gzipFile 397 | * 压缩后的文件 398 | * 399 | * @return 是否压缩成功 400 | */ 401 | public static boolean compressToGzip(File srcFile, File gzipFile) { 402 | return compressToGzip(srcFile, gzipFile, null); 403 | } 404 | 405 | 406 | /** 407 | * 将文件或目录压缩为TAR文件,输出到tarfile指定的压缩文件 408 | * 409 | * @param srcFile 410 | * 源文件或目录路径 411 | * @param gzipFile 412 | * 压缩后的文件 413 | * @param encoding 414 | * 压缩编码 415 | * 416 | * @return 是否压缩成功 417 | */ 418 | public static boolean compressToGzip(File srcFile, File gzipFile, String encoding) { 419 | boolean res = false; 420 | // 如果没有设置压缩文件名则使用文件或目录名作为压缩名 421 | TarArchiveOutputStream tos = null; 422 | BufferedInputStream bis=null; 423 | try { 424 | // 自动创建压缩文件目录 425 | if (!gzipFile.getParentFile().exists()) { 426 | gzipFile.getParentFile().mkdirs(); 427 | } 428 | if (encoding != null && (!encoding.equals(""))) { 429 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(gzipFile))), encoding); 430 | } else { 431 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(gzipFile)))); 432 | } 433 | 434 | tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 435 | if (srcFile.isDirectory()) { // 压缩目录 436 | tarDirectory(tos, srcFile, srcFile.getAbsolutePath()); 437 | } else { // 压缩文件 438 | TarArchiveEntry zae = new TarArchiveEntry(srcFile.getName());// 1创建 439 | zae.setSize(srcFile.length()); 440 | tos.putArchiveEntry(zae); // 2放入 441 | bis=new BufferedInputStream(new FileInputStream(srcFile)); 442 | 443 | IOUtils.copy(bis, tos); // 3写入 444 | 445 | tos.closeArchiveEntry(); // 4关闭 446 | } 447 | res = true; 448 | 449 | } catch (Exception e) { 450 | logger.error("compressToGzip error.", e); //$NON-NLS-1$ 451 | } finally { 452 | if(bis!=null){ 453 | try { 454 | bis.close(); 455 | } catch (IOException e) { 456 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 457 | } 458 | } 459 | if (tos != null) { 460 | 461 | try { 462 | tos.close(); 463 | } catch (Exception e2) { 464 | logger.error("compressToGzip error."); //$NON-NLS-1$ 465 | } 466 | } 467 | } 468 | 469 | return res; 470 | 471 | } 472 | 473 | /** 474 | * 将文件或目录压缩为TAR文件 475 | * 476 | * @param srcFile 477 | * 源文件或目录路径 478 | * @param tarFile 479 | * 压缩后的文件 480 | * 481 | * @return 是否压缩成功 482 | */ 483 | public static boolean compressToTar(File srcFile, File tarFile) { 484 | return compressToTar(srcFile, tarFile, null); 485 | } 486 | 487 | /** 488 | * 将文件或目录压缩为TAR文件,输出到tarfile指定的压缩文件 489 | * 490 | * @param srcFile 491 | * 源文件或目录路径 492 | * @param tarFile 493 | * 压缩后的文件 494 | * @param encoding 495 | * 压缩编码 496 | * 497 | * @return 是否压缩成功 498 | */ 499 | public static boolean compressToTar(File srcFile, File tarFile, String encoding) { 500 | boolean res = false; 501 | // 如果没有设置压缩文件名则使用文件或目录名作为压缩名 502 | TarArchiveOutputStream tos = null; 503 | BufferedInputStream bis=null; 504 | 505 | try { 506 | // 自动创建压缩文件目录 507 | if (!tarFile.getParentFile().exists()) { 508 | tarFile.getParentFile().mkdirs(); 509 | } 510 | if (encoding != null && (!encoding.equals(""))) { 511 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(tarFile)), encoding); 512 | } else { 513 | 514 | tos = new TarArchiveOutputStream(new BufferedOutputStream(new FileOutputStream(tarFile))); 515 | } 516 | 517 | tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); 518 | if (srcFile.isDirectory()) { // 压缩目录 519 | tarDirectory(tos, srcFile, srcFile.getAbsolutePath()); 520 | } else { // 压缩文件 521 | TarArchiveEntry zae = new TarArchiveEntry(srcFile.getName());// 1创建 522 | zae.setSize(srcFile.length()); 523 | tos.putArchiveEntry(zae); // 2放入 524 | bis=new BufferedInputStream(new FileInputStream(srcFile)); 525 | 526 | IOUtils.copy(bis, tos); // 3写入 527 | 528 | tos.closeArchiveEntry(); // 4关闭 529 | } 530 | res = true; 531 | 532 | } catch (Exception e) { 533 | logger.error("compressToTar error.", e); //$NON-NLS-1$ 534 | } finally { 535 | if(bis!=null){ 536 | try { 537 | bis.close(); 538 | } catch (IOException e) { 539 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 540 | } 541 | } 542 | if (tos != null) { 543 | 544 | try { 545 | tos.close(); 546 | } catch (Exception e2) { 547 | logger.error("compressToTar error."); //$NON-NLS-1$ 548 | } 549 | } 550 | } 551 | 552 | return res; 553 | } 554 | 555 | 556 | 557 | 558 | 559 | /** 560 | * 将文件或目录压缩为ZIP文件 561 | * @param srcFile 源文件或目录路径 562 | * @param zipFile 压缩后的文件 563 | * @return 是否压缩成功 564 | */ 565 | public static boolean compressToZip(File srcFile, File zipFile) { 566 | boolean res = false; 567 | 568 | // 如果没有设置压缩文件名则使用文件或目录名作为压缩名 569 | 570 | ZipArchiveOutputStream zos = null; 571 | BufferedInputStream bis=null; 572 | 573 | try { 574 | 575 | // 自动创建压缩文件目录 576 | if (!zipFile.getParentFile().exists()) { 577 | zipFile.getParentFile().mkdirs(); 578 | } 579 | 580 | zos = (ZipArchiveOutputStream) new ArchiveStreamFactory() 581 | .createArchiveOutputStream(ArchiveStreamFactory.ZIP, new BufferedOutputStream(new FileOutputStream(zipFile))); 582 | 583 | if (srcFile.isDirectory()) { // 压缩目录 584 | zipDirectory(zos, srcFile, srcFile.getAbsolutePath()); 585 | } else { // 压缩文件 586 | ZipArchiveEntry zae = new ZipArchiveEntry(srcFile.getName());// 1创建 587 | zos.putArchiveEntry(zae); // 2放入 588 | bis=new BufferedInputStream(new FileInputStream(srcFile)); 589 | 590 | IOUtils.copy(bis, zos); // 3写入 591 | 592 | zos.closeArchiveEntry(); // 4关闭 593 | } 594 | 595 | res=true; 596 | } catch (Exception e) { 597 | logger.error("compressToZip error.", e); //$NON-NLS-1$ 598 | } finally { 599 | if(bis!=null){ 600 | try { 601 | bis.close(); 602 | } catch (IOException e) { 603 | logger.error("addNewFileToGzip error.", e); //$NON-NLS-1$ 604 | } 605 | } 606 | if (zos != null) { 607 | 608 | try { 609 | zos.close(); 610 | } catch (Exception e2) { 611 | logger.error("compressToZip error."); //$NON-NLS-1$ 612 | } 613 | } 614 | } 615 | 616 | return res; 617 | } 618 | 619 | /** 620 | * 内部调用——将目录压缩文件为TAR格式(递归方法) 621 | * 622 | * @param zos 623 | * 压缩输出流对象 624 | * @param file 625 | * 压缩的文件或目录 626 | * @param rootpath 627 | * 被压缩的根目录路径(绝对路径) 628 | * @throws IOException 629 | * 异常 630 | */ 631 | private static void tarDirectory(TarArchiveOutputStream zos, File file, String rootpath) throws IOException { 632 | if (file.isDirectory()) { // 如果是目录继续递归 633 | /* 634 | * 如果不需要将空目录写出,则无需下面的写出代码部分(写出文件时会自动创建相应目录) 635 | */ 636 | String nowfileName = file.getAbsolutePath().replace(rootpath, ""); 637 | if (!nowfileName.equals("")) {// 操作非根目录,根目录不需要写 638 | String entryName = nowfileName.substring(1) + File.separator; 639 | TarArchiveEntry tae = new TarArchiveEntry(file, entryName);// 1创建(必须加入文件对象,否则会当做空文件写入) 640 | try { 641 | 642 | tae.setSize(file.length()); 643 | zos.putArchiveEntry(tae); // 2放入 644 | // 3创建目录无需数据写入操作 645 | zos.closeArchiveEntry(); // 4关闭 646 | } catch (Exception e) { 647 | logger.error("tarDirectory error.", e); //$NON-NLS-1$ 648 | } 649 | } 650 | String[] list = file.list(); 651 | for (String f : list) { 652 | tarDirectory(zos, new File(file, f), rootpath); 653 | } 654 | } else { // 如果是文件夹,压缩进压缩文件输出流 655 | String entryName = file.getAbsolutePath().replace(rootpath + File.separator, ""); 656 | TarArchiveEntry tae = new TarArchiveEntry(entryName);// 1创建 657 | 658 | tae.setSize(file.length()); 659 | zos.putArchiveEntry(tae); // 2放入 660 | BufferedInputStream bis=null; 661 | try { 662 | bis=new BufferedInputStream(new FileInputStream(file)); 663 | IOUtils.copy(bis, zos); // 3写入 664 | } catch (IOException e) { 665 | throw e; 666 | }finally { 667 | if(bis!=null){ 668 | bis.close(); 669 | } 670 | } 671 | 672 | zos.closeArchiveEntry(); // 4关闭 673 | } 674 | } 675 | 676 | 677 | /** 678 | * 内部调用——将目录或文件压缩文件为zip格式(递归方法) 679 | * 680 | * @param zos 681 | * 压缩输出流对象 682 | * @param file 683 | * 压缩的文件或目录 684 | * @param rootpath 685 | * 被压缩的根目录路径(绝对路径) 686 | */ 687 | private static void zipDirectory(ZipArchiveOutputStream zos, File file, 688 | String rootpath) { 689 | if (file.isDirectory()) { // 如果是目录继续递归 690 | /* 691 | * 如果不需要将空目录写出,则无需下面的写出代码部分(写出文件时会自动创建相应目录) 692 | */ 693 | String nowfileName = file.getAbsolutePath().replace(rootpath, ""); 694 | if (!nowfileName.equals("")) {// 操作非根目录,根目录不需要写 695 | String entryName = nowfileName.substring(1) + File.separator; 696 | ZipArchiveEntry zae = new ZipArchiveEntry(file, entryName);// 1创建(必须加入文件对象,否则会当做空文件写入) 697 | try { 698 | zos.putArchiveEntry(zae); // 2放入 699 | // 3创建目录无需数据写入操作 700 | zos.closeArchiveEntry(); // 4关闭 701 | } catch (Exception e) { 702 | logger.error("tarDirectory error.", e); //$NON-NLS-1$ 703 | } 704 | } 705 | String[] list = file.list(); 706 | for (String f : list) { 707 | zipDirectory(zos, new File(file, f), rootpath); 708 | } 709 | } else { // 如果是文件夹,压缩进压缩文件输出流 710 | String entryName = file.getAbsolutePath().replace( 711 | rootpath + File.separator, ""); 712 | ZipArchiveEntry zae = new ZipArchiveEntry(entryName);// 1创建 713 | try { 714 | zos.putArchiveEntry(zae); // 2放入 715 | BufferedInputStream bis=null; 716 | try { 717 | bis=new BufferedInputStream(new FileInputStream(file)); 718 | IOUtils.copy(bis, zos); // 3写入 719 | } catch (IOException e) { 720 | throw e; 721 | }finally { 722 | if(bis!=null){ 723 | bis.close(); 724 | } 725 | } 726 | 727 | zos.closeArchiveEntry(); // 4关闭 728 | } catch (Exception e) { 729 | logger.error("tarDirectory error.", e); //$NON-NLS-1$ 730 | } 731 | } 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/util/DecompressFileUtil.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.util; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.BufferedOutputStream; 5 | import java.io.File; 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.OutputStream; 9 | 10 | import org.apache.commons.compress.archivers.ArchiveInputStream; 11 | import org.apache.commons.compress.archivers.ArchiveStreamFactory; 12 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 13 | import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; 14 | import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; 15 | import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 16 | import org.apache.commons.compress.utils.IOUtils; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | /** 20 | * DecompressFile Util 21 | * @author easyproject.cn 22 | * 23 | * @since 1.0.0 24 | */ 25 | public class DecompressFileUtil { 26 | /** 27 | * Logger for this class 28 | */ 29 | private static final Logger logger = LoggerFactory.getLogger(DecompressFileUtil.class); 30 | 31 | /** 32 | * Decompres 33 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 34 | * @param compressFile compress file 35 | * @param outDir output directory 36 | * @param encoding encoding 37 | * @return decompress result 38 | */ 39 | public static boolean decompress(String compressType,File compressFile,File outDir, String encoding){ 40 | compressType=compressType.toUpperCase(); 41 | if(compressType.equals("ZIP")){ 42 | if(outDir!=null){ 43 | return decompressZip(compressFile, outDir); 44 | }else{ 45 | return decompressZip(compressFile); 46 | } 47 | 48 | }else if(compressType.equals("TAR")){ 49 | if(outDir!=null){ 50 | return decompressTar(compressFile, outDir, encoding); 51 | }else{ 52 | return decompressTar(compressFile, encoding); 53 | } 54 | }else if(compressType.equals("GZIP")||compressType.equals("TAR.GZ")){ 55 | if(outDir!=null){ 56 | return decompressGzip(compressFile, outDir, encoding); 57 | }else{ 58 | return decompressGzip(compressFile, encoding); 59 | } 60 | }else{ 61 | throw new RuntimeException("compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz)"); 62 | } 63 | } 64 | /** 65 | * Decompres 66 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 67 | * @param compressFile compress file 68 | * @param outDir output directory 69 | * @return decompress result 70 | */ 71 | public static boolean decompress(String compressType,File compressFile,File outDir){ 72 | return decompress(compressType, compressFile, outDir, null); 73 | } 74 | 75 | /** 76 | * Decompres 77 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 78 | * @param compressFile compress file 79 | * @param encoding encoding 80 | * @return decompress result 81 | */ 82 | public static boolean decompress(String compressType,File compressFile, String encoding){ 83 | return decompress(compressType, compressFile, null, encoding); 84 | } 85 | 86 | /** 87 | * Decompres 88 | * @param compressType must in: TAR(*.tar), ZIP(*.zip), GZIP(*.tar.gz) 89 | * @param compressFile compress file 90 | * @return decompress result 91 | */ 92 | public static boolean decompress(String compressType,File compressFile){ 93 | return decompress(compressType, compressFile, null, null); 94 | } 95 | 96 | 97 | /** 98 | * Decompress gzip file 99 | * @param gzipFile gzip file 100 | * @return whether success 101 | */ 102 | public static boolean decompressGzip(File gzipFile) { 103 | return decompressGzip(gzipFile, ""); 104 | } 105 | /** 106 | * decompress gzip file 107 | * @param gzipFile gzipFile 108 | * @param outDir output directory 109 | * @return whether success 110 | */ 111 | public static boolean decompressGzip(File gzipFile, File outDir) { 112 | return decompressGzip(gzipFile, outDir, ""); 113 | } 114 | 115 | /** 116 | * decompress gzip file 117 | * @param gzipFile Compression File 118 | * @param outDir output directory 119 | * @param encoding compression encoding 120 | * @return whether success 121 | */ 122 | @SuppressWarnings("unused") 123 | public static boolean decompressGzip(File gzipFile, File outDir, String encoding) { 124 | boolean res = false; 125 | // 获取压缩文件名称,不带后缀 126 | String outFileName = gzipFile.getName(); 127 | if (gzipFile.getName().lastIndexOf(".") != -1) { 128 | outFileName = gzipFile.getName().substring(0, gzipFile.getName().lastIndexOf(".")); 129 | } 130 | 131 | // 判断目录是否有文件存在,冲突 132 | if(outDir.isFile()){ 133 | logger.error(outDir.getAbsolutePath()+" exists a file!"); 134 | return false; 135 | } 136 | 137 | // 创建解压目录 138 | if (!outDir.exists()) { 139 | outDir.mkdirs(); 140 | } 141 | 142 | TarArchiveInputStream in = null; 143 | try { 144 | // 1、获得解压文件输入流 145 | if (encoding == null || encoding.equals("")) { 146 | in = new TarArchiveInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(gzipFile)))); 147 | } else { 148 | in = new TarArchiveInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(gzipFile))), encoding); 149 | } 150 | TarArchiveEntry zae = null; 151 | while ((zae = in.getNextTarEntry()) != null) { // 2、循环提取待解压的压缩条目 152 | File outFile = new File(outDir, zae.getName()); // 创建写出文件 153 | 154 | if (zae.isDirectory()) { // 如果是目录则无需写操作 155 | outFile.mkdirs(); 156 | continue; 157 | } 158 | 159 | outFile.getParentFile().mkdirs(); // 保证父目录创建 160 | OutputStream out = new FileOutputStream(outFile); 161 | IOUtils.copy(in, new BufferedOutputStream(out)); // 3、写出文件 162 | out.close(); 163 | } 164 | res=true; 165 | } catch (Exception e) { 166 | logger.error("decompressTar error.", e); //$NON-NLS-1$ 167 | } finally { 168 | if (in != null) { 169 | try { 170 | in.close(); 171 | } catch (Exception e) { 172 | logger.error("decompressTar error.", e); //$NON-NLS-1$ 173 | 174 | } 175 | } 176 | } 177 | return res; 178 | } 179 | /** 180 | * Decompress gzip file 181 | * @param gzipFile Compression File 182 | * @param encoding compression encoding 183 | * @return whether success 184 | */ 185 | public static boolean decompressGzip(File gzipFile, String encoding) { 186 | boolean res = false; 187 | 188 | TarArchiveInputStream in = null; 189 | try { 190 | // 1、获得解压文件输入流 191 | 192 | if (encoding == null || encoding.equals("")) { 193 | in = new TarArchiveInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(gzipFile)))); 194 | } else { 195 | in = new TarArchiveInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(gzipFile))), encoding); 196 | } 197 | TarArchiveEntry zae = null; 198 | while ((zae = in.getNextTarEntry()) != null) { // 2、循环提取待解压的压缩条目 199 | 200 | File outFile = new File(gzipFile.getParent(), zae.getName()); // 创建写出文件 201 | 202 | if (zae.isDirectory()) { // 如果是目录则无需写操作 203 | outFile.mkdirs(); 204 | continue; 205 | } 206 | 207 | outFile.getParentFile().mkdirs(); // 保证父目录创建 208 | OutputStream out = new FileOutputStream(outFile); 209 | IOUtils.copy(in, new BufferedOutputStream(out)); // 3、写出文件 210 | out.close(); 211 | } 212 | res=true; 213 | } catch (Exception e) { 214 | logger.error("decompress error. " + gzipFile.getAbsolutePath(), e); //$NON-NLS-1$ 215 | } finally { 216 | if (in != null) { 217 | try { 218 | in.close(); 219 | } catch (Exception e) { 220 | logger.error("decompress error. ", e); //$NON-NLS-1$ 221 | } 222 | } 223 | } 224 | 225 | return res; 226 | } 227 | 228 | /** 229 | * decompress tar file 230 | * @param tarFile Compression File 231 | * @return whether success 232 | */ 233 | public static boolean decompressTar(File tarFile) { 234 | return decompressTar(tarFile, ""); 235 | } 236 | /** 237 | * decompress tar file 238 | * @param tarFile Compression File 239 | * @param outDir output directory 240 | * @return Whether success 241 | */ 242 | public static boolean decompressTar(File tarFile, File outDir) { 243 | return decompressTar(tarFile, outDir, ""); 244 | } 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | /** 254 | * decompress tar file 255 | * @param tarFile Compression File 256 | * @param outDir output directory 257 | * @param encoding compression encoding 258 | * @return whether success 259 | */ 260 | @SuppressWarnings("unused") 261 | public static boolean decompressTar(File tarFile, File outDir, String encoding) { 262 | boolean res = false; 263 | // 获取压缩文件名称,不带后缀 264 | String outFileName = tarFile.getName(); 265 | if (tarFile.getName().lastIndexOf(".") != -1) { 266 | outFileName = tarFile.getName().substring(0, tarFile.getName().lastIndexOf(".")); 267 | } 268 | 269 | // 判断目录是否有文件存在,冲突 270 | if(outDir.isFile()){ 271 | logger.error(outDir.getAbsolutePath()+" exists a file!"); 272 | return false; 273 | } 274 | 275 | // 创建解压目录 276 | if (!outDir.exists()) { 277 | outDir.mkdirs(); 278 | } 279 | 280 | TarArchiveInputStream in = null; 281 | try { 282 | // 1、获得解压文件输入流 283 | if (encoding == null || encoding.equals("")) { 284 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile))); 285 | } else { 286 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile)), encoding); 287 | } 288 | TarArchiveEntry zae = null; 289 | while ((zae = in.getNextTarEntry()) != null) { // 2、循环提取待解压的压缩条目 290 | File outFile = new File(outDir, zae.getName()); // 创建写出文件 291 | 292 | if (zae.isDirectory()) { // 如果是目录则无需写操作 293 | outFile.mkdirs(); 294 | continue; 295 | } 296 | 297 | outFile.getParentFile().mkdirs(); // 保证父目录创建 298 | OutputStream out = new FileOutputStream(outFile); 299 | IOUtils.copy(in, out); // 3、写出文件 300 | out.close(); 301 | } 302 | res=true; 303 | } catch (Exception e) { 304 | logger.error("decompressTar error.", e); //$NON-NLS-1$ 305 | } finally { 306 | if (in != null) { 307 | try { 308 | in.close(); 309 | } catch (Exception e) { 310 | logger.error("decompressTar error.", e); //$NON-NLS-1$ 311 | 312 | } 313 | } 314 | } 315 | return res; 316 | } 317 | /** 318 | * decompress tar file 319 | * @param tarFile Compression File 320 | * @param encoding compression encoding 321 | * @return whether success 322 | */ 323 | public static boolean decompressTar(File tarFile, String encoding) { 324 | boolean res = false; 325 | 326 | TarArchiveInputStream in = null; 327 | try { 328 | // 1、获得解压文件输入流 329 | 330 | if (encoding == null || encoding.equals("")) { 331 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile))); 332 | } else { 333 | in = new TarArchiveInputStream(new BufferedInputStream(new FileInputStream(tarFile)), encoding); 334 | } 335 | TarArchiveEntry zae = null; 336 | while ((zae = in.getNextTarEntry()) != null) { // 2、循环提取待解压的压缩条目 337 | 338 | File outFile = new File(tarFile.getParent(), zae.getName()); // 创建写出文件 339 | 340 | if (zae.isDirectory()) { // 如果是目录则无需写操作 341 | outFile.mkdirs(); 342 | continue; 343 | } 344 | 345 | outFile.getParentFile().mkdirs(); // 保证父目录创建 346 | OutputStream out = new FileOutputStream(outFile); 347 | IOUtils.copy(in, out); // 3、写出文件 348 | out.close(); 349 | } 350 | res=true; 351 | } catch (Exception e) { 352 | logger.error("decompress error. " + tarFile.getAbsolutePath(), e); //$NON-NLS-1$ 353 | } finally { 354 | if (in != null) { 355 | try { 356 | in.close(); 357 | } catch (Exception e) { 358 | logger.error("decompress error. ", e); //$NON-NLS-1$ 359 | } 360 | } 361 | } 362 | 363 | return res; 364 | } 365 | 366 | /** 367 | * decompress zip file 368 | * @param zipFile Compression File 369 | * @return whether success 370 | */ 371 | public static boolean decompressZip(File zipFile) { 372 | boolean res = false; 373 | 374 | ArchiveInputStream in = null; 375 | try { 376 | // 1、获得解压文件输入流 377 | in = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, 378 | new BufferedInputStream(new FileInputStream(zipFile))); 379 | ZipArchiveEntry zae = null; 380 | while ((zae = (ZipArchiveEntry) in.getNextEntry()) != null) { // 2、循环提取待解压的压缩条目 381 | 382 | File outFile = new File(zipFile.getParent(), zae.getName()); // 创建写出文件 383 | 384 | if (zae.isDirectory()) { // 如果是目录则无需写操作 385 | outFile.mkdirs(); 386 | continue; 387 | } 388 | 389 | outFile.getParentFile().mkdirs(); // 保证父目录创建 390 | OutputStream out = new FileOutputStream(outFile); 391 | IOUtils.copy(in, new BufferedOutputStream(out)); // 3、写出文件 392 | out.close(); 393 | } 394 | res=true; 395 | } catch (Exception e) { 396 | logger.error("decompressZip error.", e); //$NON-NLS-1$ 397 | } finally { 398 | if (in != null) { 399 | try { 400 | in.close(); 401 | } catch (Exception e) { 402 | logger.error("decompressZip error.", e); //$NON-NLS-1$ 403 | } 404 | } 405 | } 406 | 407 | return res; 408 | } 409 | 410 | /** 411 | * decompress zip file 412 | * @param zipFile Compression File 413 | * @param outDir output directory 414 | * @return whether success 415 | */ 416 | @SuppressWarnings("unused") 417 | public static boolean decompressZip(File zipFile, File outDir) { 418 | boolean res = false; 419 | 420 | // 获取压缩文件名称,不带后缀 421 | String outFileName = zipFile.getName(); 422 | if (zipFile.getName().lastIndexOf(".") != -1) { 423 | outFileName = zipFile.getName().substring(0, zipFile.getName().lastIndexOf(".")); 424 | } 425 | 426 | // 判断目录是否有文件存在,冲突 427 | if(outDir.isFile()){ 428 | logger.error(outDir.getAbsolutePath()+" exists a file!"); 429 | return false; 430 | } 431 | 432 | // 创建解压目录 433 | if(!outDir.exists()){ 434 | outDir.mkdirs(); 435 | } 436 | 437 | ArchiveInputStream in = null; 438 | try { 439 | // 1、获得解压文件输入流 440 | in = new ArchiveStreamFactory().createArchiveInputStream(ArchiveStreamFactory.ZIP, 441 | new BufferedInputStream(new FileInputStream(zipFile))); 442 | ZipArchiveEntry zae = null; 443 | while ((zae = (ZipArchiveEntry) in.getNextEntry()) != null) { // 2、循环提取待解压的压缩条目 444 | File outFile = new File(outDir, zae.getName()); // 创建写出文件 445 | 446 | if (zae.isDirectory()) { // 如果是目录则无需写操作 447 | outFile.mkdirs(); 448 | continue; 449 | } 450 | 451 | outFile.getParentFile().mkdirs(); // 保证父目录创建 452 | OutputStream out = new FileOutputStream(outFile); 453 | IOUtils.copy(in, new BufferedOutputStream(out)); // 3、写出文件 454 | out.close(); 455 | } 456 | res=true; 457 | } catch (Exception e) { 458 | logger.error("decompressZip error.", e); //$NON-NLS-1$ 459 | } finally { 460 | if (in != null) { 461 | try { 462 | in.close(); 463 | } catch (Exception e) { 464 | logger.error("decompressZip error.", e); //$NON-NLS-1$ 465 | } 466 | } 467 | } 468 | return res; 469 | } 470 | 471 | 472 | 473 | } 474 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/util/EasyUtil.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.util; 2 | 3 | /** 4 | * Easy Util 5 | * @author easyproject.cn 6 | * 7 | * @since 1.0.0 8 | */ 9 | public class EasyUtil { 10 | 11 | public static boolean isTrue(String value) { 12 | if(value==null){ 13 | return false; 14 | } 15 | value=value.toLowerCase(); 16 | return value.equals("true") || 17 | value.equals("t") || 18 | value.equals("1") || 19 | value.equals("enabled") || 20 | value.equals("y") || 21 | value.equals("yes") || 22 | value.equals("on"); 23 | } 24 | 25 | 26 | public static boolean isNotEmpty(String str){ 27 | return !(str==null||str.trim().equals("")); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/util/FreemarkerUtil.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.util; 2 | 3 | import java.io.IOException; 4 | import java.io.StringWriter; 5 | import java.util.Map; 6 | 7 | import freemarker.cache.StringTemplateLoader; 8 | import freemarker.template.Configuration; 9 | import freemarker.template.Template; 10 | import freemarker.template.TemplateException; 11 | 12 | /** 13 | * Freemarker utils 14 | * @author easyproject.cn 15 | * 16 | * @since 1.0.0 17 | */ 18 | public class FreemarkerUtil { 19 | 20 | static Configuration cfg = new Configuration(Configuration.VERSION_2_3_22); 21 | 22 | public static String formatTemplate(String templateContent, Map data){ 23 | if(templateContent==null){ 24 | return ""; 25 | } 26 | StringWriter writer = new StringWriter(); 27 | StringTemplateLoader stringLoader = new StringTemplateLoader(); 28 | stringLoader.putTemplate("myTemplate",templateContent); 29 | cfg.setTemplateLoader(stringLoader); 30 | try { 31 | Template template = cfg.getTemplate("myTemplate","utf-8"); 32 | try { 33 | template.process(data, writer); 34 | } catch (TemplateException e) { 35 | e.printStackTrace(); 36 | } 37 | } catch (IOException e) { 38 | e.printStackTrace(); 39 | } 40 | return writer.toString(); 41 | } 42 | 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/java/cn/easyproject/easybackup/util/SpringUtil.java: -------------------------------------------------------------------------------- 1 | package cn.easyproject.easybackup.util; 2 | 3 | import org.springframework.context.support.ClassPathXmlApplicationContext; 4 | /** 5 | * Spring 工具类 6 | * @author easyproject.cn 7 | * 8 | * @since 1.0.0 9 | */ 10 | public class SpringUtil { 11 | public static ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml"); 12 | 13 | @SuppressWarnings("unchecked") 14 | public static T get(String id){ 15 | return (T) applicationContext.getBean(id); 16 | } 17 | public static T get(Class c){ 18 | return applicationContext.getBean(c); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /projects/easybackup/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # Logger 2 | log4j.rootLogger=INFO,console 3 | 4 | ## file 5 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender 6 | log4j.appender.file.File=easybackup.log 7 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.file.layout.ConversionPattern= %d{yyyy MMM dd HH:mm:ss,SSS} %p - %m%n 9 | 10 | 11 | ## console 12 | log4j.appender.console=org.apache.log4j.ConsoleAppender 13 | log4j.appender.console.layout=org.apache.log4j.SimpleLayout 14 | 15 | -------------------------------------------------------------------------------- /projects/easybackup/template/mail.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 |
14 | EasyBackup 15 |
16 | 17 |
18 |

Hello,

19 |

Your backup service is complete.

20 |

21 | Name: ${name} - [${type}] 22 |

23 |

24 | Target: ${value} 25 |

26 |

27 | Backup time: ${backuptime?datetime} 28 |

29 |

30 | Please check your E-mail attachments. 31 |

32 |
33 |
34 | EasyMonitor by easyproject.cn 35 |
36 | 37 | 38 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # EasyBackup 2 | 3 | A free, open source, cross-platform content backup, content compression, remote sending task scheduling application integration framework and engine based on Java. 4 | 5 | 基于 Java 的免费开源跨平台内容备份,压缩,远程发送一体化任务调度应用及引擎框架。 6 | 7 | ![EasyBackup](doc/images/EasyBackup.png) 8 | 9 | ## English 10 | 11 | EasyBackup is a free open-source Java-based, cross-platform content backup, content compression, remote sending task scheduling application and engine framework. 12 | 13 | Provide full support for the need to backup the content: Collection of content-based task scheduling backups, content compression, remote sending, command execution and more. And all this, just a simple configuration management to complete. 14 | 15 | Please choose according to purpose: 16 | - **EasyBackup Application**: Can run as application (`libs/easybackup_application`) 17 | - **EasyBackup Engine Framework**: Can be extended as the content backup engine framework for Java (`libs/easybackup_engine_framework`) 18 | 19 | 20 | [English Docuemnt](doc_en.md) 21 | 22 | 23 | 24 | ## 中文 25 | 26 | EasyBackup 是一个基于 Java 的免费开源跨平台内容备份压缩远程发送一体化任务调度应用及引擎框架。 27 | 28 | 能够为需要进行内容备份的程序场景提供一体化支持:集合了基于任务调度的内容备份,内容压缩,远程发送,命令执行等等功能。而这一切,仅需进行简单的配置管理即可完成。 29 | 30 | 请根据用途选择: 31 | - **EasyBackup Application**: 开箱即用版本,作为应用运行(`libs/easybackup_application`) 32 | - **EasyBackup Engine Framework**: 作为 Java 内容备份引擎框架扩展(`libs/easybackup_engine_framework`) 33 | 34 | 35 | [中文文档](doc_zh_CN.md) 36 | 37 | 38 | 39 | ## Maven - EasyBackup Engine Framework 40 | 41 | ```XML 42 | 43 | 44 | cn.easyproject 45 | easybackup 46 | 3.3.2-RELEASE 47 | 48 | 49 | 50 | 51 | 52 | cn.easyproject 53 | easybackup-mysql 54 | 3.2.0-RELEASE 55 | 56 | ``` 57 | 58 | 59 | ## EasyBackup Web Manger 60 | 61 | [EasyBackup Web Manger](https://github.com/ushelp/EasyBackup-Web "Goto EasyBackup Web Manger") 62 | 63 | A Java Web Manager based on the EasyBackup framework Engine, you can complete the backup configuration, start and stop control. 64 | 65 | (一个基于 EasyBackup 框架引擎的 Java Web 管理器,可以在 Web UI 下完成备份配置管理,备份启动,停止控制。) 66 | 67 | ![EasyBackup web manager](doc/images/dashboard.png) 68 | 69 | ![EasyBackup web manager](doc/images/dashboard_zh_CN.png) 70 | 71 | 72 | ## End 73 | 74 | Email: 75 | 76 | [http://www.easyproject.cn](http://www.easyproject.cn "EasyProject Home") 77 | 78 | 79 | **Donation/捐助:** 80 | 81 | 82 | 
83 | 支付宝/微信/QQ/云闪付/PayPal 扫码支付 84 |
支付宝/微信/QQ/云闪付/PayPal
85 | 86 |
87 | 88 | 我们相信,每个人的点滴贡献,都将是推动产生更多、更好免费开源产品的一大步。 89 | 90 | **感谢慷慨捐助,以支持服务器运行和鼓励更多社区成员。** 91 | 92 | We believe that the contribution of each bit by bit, will be driven to produce more and better free and open source products a big step. 93 | 94 | **Thank you donation to support the server running and encourage more community members.** 95 | --------------------------------------------------------------------------------