樹莓派上的系統自動更新

樹莓派上的系統自動更新


有這樣一個問題,假如我們有成千上萬臺設備在運行,假如系統出了BUG,或者我們需要添加什麼功能,我們不可能派人每一臺每一臺的去修復吧。因此我們需要做一個自動更新的東西,假如系統出現bug,或者需要增加新功能,我們就像是在修改網站一樣,只需要在網站上修改代碼,然後大家所有的設備上都更新了。

我們需要怎麼做呢,首先我們需要在數據庫上建立一個表,至少要兩個字段,當前版本號和當前要更新的文件的下載地址,當然我們的更新文件是以zip的方式打包的。

像下面這樣:

<code>DROP TABLE IF EXISTS `yzn_versionctl`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `yzn_versionctl` (
`versionid` int(11) NOT NULL DEFAULT '0',
`version_url` varchar(245) COLLATE utf8_bin DEFAULT '',
PRIMARY KEY (`versionid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;/<code>
<code>--
-- Dumping data for table `yzn_versionctl`
--
LOCK TABLES `yzn_versionctl` WRITE;
/*!40000 ALTER TABLE `yzn_versionctl` DISABLE KEYS */;
INSERT INTO `yzn_versionctl` VALUES (2,'http://cms.o4.com/update/raspberrypi_client.zip');
/*!40000 ALTER TABLE `yzn_versionctl` ENABLE KEYS */;
UNLOCK TABLES;/<code>

我們通過php後臺,下次要更新系統時,只需要通過後臺提高系統版本號,並且上傳相應的更新文件就可以了。

然後樹莓派就需要通過php獲取到這些版本信息,我們看看php後臺代碼是怎樣的:

<code>    public function getVersionUpdateInfo()
{
$versiondata = $this->Member_Model->member_getVersionUpdateInfo();
return json_encode($versiondata[0]);
}/<code>

查詢數據庫:

<code>    public function member_getVersionUpdateInfo()
{
$data = Db::name('versionctl')
->select();
return $data;
}/<code>

解決跨域問題:

<code>Route::get('getVersionUpdateInfo','api/mobile/getVersionUpdateInfo')->allowCrossDomain();/<code>

好,到這裡,我們就可以通過下面這種方式去獲取版本信息了:

<code>http://cms.o4.com/getVersionUpdateInfo/<code>

接下來,我們看看樹莓派上的nodejs如何操作,要進行更新,我們需要安裝下面的東西:

<code>sudo npm install pm2 -g       -- 用於啟動和管理nodejs進程
sudo npm install fs -- 本地文件操作
sudo npm install axios -- 用於和php後臺交互
sudo npm install unzip -- 用於解壓文件

sudo npm install node-schedule -- 用於定時任務,半夜三更才更新系統/<code>

然後,我們接下來看看具體操作步驟,首先是要從網站上下載文件,代碼如下:

<code>const http = require('http');
const fs = require('fs');
function downloadFileAsync(uri, dest){
return new Promise((resolve, reject)=>{
// 確保dest路徑存在
const file = fs.createWriteStream(dest);
http.get(uri, (res)=>{
if(res.statusCode !== 200){
reject(res.statusCode);
return;
}
res.on('end', ()=>{
console.log('download end');
});
// 進度、超時等
file.on('finish', ()=>{
console.log('finish write file')
file.close(resolve);
}).on('error', (err)=>{
fs.unlink(dest);
reject(err.message);
})
res.pipe(file);
});
});
}/<code>

然後是解壓文件:

<code>function unzipFile(ExtractPath,zipFile) {
\treturn new Promise((resolve, reject) => {
\t\t\tfs.createReadStream(zipFile).pipe(unzip.Extract({ path:ExtractPath}).on("close",() => {
\t\t\t\tconsole.log('unzip success');
\t\t\t\tresolve("unzipSync Done")
\t\t\t}).on('error',(err) => {
\t\t\t\treject(err)
\t\t\t}))
\t\t\t.on('error', (err) => {
\t\t\t\treject(err)

\t\t\t})
\t\t})
}/<code>

首先,我們在我們系統中保存一個版本號,每次系統啟動後就先對比php後臺上的版本號,如果發現對不上,就從網站上下載最新的系統文件,然後解壓更新本地機器上的文件,本地系統更新完成後,重啟整個系統。

下面是系統更新的代碼:

<code>function VersionUpdate(curVersion) {
\taxios.get(update_url).then(async(res) => {
\t\tconsole.log('curVersion:'+curVersion+' newVersion:'+res.data.versionid+' updateUrl:'+res.data.version_url);
\t\tif(res.data.versionid != curVersion) {
\t\t\tawait downloadFileAsync(res.data.version_url,'raspberrypi_version.zip');
\t\t\tawait unzipFile('./','raspberrypi_version.zip');
\t\t\tconsole.log('update success.last version:'+res.data.versionid);
\t\t}
\t\telse {
\t\t\tconsole.log('not update.curVersion:'+curVersion);\t
\t\t}
\t}).catch(function (error) {
\t\tconsole.log('version update error:'+error);
\t});\t
}/<code>

而系統重啟就要交給pm2這個工具了,它有一個功能就是檢測到當前代碼出現變動就自動重新啟動系統。

<code>pm2 start ./bin/www --watch
--watch參數,意味著當你的express應用代碼發生變化時,pm2會幫你重啟服務/<code>

我們有兩個地方要更新,一個是在每次系統啟動後就自動更新到最新的系統,另外就是每晚夜深人靜的時候的時候檢測系統是否更新,因此我們需要用定時任務。

關於node-schedule的用法可以參考下面的參考文檔,我們這裡代碼如下:

<code>const  scheduleCronstyle = ()=>{
//每天的凌晨1點1分30秒觸發
schedule.scheduleJob('30 1 1 * * *',()=>{
VersionUpdate(curVersion);
});
}
scheduleCronstyle();/<code>

OK,到這裡,我們整個系統就可以如做網站般簡單了。你只需要後臺操作一下,就可以更新所有的設備,可以安心去睡個好覺了。


參考文檔:

pm2常用的命令用法介紹

https://blog.csdn.net/chengxuyuanyonghu/article/details/74910875

Nodejs定時任務(node-schedule)

https://www.jianshu.com/p/8d303ff8fdeb

鼴鼠智能售貨機系統(Mole intelligent vending machine system)

https://gitee.com/akinggw/MIVMS


分享到:


相關文章: