Python3.6 pip install vs sudo pip install

Ubuntu 18.04 Linux學習心得

Gopher is cute
Caesar's study review on Web development
12 min readMay 23, 2018

--

我想轉職成為web開發者,先前在微軟win10的環境學習Python與Git,時常遇到編碼及換行CRLF的問題,於是有了學習Linux的心情,想深入軟體開發領域,我認為不能死守在自己最熟悉的微軟環境。

使用Virtual Box安裝了Ubuntu 18.04,學習Linux的目錄結構 (Filesystem Hierarchy Standard,FHS),了解Linux的權限問題以及環境變數$PATH、$HOME的作用。

(此篇心得為個人領悟,若有錯誤請告知)

利用pipe | (I/O Redirection)結合ls指令與grep指令,查詢Ubuntu原生系統的執行檔/usr/bin及函數庫/usr/lib,存在哪些Python函數庫。

ls -l /usr/lib | grep python

從上圖可得知,Ubuntu 18.04原生系統存在著Python3.6及Python2.7的函數庫,有了函數庫,執行檔才可以作用。

而Python3與3.7其實並非主要函數庫,實際查看相關目錄就可以發現,裡面只存在輔助性質的檔案,python主要運作還是依靠Python3.6及Python2.7。

ls -l /usr/bin | grep python

/usr/bin所找到的檔案也就是所謂的二進位檔案,在Bash中我們打的指令都必須存在於/bin的相關目錄,才可以使用。

舉例來說,/usr/bin可以看到有python3、python3.6、python3.6m...等等,打指令python3時會導向到python3.6,若你打指令python2或python系統會告訴你找不到相關command。

即使你有python2.7的函數庫,但只要執行檔沒有,就無法利用。

藉由安裝python的套件管理工具pip,讓我更了解Linux的基本運作過程,首先安裝pip,在Bash中打指令;

sudo apt-get install python3-pip

由於Linux原生就有安裝Python3.6及Python2.7,Python3以上的版本請安裝 python3-pip 其工具為 pip3 ,而Python2.7的版本請安裝 python-pip 其工具為 pip。

apt-get是 ubuntu官方的套件管理工具,由apt-get所安裝的套件其預設目錄為/usr/bin,安裝pip3後,可利用whereis 指令查詢,其所在的目錄。

/usr/bin/ 在Linux的目錄下,其權限屬於root,一般使用者帳號無法對該目錄做檔案刪除或是寫入,於是需要加上指令 sudo ,以root的身分進行安裝。

若你為一般使用者帳號不加上指令 sudo,直接使用apt-get,只會得到不符權限的訊息,因為apt-get試圖對root權限的目錄做讀寫,而你現在的身分只是一般帳號,在Linux中,權限是很重要的且必須了解的基本觀念。

若是對於Linux的目錄結構有興趣了解,可參考以下連結

pip與apt-get類似,一樣是套件管理工具,只不過pip是屬於第三方管理工具,專門安裝與python有關的套件,而apt-get是官方的套件管理工具,藉由第三方軟體所安裝的套件,其預設目錄為可分為兩種;

  1. 系統端( /usr/local/)
  2. 用戶端(/home/<username>/.local/)

假設我們現在要透過pip3安裝jupyter notebook,若希望安裝在系統端則要打指的指令如下,且其安裝目錄為 /usr/local/lib/

sudo -H pip3 install jupyter

所謂裝設在系統端的意思是說,若該台電腦還有其他使用者,所有的使用者都可以使用系統端安裝的套件,但是通常不建議這麼做,由於root權限是最高級的,透過第三方管理工具安裝的套件,可能會有資安上的疑慮,因此通常建議將第三方套件裝在用戶端。

至於 -H 的參數是什麼意思,這就牽涉到環境變數$HOME的問題,$HOME儲存了使用者的家目錄路徑,也就是說$HOME=/home/<username>/,首先要了解pip在安裝套件時,會讀取$HOME環境變數,得到家目錄的路徑後,在家目錄底下創造/.cache/pip/來進行緩衝下載的動作。

若你打指令為 sudo pip3 install jupyter 那系統會提出警告,但不會影響套件安裝,不過安裝套件的速度可能會慢了一點?

警告訊息:
The directory ‘/home/caesar/.cache/pip/http’ or its parent directory is not owned by the current user and the cache has been disabled. Please check the permissions and owner of that directory. If executing pip with sudo, you may want sudo’s -H flag.

這個警告訊息意思是說,由於使用了sudo指令,你現在的身分暫時為root,但是$HOME依舊是家目錄的路徑,你的身分為Root而家目錄的owner為一般使用者,雖然root有足夠的權限對一般使用者的目錄進行讀寫,但是系統不想在家目錄底下建立一個root權限的/.cache/目錄。

家目錄底下應該權限只能有一般權限,若是出現一個root權限的目錄,往後若有其程式需要讀取該目錄,則會被禁止訪問,為了避免此情況以及統一家目錄權限為一般權限,因此這個警告說明了,此次安裝不使用緩衝下載的模式(the cache has been disabled)。

回到-H,若使用指令sudo 加上參數-H,則會改變環境變數$HOME的值,將$HOME的值從家目錄的路徑改為/root目錄,如此就可以使用緩衝下載的功能,又不會影響家目錄的權限完整性,可由以下例子簡單說明sudo -H的功能

echo $HOME $USER
/home/caesar caesar

sudo bash -c 'echo $HOME $USER'
/home/caesar root

sudo -H bash -c 'echo $HOME $USER'
/root root

其他相關討論可以參考 stackoverflow

也可能是ubuntu本身的BUG?

談完了系統端的安裝,再來談談若是希望安裝jupyter notebook在用戶端則要打指的指令如下,且其安裝目錄為/home/<username>/.local/lib/

1. pip install jupyter --user
2. pip install jupyter

指令1跟2,我在Ubuntu實測並沒有查詢到差異處,猜測對Mac的用戶才有區別,在用戶端安裝的套件只有該使用者可以使用,別的使用者無法使用。

一開始我安裝第一個第三方套件在用戶端時,我一直以為安裝失敗,因為系統一直找不到jupyter的指令,前面有說過要使用指令,必須在/usr/bin或/usr/local/bin或/home/<username>/.local/bin/有相關檔案才可以使用,之後才發現是環境變數$PATH的問題。

環境變數$PATH,儲存了許多路徑,作業系統會讀取$PATH的值,依序讀取路徑查詢執行檔,簡單來說$PATH代表著「系統要到哪些路徑底下找執行檔」。這樣講可能太過抽象,以下舉例

caesar@Ubuntu-VirtualBox:~$ echo $PATH
/home/caesar/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

上述例子可知$PATH儲存了10個路徑,每個路徑以冒號:分隔,假設現在我想要執行jupyter指令,系統會根據$PATH首先尋找/home/caesar/.local/bin,若在該路徑沒有發現jupyter的bin檔,接下來會尋找/usr/local/sbin,依此類推直到搜尋所有$PATH儲存的路徑,若所有路徑都搜尋完,依舊沒有在這些路徑發現jupyter的bin檔,系統就會提示Command ‘jupyter’ not found

仔細觀察可以發現,$PATH儲存的路徑從最前面開始,依序為用戶端,之後才是系統端,也就是說系統會優先讀取用戶端的資料,若在用戶端就讀取到相關檔案後,系統則停止讀取$PATH的路徑,藉此打造個人化的設定及安裝環境。

那麼$PATH路徑的資料是從哪邊讀取或擴增的呢?這就要提到bash 的環境設定檔, bash 在啟動時直接讀取這些設定檔, 其中又可以分為系統端及用戶端的設定檔。

介紹 bash 的設定檔前,我們要先知道的就是 login shell 與 non-login shell! 重點在於有沒有登入 (login) !詳細介紹請參考鳥哥的私房菜。

login shell 讀取這兩個設定檔

  1. /etc/profile:這是系統整體的設定,最好不要修改這個檔案
  2. ~/.profile 或~/.bash_login或~/.bash_profile :屬於用戶端的設定

bash 在讀完系統端 /etc/profile的設定,並藉此呼叫其他設定檔後,接下來是會讀取用戶端的設定檔。我的ubuntu 18.04中,bash用戶端的設定檔為~/.profile,部分內容如下

簡單說明以下內容,指令 -d: 該『檔名』是否存在且為目錄,若存在該目錄則執行以下動作PATH=”$HOME/bin:$PATH”,此動作為擴增環境變數$PATH。

而non-login shell 僅會讀取

  1. ~/.bashrc :規範了較為保險的命令別名
bash設定檔讀取流程

回到一開始所說,安裝第一個第三方套件在用戶端時,一直找不到jupyter的指令。這是因為login shell登入時,$HOME/.local/bin的目錄還不存在,因此$PATH不會擴增此路徑($HOME/.local/bin)。

直到安裝第一個第三方套件在用戶端時,~/.local/bin的目錄才生成,此時的$PATH並沒有加入~/.local/bin,故執行jupyter指令系統才會說找不到該指令,解決的辦法為重新登入一次,讓bash重新套用login shell設定,就可以正常執行jupyter的指令了,或者選擇export PATH也可以。

此情況只會發生在第一次安裝第三方套件在用戶端,之後由於目錄生成了,往後$PATH就會依照bash的設定擴增此路徑,但對於剛學習Linux的我,一開始一直以為自己安裝失敗,看了很多Linux的資料才明白發生此錯誤的原因。

以上為我學習Linux的心得,老實說覺得自己似乎有點太鑽牛角尖,感覺對於學習WEB開發並無太多幫助,可能以後架node.js環境比較清楚自己在做什麼吧?我又不是要當devops 也沒有想搞維運,但個性上就是想把基本的東西搞清楚。

恰巧最近在公司寫C程式用到了multi-thread的概念,學習Linux時有看到工作管理 (job control)的資料,藉由操作指令 jobs、將背景工作拿到前景來處理:fg、將指令丟到背景中『執行』的 &,學到一些 Process概念,讓我在學習multi-thread時更加明白程式想表達的意思,multi-thread似乎是作業系統的基本觀念,看來日後也是要補起作業系統這門學科。

之後心力會放在資料結構以及Javascript,報名了appwork school的前端課程,還沒收到面試通知,擔心著是否我的努力還不足,連面試資格都不能獲取,非本科真的好多東西要學,很希望可以藉由appwork school加速腳步。

--

--

Gopher is cute
Caesar's study review on Web development

我的第一份後端工作結束了,短短四個月,部門全員掰掰,尋找新的機會。