整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Openwrt LuCI模塊練習(xí)詳細(xì)步驟

          Openwrt LuCI模塊練習(xí)詳細(xì)步驟

          近在學(xué)習(xí)openwrt luci方面的知識(shí),為了貫穿整個(gè)知識(shí)體系,練習(xí)題目為:

          通過頁面配置周期性地往/tmp/addtest文件寫入內(nèi)容和時(shí)間戳
          1.在web主頁面的下拉菜單做一個(gè)按鈕,進(jìn)入設(shè)置頁面;
          2.兩個(gè)設(shè)置項(xiàng):輸入的內(nèi)容和周期;
          3,讀取/tmp/addtest中的內(nèi)容并顯示在頁面上;

          代碼已經(jīng)開源,歡迎交流~


          知識(shí)準(zhǔn)備

          源碼編譯及ipk生成

          這部分網(wǎng)上相關(guān)文章很多,也可以參見拙作

          LuCI

          首先回答一個(gè)問題:什么是Luci?
          >LuCI是OpenWrt上的Web管理界面,LuCI采用了MVC三層架構(gòu),使用Lua腳本開發(fā).

          簡單地說,Luci就是用來做openwrt的頁面的.不同于常見的html+css+javascript,Openwrt是用lua腳本語言開發(fā)的.

          怎么開發(fā)一個(gè)頁面呢?

          要開發(fā)一個(gè)新的功能頁面,開發(fā)者只要根據(jù)MVC框架寫些簡單的lua腳本,剩下的部分由openwrt為你自動(dòng)完成.

          說到MVC框架了,什么是MVC框架呢?

          MVC是model+view+controller的簡寫.為了便于開發(fā),openwrt將實(shí)現(xiàn)不同功能的lua腳本放在不同的文件夾中.請(qǐng)看下圖:

          什么是controller控制器?

          我們?cè)谶@里設(shè)置功能在頁面的位置,同時(shí)設(shè)置點(diǎn)擊頁面后,將要調(diào)用的功能.是要去Model模型讀寫配置數(shù)據(jù)呢?還是要呈現(xiàn)一個(gè)靜態(tài)頁面,或者是直接執(zhí)行l(wèi)ua腳本函數(shù).

          什么是model模型?

          這里我們常用的是,通過cbi模塊和UCI(統(tǒng)一配置接口)進(jìn)行交互.簡單地說,就是我們?cè)谶@里將頁面和路由器里面的配置關(guān)聯(lián)起來,從而將頁面的設(shè)置寫到路由器當(dāng)中.

          什么是view視圖?

          這個(gè)應(yīng)該是最容易理解的,就是呈現(xiàn)的頁面的樣式,有點(diǎn)類似于傳統(tǒng)的html頁面.

          上面說到了UCI(Unified Configuartion Interface),這是什么龜?

          openwrt將配置用統(tǒng)一的格式書寫,放在規(guī)定的地方(/etc/config/),同時(shí)提供接口函數(shù)進(jìn)行讀取和設(shè)置.

          如果還不太明白,接著向下看.如果有可能跟著我動(dòng)動(dòng)手,相信你很快就會(huì)掌握:)


          正文

          我們先看下最終效果圖:


          我們?cè)陧撁嫔厦娴?/span>System下拉框的下面加了一個(gè)AddTest按鈕,下面有兩個(gè)子選項(xiàng):SetInfo.其中Set用于選擇是否開啟功能,設(shè)置時(shí)間間隔和內(nèi)容.Info用于顯示/tmp/addtest文件中的內(nèi)容.

          準(zhǔn)備工作

          首先,嗯~
          你得有環(huán)境,得有電,有源碼,編譯過簡單的ipk.如果沒有,請(qǐng)回爐重造.
          其次,建立相應(yīng)的文件夾及文件.至于linux操作神馬的,我相信你一定沒有問題.

          $mkdir -p ~/temp/addtest
          $cd ~/temp/addtest

          最終文件樹形圖


          骨架已經(jīng)有了,下面只需要往里面填肉了,是不是感覺很快~
          不要管為什么要這樣,我們后面慢慢解釋.


          controller

          前面我們提到,controller主要用于控制頁面按鈕位置,以及調(diào)用的功能.首先來編輯這個(gè)文件.

          $vim ~/temp/addtest/files/usr/lib/lua/luci/controller/addtest.lua

          代碼如下:

          module("luci.controller.addtest",package.seeall)
          
          function index()
              entry({"admin","system","addtest"},alias("admin","system","addtest","set"),_("AddTest"),99).index=true
              entry({"admin","system","addtest","set"},cbi("addtest"),_("Set"),1)
              entry({"admin","system","addtest","info"},call("action_info"),_("Info"),2)
          end
          
          function action_info()
              if not nixio.fs.access("/tmp/addtest") then
                  return
              end
          
              local info=nixio.fs.readfile("/tmp/addtest")
              luci.template.render("addtest_info",{info=info})
          end

          格式模板:

          module("luci.controller.控制器名", package.seeall)
          
          function index()
                  entry(路徑, 調(diào)用目標(biāo), _("顯示名稱"), 顯示順序)
                  end

          這個(gè)腳本文件可以分為3塊:第1行,3~7行,9~16行

          第1行說明了模塊的名稱,本文在controller目錄下創(chuàng)建了addtest.lua文件,將模板中的控制器名替換為addtest即可.第3行第3~7行定義按鈕的位置,調(diào)用的功能,顯示名稱.其中第3行和第7行是固定的模板格式,不需要修改第4行entry表示添加新的模塊.
          第一個(gè)參數(shù){"admin","system","addtest"}表示按鈕的位置.admin表示我們這個(gè)功能只有以管理員身份登錄頁面才可以看到.system表示一級(jí)菜單名,addtest則是一級(jí)菜單下的子菜單.
          第二個(gè)參數(shù)alias("admin","system","addtest","set")表示調(diào)用的功能.這個(gè)按鈕沒有獨(dú)立的功能,而是將它關(guān)聯(lián)到它的下一級(jí)子菜單set.
          第三個(gè)參數(shù)_("AddTest")表示顯示名稱,可選.如果頁面按鈕想做成中文,可以在這里設(shè)置.
          第四個(gè)參數(shù)99表示顯示順序的優(yōu)先級(jí),Luci根據(jù)這個(gè)值為同一父菜單的所有子菜單排序.第5行第一個(gè)參數(shù){"admin","system","addtest","set"}表示在addtest下再增加一個(gè)子選項(xiàng)set.
          第二個(gè)參數(shù)cbi("addtest")表示調(diào)用cbi模塊,這里將會(huì)調(diào)用到/usr/lib/lua/luci/model/cbi/addtest.lua第6行第二個(gè)參數(shù)call("action_info")表示執(zhí)行指定方法,這里將會(huì)調(diào)用我們下面寫的acttion_info函數(shù).備注關(guān)于entry第二個(gè)參數(shù)調(diào)用目標(biāo).我們還有一個(gè)template沒有涉及,它表示訪問指定頁面.比如template(addtest_info)將會(huì)直接訪問/usr/lib/lua/luci/view/addtest_info.htm.9~16行這里使用lua語言調(diào)用nixio接口寫了一個(gè)簡單的函數(shù),首先判斷文件是否存在,然后讀取其中的內(nèi)容賦值給變量info,最后訪問指定頁面/usr/lib/lua/luci/view/addtest_info.htm,同時(shí)將變量info傳遞過去.
          luci接口手冊(cè)
          nixio接口手冊(cè)


          UCI

          UCI是openwrt的配置管理機(jī)制,它將配置統(tǒng)一放到/etc/config文件夾下.詳細(xì)地介紹請(qǐng)參考這里.
          下面來編輯這個(gè)文件

          $vim ~/temp/addtest/files/etc/config/addtest

          代碼如下:

          config arguments
              option interval ''
              option content ''

          Section開始語法: config '類型' '名字'
          參數(shù)定義語法: option '鍵' '值'
          列表定義語法: list '集合名字' '值'

          簡單解釋下,我們?cè)?/span>/etc/config下新建一個(gè)名為addtest的配置文件,其中類型為arguments,名字省略.有兩個(gè)鍵,一個(gè)名為interval用來存時(shí)間間隔.一個(gè)名為content用來存準(zhǔn)備周期性輸入的內(nèi)容.


          Model

          controller章節(jié)中,我們提到cbi會(huì)調(diào)用到model文件夾中的addtest.lua文件.下面我們來編輯它.

          $vim ~/temp/addtest/files/usr/lib/lua/luci/model/cbi/addtest.lua

          代碼如下:

          m=Map("addtest",translate("Luci practice"),translate("fat cheng's test"))
          
          s=m:section(TypedSection,"arguments","")
          s.addremove=true
          s.anonymous=false
          
          s:option(Flag,"enable",translate("Enable"))
          s:option(Value,"interval",translate("Interval"))
          s:option(Value,"content",translate("Content"))
          
          local apply=luci.http.formvalue("cbi.apply")
          if apply then
              io.popen("/etc/init.d/addtestd restart")
          end
          
          return m

          下面我們來解釋下這個(gè)文件.

          第1行模板m=Map("配置文件文件名", "配置頁面標(biāo)題", "配置頁面說明")
          第一個(gè)參數(shù):上一步我們新建配置文件/etc/config/addtest.這里就是建立與配置文件的聯(lián)系.
          第二,三兩個(gè)參數(shù),則是頁面的主標(biāo)題和副標(biāo)題.還不清楚的話,翻上去看看最終效果圖,看看它們?cè)谀睦?第3行在一個(gè)配置文件中可能有很多Section,所以我們需要?jiǎng)?chuàng)建與配置文件中我們想要的Section的聯(lián)系.
          有兩種方式可以選擇:NamedSection(name,type,title,description)和TypedSection(type,title,description),前者根據(jù)配置文件中的Section名,而后者根據(jù)配置文件中的Section類型.我們選用了第二種.第4行設(shè)定不允許增加或刪除Section第5行設(shè)定顯示Section的名稱,這里建議你可以試試設(shè)定為true,看看會(huì)發(fā)生什么.7~9行接著則是建立與Section中的option之間的聯(lián)系.模板s:option(交互形式,option鍵值,顯示名稱).
          第一個(gè)參數(shù):常見的交互形式有Value(文本框),ListValue(下拉框),Flag(選擇框).,不知道為啥我打不開官方文檔,這里也可以參考
          第二個(gè)參數(shù)表示在配置文件中的option的鍵值
          第三個(gè)參數(shù)表示,你希望在頁面上呈現(xiàn)的名稱.
          創(chuàng)建后開發(fā)者無需考慮讀取以及寫入配置文件的問題,系統(tǒng)會(huì)自動(dòng)處理.11~14行系統(tǒng)會(huì)為我們?cè)陧撁嫔献詣?dòng)創(chuàng)建一些按鈕Save&Apply,Save,Reset.我們僅僅將配置寫入/etc/config下對(duì)應(yīng)的文件是不夠的,我們還希望可以根據(jù)這個(gè)配置進(jìn)行一些操作.
          這部分代碼的作用是,當(dāng)你按下頁面的apply按鈕后,相當(dāng)于在串口shell下輸入/etc/init.d/addtestd restart


          init.d

          上一節(jié)我們已經(jīng)可以讀寫配置了,怎么根據(jù)配置來進(jìn)行操作呢?這是我們這一節(jié)要談的.我們來編輯~/temp/addtest/files/etc/init.d/addtestd這個(gè)文件.
          代碼如下:

          #!/bin/sh /etc/rc.common
          START=50
          
          run_addtest()
          {
              local enable
              config_get_bool enable $1 enable
          
              if [ $enable ]; then
                  local interval
                  local content
                  config_get interval $1 interval
                  config_get content $1 content
          
                  addtest $interval $content           
              fi
          }
          
          start()
          {
              config_load addtest
              config_foreach run_addtest arguments
          }
          
          stop()
          {
              result=`pidof addtest`
              kill -9 $result
              echo "addtest has stoped"
          }

          第1行Linux 系統(tǒng)根據(jù) “#!” 及該字串后面的信息確定該文件的類型,表示這個(gè)文件需要由/bin/sh和/etc/rc.common來解釋執(zhí)行.第2行表示啟動(dòng)的優(yōu)先級(jí),這里暫時(shí)用不到4~17行是一個(gè)函數(shù),主要作用是讀取/etc/config/addtest中的內(nèi)容,然后根據(jù)是否打開開關(guān)在第15行將配置傳遞給可執(zhí)行文件addtest,由它根據(jù)配置執(zhí)行指定的操作.
          讀取配置的方法,我強(qiáng)烈推薦你閱讀官方文檔,精煉而簡潔.
          獲取布爾值類型:config_get_bool 變量名 Section名 Section參數(shù)名
          獲取變量值:config_get 變量名 Section名 Section參數(shù)名19~23行對(duì)應(yīng)于/etc/init.d/addtestd start.首先使用config_load 配置文件名的方法載入配置文件,然后使用config_foreach 遍歷函數(shù)名 Section類型的方法,遍歷配置文件中的Section.25~30行對(duì)應(yīng)于/etc/init.d/addtestd stop.找到addtest這個(gè)進(jìn)程的進(jìn)程號(hào),然后殺死它備注前一節(jié)提到的/etc/init.d/addtestd restart中的restart命令,在/etc/rc.common進(jìn)行了定義,簡單來講就是先執(zhí)行了stop命令,再執(zhí)行start命令.
          最后務(wù)必執(zhí)行$sudo chmod 755 ~/temp/addtest/files/etc/init.d/addtestd.


          src

          前一節(jié),我們談到run_addtest調(diào)用可執(zhí)行文件addtest,現(xiàn)在我們編輯這部分內(nèi)容

          $vim ~/temp/addtest/files/src/addtest.c

          代碼如下:

          #include <stdio.h>
          #include <string.h>
          #include <unistd.h>
          #include <stdlib.h>
          
          int main(int argc, char *argv[])
          {
              int index;
              for(index=0; index<10; index++)
              {
                  FILE *fp=fopen("/tmp/addtest","at");
                  system("date >> /tmp/addtest");
                  fprintf(fp, "%s\n", argv[2]);
                  fclose(fp);
                  printf("interval=%d\n",atoi(argv[1]));
                  sleep(  atoi(argv[1]) );
              }
              return 0;
          }

          這部分代碼比較簡短,我們不再解釋.需要掌握的點(diǎn)有:

          1.argcargv[]的使用方法
          2.fopen函數(shù),fclose函數(shù)以及fprintf函數(shù)的使用方法
          3.system函數(shù)的使用方法
          4.sleep函數(shù)和atoi函數(shù)的使用方法,argv[1]的類型為char需要轉(zhuǎn)換為整型.

          通過這個(gè)可執(zhí)行文件,我們周期性地將時(shí)間戳和內(nèi)容寫入了/tmp/addtest文件.
          最后我們寫一個(gè)簡單的Makefile:

          $vim $vim ~/temp/addtest/files/src/Makefile

          代碼如下:

          addtest : addtest.o
              $(CC) addtest.o -o addtest
          
          addtest.o : addtest.c
              $(CC) -c addtest.c
          
          clean :
              rm *.o addtest

          View

          上一節(jié),我們已經(jīng)根據(jù)配置將指定的內(nèi)容周期性地寫入了/tmp/addtest.在controller那一節(jié),我們的函數(shù)action_info讀取了/tmp/addtest中的內(nèi)容并訪問指定頁面/usr/lib/lua/luci/view/addtest_info.htm,同時(shí)將讀取的內(nèi)容通過變量info傳遞過去.
          下面我們來編輯這個(gè)頁面,
          $vim ~/temp/addtest/files/usr/lib/lua/luci/view/addtest_info.htm
          代碼如下:

          <%+header%>
          <h2><a id="content" name="content"><%:Addtest Info%></a></h2>
          <div id="content_addtest_info">
          <textarea readonly="readonly" wrap="off" rows="<%=info:cmatch("\n")+2%>" id="info"><%=info:pcdata()%></textarea>
          </div>
          <%+footer%>

          這部分和傳統(tǒng)的html很類似,我主要是根據(jù)其他頁面照貓畫虎,不是很美觀.有機(jī)會(huì)還要加強(qiáng)這個(gè)方面的學(xué)習(xí).


          Makefile

          不知不覺,我們居然已經(jīng)將代碼全部寫完了,竟還有點(diǎn)戀戀不舍呢.下面我們用一個(gè)Makefie文件將它們打包生成一個(gè)ipk文件.

          $vim ~/temp/addtest/Makefile

          代碼如下:

          include $(TOPDIR)/rules.mk
          
          PKG_NAME:=addtest
          PKG_VERSION=1.0
          PKG_RELEASE:=1
          
          PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
          
          include $(INCLUDE_DIR)/package.mk
          
          define Package/addtest
              SECTION:=utils
              CATEGORY:=Utilities
              TITLE:=Addtest--print something to /var/addtest
          endef
          
          define Package/addtest/description
              It's a test,print something to /var/addtest cyclicaliy
          endef
          
          define Build/Prepare
              mkdir -p $(PKG_BUILD_DIR)
              $(CP) ./src/* $(PKG_BUILD_DIR)/
          endef
          
          define Package/addtest/postinst
          #!/bin/sh
          rm -rf /tmp/luci*
          endef
          
          define Build/Configure
          endef
          
          define Build/Compile
              $(call Build/Compile/Default)
          endef
          
          define Package/$(PKG_NAME)/install
              $(CP) ./files/* $(1)/
              $(INSTALL_DIR) $(1)/bin
              $(INSTALL_BIN)  $(PKG_BUILD_DIR)/addtest  $(1)/bin
          endef
          
          $(eval $(call BuildPackage,$(PKG_NAME)))

          Makefile的解釋,請(qǐng)參見拙作.我們這里稍作補(bǔ)充.

          26~29行由于luci會(huì)將模塊加載到/tmp目錄下運(yùn)行,每次新加載luci模塊后,需要執(zhí)行$rm -rf /tmp/luci*.這里表示安裝了ipk之后,將會(huì)自動(dòng)執(zhí)行刪除命令,重新載入.39行$(1)是傳入的參數(shù),表示系統(tǒng)鏡像目錄,你可以將之視為路由器最后的文件系統(tǒng).所以這句的意思就是將我們files下的內(nèi)容拷貝到路由器的文件系統(tǒng)中.這也是我們?yōu)槭裁匆⒁婚_始那么復(fù)雜的目錄樹的原因.


          編譯&安裝

          簡直像裹腳布一樣,又臭又長.不要說讀了,我自己寫的都快有點(diǎn)受不了了.讀到這里的人真是辛苦了,下面到了我們收獲果實(shí)的時(shí)候了.
          將文件拷貝到源碼目錄的
          package目錄下.其余部分,請(qǐng)參考拙作

          $cp ~/temp/addtest ~/openwrt/package

          把它拷貝到你的開發(fā)板中,試試看.


          調(diào)試方法

          我們當(dāng)然希望可以一次成功,不過世間不如意之事十之八九.我來談?wù)勎易约旱恼{(diào)試方法.

          src部分src文件下有Makefile文件,你可以直接在編譯機(jī)上執(zhí)行$make生成可執(zhí)行文件addtest,然后在編譯機(jī)上src目錄下執(zhí)行$./addtest 參數(shù)1 參數(shù)2.最后記得執(zhí)行$make clean.luci部分將ipk安裝到開發(fā)板后,可以通過串口或者ssh的方式登錄開發(fā)板,然后直接在開發(fā)板中修改文件內(nèi)容,再執(zhí)行$rm -rf /tmp/luci*.最后重新載入設(shè)備頁面.

          、luci-base目錄下包含如下圖幾個(gè)文件夾:

          1、htdocs(html+docs):此目錄存放HTML相關(guān)文件,主要包含以下兩個(gè)目錄,當(dāng)燒錄到硬件設(shè)備后,將拷貝到/www根目錄下

          cgi-bin:存放luci啟動(dòng)腳本
          luci-static:存放HTML相關(guān)文件,包含CSS、JS及網(wǎng)頁圖片等文件
          

          2、luasrc(lua+src):此目錄存放系統(tǒng)功能的LUA文件及M(model)、V(view)、C(controller)文件夾,當(dāng)燒錄到硬件設(shè)備后,將拷貝到/usr/lib/lua/luci目錄下

          C(controller):控制器,生成頁面的菜單欄并定義各個(gè)頁面的調(diào)用方法
          M(model):數(shù)據(jù)模型,根據(jù)底層UCI配置文件生成頁面
          V(view):視圖,HTML頁面

          3、po:定義頁面的語言風(fēng)格

          4、root:存放配置文件,該目錄下的所有文件將拷貝到硬件設(shè)備根目錄下

          5、src:生成所需要的庫文件及LUA腳本

          6、Makefile:定義luci-base的編譯方法

          二、luci-mod-admin-full目錄

          由此可以看出,LUCI的文件框架都是以luci-base目錄為基礎(chǔ),其他主題及模式都是在此基礎(chǔ)之上進(jìn)行增減。

          三、/www目錄結(jié)構(gòu)

          cgi-bin:此文件從luci-base下拷貝過來的,存放luci啟動(dòng)腳本
          index.html :http請(qǐng)求的主頁面,默認(rèn)是/www/index.html,這個(gè)文件里顯示了登錄時(shí)常看見的那句話“LuCI - Lua Configuration Interface”,同時(shí)也指定了href鏈接/cgi-bin/luci
          luci-static:存放HTML相關(guān)文件,包含CSS、JS及網(wǎng)頁圖片等文件。不同主題的htdocs/luci-static都將拷貝到這個(gè)目錄下

          四、/usr/lib/lua/目錄結(jié)構(gòu)/

            usr/lib/lua/路徑,顧名思義,存放了與LUA相關(guān)的文件,在LUA腳本中,通過require命令引用的腳本及函數(shù),起始路徑都是該目錄。同時(shí),不同模型及主題的luasrc文件夾都拷貝到/usr/lib/lua/luci目錄下,通過/etc/config/luci中的mediaurlbase字段決定當(dāng)前使用的主題及語言。

          果你經(jīng)常需要從GitHub上Pull一些開源的項(xiàng)目啥的!國外的服務(wù)器還好,但是國內(nèi)的服務(wù)器就非常慢了!經(jīng)常是下不動(dòng)或者只有 10KB 的速度。

          這篇文章就來分享幾個(gè)特別簡單的可以加速GitHub 下載的方法,雞肋的方法就不介紹了。

          1、利用Gitee加速訪問GitHub倉庫

          1.1、關(guān)于Gitee

          官網(wǎng):https://gitee.com/

          OSCHINA 推出的代碼托管·協(xié)作開發(fā)平臺(tái),開發(fā)者超過 500 萬,托管項(xiàng)目超過 1000 萬,匯聚幾乎所有本土原創(chuàng)開源項(xiàng)目,并于 2016 年推出企業(yè)版,提供企業(yè)級(jí)代碼托管服務(wù),成為開發(fā)領(lǐng)域領(lǐng)先的 SaaS 服務(wù)提供商。

          支持 Git / SVN,個(gè)人版免費(fèi)5G倉庫容量。

          1.2、部署流程

          1)注冊(cè)賬號(hào)

          2)登陸Gitee賬號(hào),擊右上角新建倉庫的“+”,選擇 【 從 GitHub / GitLab 導(dǎo)入倉庫】或者【進(jìn)入https://gitee.com/login注冊(cè)】

          3)填寫要導(dǎo)入的項(xiàng)目即可(如果之前有人導(dǎo)入過該倉庫,可以直接復(fù)用他的倉庫即可)。

          4)等待項(xiàng)目成功導(dǎo)入碼云后,直接從碼云將項(xiàng)目 clone 到本地,速度非常快

          對(duì)比之前github的速度。

          2、GitHub代下載服務(wù)

          1、網(wǎng)址:http://g.widora.cn/

          • 示例1: GitHub主倉庫 https://github.com/aaaa/bbbb.git
          • 示例2: GitHub分支用示例1的鏈接,下載完后到本地用git checkout出任意分支或tag
          • 示例3: Release頁面右鍵復(fù)制的鏈接,例如 https://github.com/openwrt/luci/archive/0.10.0.zip
          • 示例4: 其他源碼包的直鏈,例如 https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.7.tar.xz

          2、網(wǎng)址:https://d.serctl.com/

          使用方法和上面一樣,具體看圖:

          3、http://toolwa.com/github/

          用法和上面類似,這里不在贅述。

          3、VPS中轉(zhuǎn)

          前提是你有一臺(tái)國外的vps,你把項(xiàng)目git到你的vps上,然后再從自己的vps里面下載項(xiàng)目,速度也會(huì)不錯(cuò)。比如說你安裝了寶塔,可以利用寶塔面板自帶的外鏈分享來實(shí)現(xiàn)下載。

          4、富強(qiáng)、民主、自由、和諧

          前提是有一臺(tái)境外的vps,搭建一個(gè)工具,然后,設(shè)置全局服務(wù),git的速度也是很快的。這個(gè)方法這里就不討論了。

          5、最后

          方法都有缺陷,最好的就是最后一種方法,用Gitee的話,如果是最新版本還需要去github下載。

          如果你有自己vps,那么可以先clone到VPS上,然后再拉回來。

          利用第三方工具來下載也是個(gè)不錯(cuò)的方法。

          還有一種cdn加速方法,就是尋找github的加速地址即可,不過,這個(gè)方法有點(diǎn)啰嗦了,不符合簡潔好用的范疇,這里也就不討論了。

          如果你有更好的方法,不妨留言分享。

          原文鏈接:https://www.haah.net/archives/4103.html


          主站蜘蛛池模板: 国产91精品一区| 亚洲欧美日韩中文字幕在线一区| 无码少妇一区二区三区芒果| 亚洲va乱码一区二区三区| 亚洲美女一区二区三区| 国产日韩精品视频一区二区三区| 免费高清av一区二区三区| 精品国产一区二区麻豆| 一区二区三区免费精品视频| 久久精品国产一区二区三区 | 国产成人一区二区三区在线观看| 日本免费一区二区久久人人澡| 麻豆一区二区在我观看 | 精品动漫一区二区无遮挡| 无码av中文一区二区三区桃花岛| 成人国产精品一区二区网站| 亚洲AV无码一区二区三区DV| 亚洲综合av一区二区三区| 亚洲第一区在线观看| 亚洲天堂一区二区| 日本一区二区三区不卡在线视频| 一区二区三区杨幂在线观看| 一区二区三区国产精品| 国产在线一区观看| 国产成人一区二区三区在线观看| 无码日韩人妻av一区免费| 熟女少妇精品一区二区| 成人毛片一区二区| 亚洲AV无码一区二区乱孑伦AS| 无码午夜人妻一区二区不卡视频| 中文字幕精品无码一区二区| 无码精品一区二区三区| 中文字幕一区二区三区永久| 国产一区二区三区韩国女主播| 久久精品国产一区二区三区| 无码喷水一区二区浪潮AV| 肉色超薄丝袜脚交一区二区| 一区二区高清在线观看| 国产福利日本一区二区三区| 国产伦精品一区二区三区| 日本一区二区三区在线视频|