1. 程式人生 > >跟濤哥一起學嵌入式第12集:關於 apt-get 軟體安裝那些事兒

跟濤哥一起學嵌入式第12集:關於 apt-get 軟體安裝那些事兒

對於很多linux/ubuntu新手來說,要想在Ubuntu系統上熟練地安裝、升級、解除安裝軟體,確實是挺考驗人的一件事,會遇到各種各樣的問題,有時候會把人搞得很不耐煩,打擊人的學習積極性。Ubuntu一般使用apt-get命令 (ubuntu16.04版本以後可以簡寫為apt) 來安裝、升級、解除安裝軟體。比如我們想安裝一個軟體,常用下面的命令進行安裝:

    $  apt-get install xxx
    $  apt-get update
    $  apt-get upgrade

順利安裝還好,但有時候還是會遇到各種各樣的問題,雖說有時候能通過網際網路解決掉,但是對於 apt-get 如何安裝的卻不是很清楚,比如什麼是軟體源,就沒有啥概念。本文目的就是跟大家一起了解下Ubuntu環境下 apt-get 的軟體安裝基本原理。


想要了解apt-get的工作原理,首先我們要明白軟體的安裝是怎麼回事。我們知道一個程式的執行,一般是要先載入(load)到記憶體(RAM)中,因為RAM儲存器支援隨機讀寫,因此CPU可以一條一條地去取指令、翻譯指令、執行指令。但是RAM有一個缺點,就是斷電後資料會消失,無法儲存。因此,我們需要將程式檔案儲存到一個非易失性儲存器上,比如硬碟、NAND Flash上,斷電後資料也可以儲存。把程式儲存到磁碟上的過程其實就是軟體的安裝過程,早期的微控制器裸機環境,程式一般都是使用專門的工具直接燒寫到Flash上的,後來有了OS和檔案系統,我們可以很方便的通過滑鼠,直接將程式檔案安裝到某個檔案目錄下面,程式在執行時,系統就可以直接到這個目錄下面找到對應的二進位制檔案,載入到記憶體,然後就可以直接運行了。


無論是Windows還是Linux,基本流程都是如此:告訴系統你的程式二進位制檔案存放到哪裡了,然後程式在執行時,系統就會到這個指定的路徑下面去找你要執行的二進位制程式檔案,載入到記憶體,然後執行。在Windows下面,你安裝好軟體後,在桌面上會有一個快捷方式,其實就是指向你安裝路徑的軟連結。在Linux環境下面,我們要執行的程式一般是放在預設的路徑下面的,如:/bin、/sbin、/usr/bin、/usr/sbin等。比如你在shell下面執行:$ ls

命令時,系統就會到這些預設的路徑下面去尋找ls檔案,在/bin/ls下面找到後,就會載入到記憶體,然後 ls 程式就可以運行了。

我們寫一個簡單的helloworld程式,編譯為a.out,我們可以直接執行它:

    $ ./a.out

為什麼不能直接執行$ a.out呢,因為我們的a.out沒有安裝到預設路徑,因此執行時,你要指定路徑資訊,否則系統就找不到。你把a.out放到預設的/usr/bin下面,然後就可以直接通過$ a.out檔名去執行程式了。當然,你可以可以把自己編譯的a.out二進位制檔案放在自定義的某個目錄下面,然後以環境變數的形式告訴系統這個安裝路徑,當系統在那些預設路徑下面找不到時,會到這個安裝路徑下查詢。


我們在Linux環境下安裝軟體時,最簡單的方法是從網上下載這個二進位制程式檔案,放到Linux系統中的預設路徑下面就可以了。但是有些程式是採用動態連結編譯的,執行時需要依賴一些動態共享庫,因此需要打包一起安裝。我們下載的軟體一般很少是一個單純的二進位制檔案,而是壓縮包的形式,在這個壓縮包裡有:二進位制程式檔案、動態連結庫、軟體文件說明、安裝資訊、甚至有一些自動安裝的指令碼等。在 Debian 和 Ubuntu 環境下,這個壓縮包格式為deb格式,我們安裝軟體時,先從網上下載對應的deb包,然後可以使用dpkg工具去解析這個包、安裝這個包。

$ dpkg -i xxx.deb   安裝xxx.deb軟體包
$ dkpg -R /home/xxx   安裝xxx目錄下的多個deb包
$ dkpg -r xxx   解除安裝xxx軟體包

當然你也可以將自己的二進位制程式製作成一個deb安裝包,放到網上,供其他人下載安裝:

$ apt install checkinstall dh-make
$ ./configure --prefix=/home/tools //配置編譯資訊
$ make  //編譯你的程式
$ checkinstall  //製作deb包
$ dkp -i xxx.deb //安裝deb包

因為每個人都可以編譯、製作deb包、並隨意釋出到網上,這就很容易造成混亂,魚龍混雜、質量得不到保證,甚至有些包還有可能是一個病毒軟體。因此Ubuntu系統採用一個軟體倉庫來管理這些deb軟體包,把這些包放到一個官方的網站伺服器上,類似於蘋果系統的APP store,使用者使用apt命令安裝軟體時,只能到這個伺服器上下載軟體。考慮到全球各個地方的網路環境差異,往往會在全球各地同時配置幾個映象伺服器,這樣全球各地的Ubuntu使用者都可以根據網路狀況到最合適的伺服器上去下載和安裝deb軟體包了。這些伺服器我們也稱為軟體源 (Reposity) 或者簡稱為“源”。

這些伺服器的網路地址儲存在/etc/apt/source.list檔案中。檔案內容如下所示:

deb http://us.archive.ubuntu.com/ubuntu/ xenial universe

當我們使用apt install安裝軟體時,apt工具就會根據這個source.list檔案中的網路地址,選擇最合適的伺服器去下載軟體包。

一般Ubuntu預設的軟體源是Ubuntu官方網站,開啟上面的網址,你會發現上面存有很多軟體包的資訊。

小Q截圖-20181126133506.png

對於國內使用者來說,訪問國外的網站速度可能會慢很多、甚至無法訪問。國內高校和網際網路公司其實也有很多伺服器提供下載,大家百度搜索一下:阿里雲軟體源、中科大軟體源,一般都會搜尋到很多伺服器地址,可以選擇其中幾個,新增到/etc/apt/source.list檔案中,以後使用apt-get安裝軟體時,就可以直接從國內的伺服器上直接下載deb包了,速度會快很多。

修改好/etc/apt/source.list檔案後,你還需要使用$ apt-get update命令更新一下。這個命令的作用訪問 /etc/apt/source.list 檔案中的每一個伺服器,讀取可以支援下載安裝的軟體列表,並儲存到本地電腦中(/var/lib/apt/lists)。這個列表就像飯店裡的選單一樣,要按照選單去點菜,直接使用apt install xxx 就可以直接安裝軟體了。如果你要安裝的軟體如果不在軟體列表中,很可能就安裝失敗。

軟體列表的另一個作用是可以幫助你軟體更新,因為伺服器上的軟體版本也會不斷更新,你本地已經安裝的軟體如果跟軟體列表中的軟體版本不一致,它可能就會提示你軟體需要更新,就像我們PC中的軟體管家一樣,它會提示你,你的電腦中有多少個軟體可以更新。

小Q截圖-20181126135019.png

當然,你也可以使用apt list命令去檢視具體需要更新的軟體包:

小Q截圖-20181126135137.png

接下來,如果你想更新這些已經安裝的軟體,就可以通過$ apt-get upgrade命令來完成。這個命令會將本地已經安裝的軟體與剛剛使用update命令下載到本地的軟體列表進行對比,如果發現版本不一致,就會重新安裝最新的版本。如果你的系統需要更新的軟體包太多,這個可能需要一定的時間,耐心等待就可以了,升級成功後,一般會有提示資訊,你升級了多少個軟體包...


使用apt安裝軟體的另一個好處是可以自動處理依賴關係。比如你想安裝一個B,需要依賴A,那麼你安裝B的同時,B所依賴的A軟體包也會自動安裝上了。在/var/lib/dpkg/available檔案中,有詳細的軟體包資訊,包括軟體版本、軟體依賴的包等。包括在視訊教程《使用QEMU搭建嵌入式U-boot+Linux+NFS開發環境》中,很多學員反饋說,為什麼我的環境跟視訊中的不一樣?這是因為每個Ubuntu版本不同、安裝的軟體不同,安裝的庫、標頭檔案也不一樣,大家在編譯的時候如果遇到一些無法識別的命令、缺少一些標頭檔案,直接安裝對應的工具和庫就可以了,隨著你的Ubuntu系統安裝的一些依賴庫、工具越來越多,以後再編譯其它軟體時,一般都可以順利編譯了,因為很多依賴的庫檔案、標頭檔案、工具、命令等都安裝得差不多了。


對於一個新手。在使用apt-get安裝軟體時,經常遇到的問題很多,比如許可權不夠,使用sudo、或切換到root安裝可以解決這個問題。無法獲取軟體包,網路訪問不了,可以在/etc/apt/source.list檔案中新增國內的一些映象伺服器地址(軟體源)。還有一個經常遇到的問題是:

E: 無法獲得鎖 /var/cache/apt/archives/lock

直接刪除這個檔案就可以了,對應的還有 /var/lib/dpkg/lock檔案,順便也刪除掉,一般就可以解決問題。在安裝的過程中,如果遇到其它問題,建議先到百度裡搜一搜,你遇到的問題、踩到的坑,前面可能已經有無數人遇到過了,看看它們是怎麼解決的,一般都可以解決問題。


最後,當你安裝的軟體在伺服器中確實沒有時,這就需要你手動下載原始碼、編譯安裝了,一般在Linux系統中,可以直接下載GNU工程開原始碼,然後直接通過三步走,就可以直接編譯和安裝了:

$ ./configure$ make$ make install