153 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			153 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			PHP
		
	
	
| 
								 | 
							
								<?php
							 | 
						|||
| 
								 | 
							
								namespace app\controller\manager;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								use think\facade\{Db, Config, Env};
							 | 
						|||
| 
								 | 
							
								use app\model\{Log as MLog};
							 | 
						|||
| 
								 | 
							
								use app\service\Tool;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								class Backup extends Base
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    /**
							 | 
						|||
| 
								 | 
							
								     * 因受mysql 配置参数net_buffer_length和max_allowed_packet大小的限制,因此insert语句改为单条插入
							 | 
						|||
| 
								 | 
							
								     * show VARIABLES like "%net_buffer_length%" 默认单条sql语句长度16k 
							 | 
						|||
| 
								 | 
							
								     * show VARIABLES like "%max_allowed_packet%" 默认单个sql文件最大容量
							 | 
						|||
| 
								 | 
							
								     * sql 文件注释 -- + 空格之后填写注释内容
							 | 
						|||
| 
								 | 
							
								     * 因根目录文件夹权限限制,因此需要手动创建backup/data目录并赋予权限(www用户组)
							 | 
						|||
| 
								 | 
							
								     */
							 | 
						|||
| 
								 | 
							
								    public function back()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        ini_set('max_execution_time', 0);
							 | 
						|||
| 
								 | 
							
								        ini_set("memory_limit",-1);
							 | 
						|||
| 
								 | 
							
								        set_time_limit(0);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        $path = Config::get('filesystem.disks.backup.root') . '/';
							 | 
						|||
| 
								 | 
							
								        $dataBase = Env::get('database.database');
							 | 
						|||
| 
								 | 
							
								        // 不要使用单引号,双引号中的变量可以解析,单引号就是绝对的字符串
							 | 
						|||
| 
								 | 
							
								        $eol = "\r\n";
							 | 
						|||
| 
								 | 
							
								        $eolB = "\r\n\r\n";
							 | 
						|||
| 
								 | 
							
								        $info = '-- ------------------------------'.$eol;
							 | 
						|||
| 
								 | 
							
								        $info .= '-- 日期: '.date('Y-m-d H:i:s',time()).$eol;
							 | 
						|||
| 
								 | 
							
								        $info .= '-- MySQL --Database - '.$dataBase.$eol;
							 | 
						|||
| 
								 | 
							
								        $info .= '-- ------------------------------'.$eol;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        $info .= 'CREATE DATABASE IF NOT EXISTS `'.$dataBase.'` DEFAULT CHARACTER SET "utf8mb4" COLLATE "utf8mb4_general_ci";'.$eolB;
							 | 
						|||
| 
								 | 
							
								        $info .= 'USE `'.$dataBase.'`;'.$eol;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        if(is_dir($path)) {
							 | 
						|||
| 
								 | 
							
								            if(!is_writable($path)) {
							 | 
						|||
| 
								 | 
							
								                chmod($path, 0755);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        } else {
							 | 
						|||
| 
								 | 
							
								            mkdir($path, 0755, true);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        $fileName = $path.$dataBase.'_'.date('YmdHis',time()).'.sql';
							 | 
						|||
| 
								 | 
							
								        if(file_exists($fileName)) {
							 | 
						|||
| 
								 | 
							
								            @unlink($fileName);
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        // 以追加的方式写入
							 | 
						|||
| 
								 | 
							
								        file_put_contents($fileName, $info, FILE_APPEND);
							 | 
						|||
| 
								 | 
							
								        $tables = Db::query('show tables');
							 | 
						|||
| 
								 | 
							
								        foreach ($tables as $table) {
							 | 
						|||
| 
								 | 
							
								            // 表结构
							 | 
						|||
| 
								 | 
							
								            $tableName = $table['Tables_in_'.$dataBase];
							 | 
						|||
| 
								 | 
							
								            $sqlTable = 'SHOW CREATE TABLE '.$tableName;
							 | 
						|||
| 
								 | 
							
								            $res = Db::query($sqlTable);
							 | 
						|||
| 
								 | 
							
								            $infoTable = '-- ------------------------------'.$eol;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= '-- Table structure for `'.$tableName.'`'.$eol;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= '-- ------------------------------'.$eolB;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= 'DROP TABLE IF EXISTS `'.$tableName.'`;'.$eolB;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= $res[0]['Create Table'].';'.$eolB;
							 | 
						|||
| 
								 | 
							
								            // 表数据
							 | 
						|||
| 
								 | 
							
								            $infoTable .= '-- ------------------------------'.$eol;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= '-- Data for the table `'.$tableName.'`'.$eol;
							 | 
						|||
| 
								 | 
							
								            $infoTable .= '-- ------------------------------'.$eolB;
							 | 
						|||
| 
								 | 
							
								            file_put_contents($fileName, $infoTable, FILE_APPEND);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            $sqlData = 'select * from '.$tableName;
							 | 
						|||
| 
								 | 
							
								            $data = Db::query($sqlData);
							 | 
						|||
| 
								 | 
							
								            $count = count($data);
							 | 
						|||
| 
								 | 
							
								            if ($count > 0) {
							 | 
						|||
| 
								 | 
							
								                $dataStr = 'INSERT INTO `'.$tableName.'` VALUE ';
							 | 
						|||
| 
								 | 
							
								                foreach ($data as $k => $item) {
							 | 
						|||
| 
								 | 
							
								                    $valStr = '(';
							 | 
						|||
| 
								 | 
							
								                    foreach ($item as $val) {
							 | 
						|||
| 
								 | 
							
								                        // 字符串转义
							 | 
						|||
| 
								 | 
							
								                        $val = addslashes($val);
							 | 
						|||
| 
								 | 
							
								                        $valStr .= '"'.$val.'", ';
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                    // 去除最后的逗号和空格
							 | 
						|||
| 
								 | 
							
								                    $valStr = substr($valStr,0,strlen($valStr)-2);
							 | 
						|||
| 
								 | 
							
								                    // 限制单条sql语句在16K以内(可根据mysql配置条件进行调整)
							 | 
						|||
| 
								 | 
							
								                    $sqlLength = strlen($dataStr) + strlen($valStr);
							 | 
						|||
| 
								 | 
							
								                    if($sqlLength >= (1024 * 16 - 10)) {
							 | 
						|||
| 
								 | 
							
								                        $dataStr .= $valStr.');'.$eol;
							 | 
						|||
| 
								 | 
							
								                        file_put_contents($fileName, $dataStr, FILE_APPEND);
							 | 
						|||
| 
								 | 
							
								                        // 提前分段写入后需重置数据语句
							 | 
						|||
| 
								 | 
							
								                        if ($k <= ($count-1)) {
							 | 
						|||
| 
								 | 
							
								                            $dataStr = 'INSERT INTO `'.$tableName.'` VALUE ';
							 | 
						|||
| 
								 | 
							
								                        } else {
							 | 
						|||
| 
								 | 
							
								                            $dataStr = '';
							 | 
						|||
| 
								 | 
							
								                        }
							 | 
						|||
| 
								 | 
							
								                    } else {
							 | 
						|||
| 
								 | 
							
								                        if ($k < ($count-1)) {
							 | 
						|||
| 
								 | 
							
								                            $dataStr .= $valStr.'),'.$eol;
							 | 
						|||
| 
								 | 
							
								                        } else {
							 | 
						|||
| 
								 | 
							
								                            $dataStr .= $valStr.');'.$eolB;
							 | 
						|||
| 
								 | 
							
								                        }
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								                file_put_contents($fileName, $dataStr, FILE_APPEND);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        clearstatcache();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        $backups = explode('/', $fileName);
							 | 
						|||
| 
								 | 
							
								        $backupName =  $backups[count($backups)-1];
							 | 
						|||
| 
								 | 
							
								        $src = Config::get('filesystem.disks.backup.url') . '/';
							 | 
						|||
| 
								 | 
							
								        return $this->json(0, '备份成功:' . $src . $backupName);
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    public function index()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        $path = Config::get('filesystem.disks.backup.root') . '/';
							 | 
						|||
| 
								 | 
							
								        $src = Config::get('filesystem.disks.backup.url') . '/';
							 | 
						|||
| 
								 | 
							
								        $items = [];
							 | 
						|||
| 
								 | 
							
								        if(is_dir($path)) {
							 | 
						|||
| 
								 | 
							
								            if(!is_readable($path)) {
							 | 
						|||
| 
								 | 
							
								                chmod($path,0755);
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            $files = scandir($path);
							 | 
						|||
| 
								 | 
							
								            foreach ($files as $file) {
							 | 
						|||
| 
								 | 
							
								                if($file != '.' && $file != '..') {
							 | 
						|||
| 
								 | 
							
								                    $ext = substr($file, -4);
							 | 
						|||
| 
								 | 
							
								                    if ($ext == '.sql') {
							 | 
						|||
| 
								 | 
							
								                        $creatTime = substr($file, -18, 14);
							 | 
						|||
| 
								 | 
							
								                        $items[] = [
							 | 
						|||
| 
								 | 
							
								                            'file' => $file,
							 | 
						|||
| 
								 | 
							
								                            'path' => $src . $file,
							 | 
						|||
| 
								 | 
							
								                            'time' =>is_numeric($creatTime) ? date('Y-m-d H:i:s', strtotime($creatTime)) : '',
							 | 
						|||
| 
								 | 
							
								                        ];
							 | 
						|||
| 
								 | 
							
								                    }
							 | 
						|||
| 
								 | 
							
								                }
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								        clearstatcache();
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								        $this->data['items'] = $items;
							 | 
						|||
| 
								 | 
							
								        $this->data['backupPath'] = str_replace('\\','/', $path);
							 | 
						|||
| 
								 | 
							
								        return $this->view();
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								    
							 | 
						|||
| 
								 | 
							
								    public function del()
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        if (request()->isPost()) {
							 | 
						|||
| 
								 | 
							
								            $filePath = input('post.id');
							 | 
						|||
| 
								 | 
							
								            Tool::delFile($filePath);
							 | 
						|||
| 
								 | 
							
								            MLog::write('backup', 'del', '删除了备份数据文件,文件路径为:' . $filePath);
							 | 
						|||
| 
								 | 
							
								            return $this->json();
							 | 
						|||
| 
								 | 
							
								        } else {
							 | 
						|||
| 
								 | 
							
								            return $this->json(1, '非法请求');
							 | 
						|||
| 
								 | 
							
								        }
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |