溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

php實(shí)現(xiàn)更新功能的方法

發(fā)布時(shí)間:2020-09-08 10:22:23 來(lái)源:億速云 閱讀:173 作者:小新 欄目:編程語(yǔ)言

php實(shí)現(xiàn)更新功能的方法?這個(gè)問(wèn)題可能是我們?nèi)粘W(xué)習(xí)或工作經(jīng)常見(jiàn)到的。希望通過(guò)這個(gè)問(wèn)題能讓你收獲頗深。下面是小編給大家?guī)?lái)的參考內(nèi)容,讓我們一起來(lái)看看吧!

php實(shí)現(xiàn)更新功能的方法:首先制作升級(jí)包,增量更新;然后驗(yàn)證上傳文件,并驗(yàn)證當(dāng)前系統(tǒng)版本;接著備份原來(lái)的代碼,并當(dāng)升級(jí)失敗時(shí)進(jìn)行回滾;最后記錄升級(jí)日志,返回升級(jí)進(jìn)度即可。

php實(shí)現(xiàn)更新功能的方法

php 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的項(xiàng)目升級(jí)功能

思路

1.制作升級(jí)包,增量更新

2.升級(jí)包上傳驗(yàn)證上傳文件,驗(yàn)證當(dāng)前系統(tǒng)版本

3.升級(jí)之前要先備份原來(lái)的代碼,升級(jí)失敗要進(jìn)行回滾

4.記錄升級(jí)日志,返回升級(jí)進(jìn)度

5.升級(jí)包應(yīng)該是加密的(暫時(shí)沒(méi)實(shí)現(xiàn))

說(shuō)明

1.升級(jí)包的目錄結(jié)構(gòu)必須如下

/**
 *  升級(jí)包規(guī)定的目錄結(jié)構(gòu)
 *  xxx_版本號(hào).zip(如:xxx_1.0.0.zip)
 *   |
 *   |————mysql
 *   |    |
 *   |    |___mysql_update.sql(更新腳本)
 *   |    |___mysql_rockback.sql(回滾腳本)
 *   |    
 *   |____php
 * 
*/

2.mysql_update.sql

create table test(id init(11));
create table test2(id init(11));
mysql_rockback.sql
drop table test;
drop table test2;
4.代碼
class UpgradeSys{
    public $update_log = "/tmp/web/update_log.log"; //系統(tǒng)升級(jí)日志
    public $return_log = "/tmp/web/return_log.log"; //系統(tǒng)回滾日志
    public $progress_log = "/tmp/web/progress_log.log"; //記錄進(jìn)度
    public $root_dir = "/Users/feng/Documents/work/test"; //站點(diǎn)代碼的根目錄
    public $aFile = ["log","runtime"];//忽略文件夾相對(duì)路徑
    public $backup_dir = "/tmp/web/backup_dir";//備份目錄
    public $upload_dir = "/tmp/web/upload_dir";//升級(jí)包目錄
    public $sys_version_num = '1.0.0';//當(dāng)前系統(tǒng)的版本 這個(gè)在實(shí)際應(yīng)用中應(yīng)該是蟲(chóng)數(shù)據(jù)庫(kù)獲取得到的,這里只是舉個(gè)例子
    /** 展示升級(jí)界面 */
    public function index()
    {
        include("update.html");
    }
    /**
     * 處理升級(jí)包上傳
     */
    public function upload()
    {
        $params = $_POST;
        if($_FILES)
        {
            $name  = $_FILES['file']['tmp_name'];
            if(!$name || !is_uploaded_file($name))
            {
                echo json_encode(["status"=>0,"msg"=>"請(qǐng)上傳升級(jí)包文件"]);
                die;
            }
        }
        //校驗(yàn)后綴
        $astr = explode('.',$name);
        $ext = array_pop($astr);
        if($ext != 'zip')
        {
            echo json_encode(["status"=>0,"msg"=>"請(qǐng)上傳文件格式不對(duì)"]);
            die;
        }
        //校驗(yàn)升級(jí)密碼
        // if(!isset($params['password']) || $params['password'] != $this->password)
        // {
        //     echo json_encode(["status"=>0,"msg"=>"密碼錯(cuò)誤"]);
        //     die;
        // }
        //對(duì)比版本號(hào)
        $astr = explode('_',$name);
        $version_num = str_replace(".zip", '',array_pop($astr));
        if(!$version_num)
        {
            echo json_encode(["status"=>0,"msg"=>"獲取版本號(hào)失敗"]);
            die;
        }
        //對(duì)比
        if(!$this->compare_version($version_num))
        {
            echo json_encode(["status"=>0,"msg"=>"不能升級(jí)低版本的"]);
            die;
        }
        $package_name = $this->upload_dir.'/'.$version_num.'.zip';
        if(!move_uploaded_file($name,$package_name))
        {
            echo json_encode(["status"=>0,"msg"=>"上傳文件失敗"]);
            die;
        }
        //記錄下日志
        $this->save_log("上傳升級(jí)包成功!");
        $this->update_progress("20%");
        //備份code
        $result = $this->backup_code();
        if(!$result)
        {
            $this->save_log("備份失??!");
            echo json_encode(["status"=>0,"msg"=>"備份失敗"]);
            die;
        }
        $this->update_progress("30%");
        //執(zhí)行升級(jí)
        $this->execute_update($package_name);
    }
    /**
     * 升級(jí)操作
     * @return [type] [description]
     */
    private function execute_update($package_name)
    {
        //解壓 如何使用zip加密壓縮,這里解壓縮的時(shí)候注意要解密
        exec(" cd $upload_dir && unzip $package_name ");
        $package_name = str_replace(".zip","",$package_name);
        if(!is_dir($package_name))
        {
            $this->save_log("解壓失敗");
            echo json_encode(["status"=>0,"msg"=>"解壓失敗"]);
            die;
        }
        $this->update_progress("50%");
        //升級(jí)mysql
        if(file_exists($this->upload_dir.'/'.$package_name."/mysql/mysql_update.sql"))
        {
            $result = $this->database_operation($this->upload_dir.'/'.$package_name."/mysql/mysql_update.sql");
            if(!$result['status'])
            {
                echo json_encode($result);die;
            }
        }
        $this->update_progress("70%");
        //升級(jí)PHP
        if(is_dir($this->upload_dir.'/'.$package_name.'/php'))
        {
            exec("cd {$this->upload_dir}/{$package_name}/php && cp -rf ./* $this->root_dir ",$mdata,$status);
            if($status != 0 )
            {
                $this->save_log("php更新失敗");
                //數(shù)據(jù)庫(kù)回滾
                if(file_exists($this->upload_dir.'/'.$package_name."/mysql/mysql_rockback.sql"))
                {
                    $this->save_log("數(shù)據(jù)庫(kù)回滾");
                    $this->database_operation($this->upload_dir.'/'.$package_name."/mysql/mysql_rockback.sql");
                 
                }
                //php代碼回滾
                $cmd = "cp -rf " .$this->backup_dir."/".$this->sys_version_num.'/'.basename($this->root_dir)."/* ".$this->root_dir;
                exec($cmd,$mdata,$status);
                $this->save_log("php回滾");
                echo json_encode(["status"=>0,"msg"=>"php更新失敗"]);
                die;
            }
        }
        //把解壓的升級(jí)包清除
        exec("rm -rf $upload_dir/$package_name ");
        
        $this->update_progress("100%");
        //更新系統(tǒng)的版本號(hào)了
       //更新php的版本號(hào)了(應(yīng)該跟svn/git的版本號(hào)一致)
       //更新數(shù)據(jù)庫(kù)的版本號(hào)了(應(yīng)該跟svn/git的版本號(hào)一致)
        echo json_encode(["status"=>1,"msg"=>"升級(jí)成功"]);
        die;
    }
    /**
     * 比較代碼版本
     * @return [type] [description]
     */
    private function compare_version($version_num='1.0.0')
    {
        
        return version_compare($version_num,$this->sys_version_num,'>');
    }
    /**
     * 備份代碼
     */
    private function backup_code()
    {
        //rsync 要確定系統(tǒng)是否已經(jīng)安裝
        $cmd = "cd $root_dir && cd ..  && rsync -av ";
        foreach ($this->aFile as $key => $value) {
            $cmd ."--exclude ". basename($this->root_dir) ."/".$value ." ";
        }
        $cmd .= basename($this->root_dir)." ".$this->backup_dir."/".$this->sys_version_num;
        exec($cmd,$mdata,$status);
        if($status != 0)
        {
            return false;
        }
        //這里還可以對(duì)備份的文件進(jìn)行壓縮
        return true;
    }
    /**
     * 數(shù)據(jù)庫(kù)操作
     */
    public function database_operation($file)
    {
        $mysqli = new mysqli("localhost","root","root","test");
        if($mysqli->connect_errno)
        {
            return ["status"=>0,"msg"=>"Connect failed:".$mysqli->connect_error];
        }
        $sql = file_get_contents($file);
        $a = $mysqli->multi_query($sql);
        return ["status"=>1,"msg"=>"數(shù)據(jù)庫(kù)操作OK"];
    }
    /**
     * 返回系統(tǒng)升級(jí)的進(jìn)度
     */
    public function update_progress($progress)
    {
        exec(" echo '".$progress."' > $this->progress_log ");
    }
    /**
     * 記錄日志
     */
    public function save_log($msg,$action="update")
    {
        $msg .= date("Y-m-d H:i:s").":".$msg."\n";
        if($action == "update")
        {
            exec(" echo '".$msg."' >>  $this->update_log ");
        }else
        {
            exec(" echo '".$msg."' >>  $this->return_log ");
        }
    }
}

感謝各位的閱讀!看完上述內(nèi)容,你們對(duì)php實(shí)現(xiàn)更新功能的方法大概了解了嗎?希望文章內(nèi)容對(duì)大家有所幫助。如果想了解更多相關(guān)文章內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI