🌟?各位看官好,我是egoist2023!
🌍?Linux == Linux is not Unix !
🚀?今天來學習命令行參數與環境變量的相關知識。
👍?如果覺得這篇文章有幫助,歡迎您一鍵三連,分享給更多人哦!
目錄
命令行參數
意義
環境變量
羅列Linux環境變量
PATH
OLDPWD
PWD
多方法獲取環境變量
main函數獲取
?編輯
getenv獲取
environ獲取
?編輯
我的進程如何獲取環境變量?
環境變量全局屬性
內建命令
命令行參數
main函數可以有參數嗎?可以有幾個參數呢?參數又是什么呢?帶著這三個疑問往下閱讀。
int main(int argc,char *argv[])
{printf("hello linux!\n");return 0;
}
我們或多或少在別人的程序中見過這種代碼,清楚main函數是可以帶參數的,并且可以有兩個參數(實際上可以有3個參數,第3個是環境變量表)。那么這兩個參數各代表什么含義呢?
- argv是一個指針數組,它指向一個一個的字符串,最后以NULL結尾;
- argc用來記錄argv[]的元素個數。
我們的命令行參數會放到命令行參數表上,即argv,它用來存儲命令行參數的每個單獨的字符串。
意義
為什么要有命令行參數表呢?它能帶來的意義又有哪些呢?
- 命令行參數傳遞:借助主函數的參數,能把命令行中用戶輸入的參數傳遞到程序內部,這樣程序就能依據不同參數執行不同操作。
- 程序靈活性提升:無需對代碼進行修改,通過命令行參數就能改變程序的運行方式或者配置信息。
從這兩方面我們并不能體會到啊?因此小編寫了段程序解釋命令行參數帶來的意義:
下圖中寫了一段程序,它借助main函數參數,讓命令行參數傳遞的時候,通過匹配不同的命令行參數,如果第二個參數帶的是v1則實現v1版本,帶的是v2則實現v2版本,從而實現不同版本的邏輯,這帶來的意義就是命令行參數傳遞實現不同的邏輯,同時我們也可以限制如果傳遞的命令行參數不符合我們的邏輯,則不能通過,提升了程序靈活性。
?💻如圖實現:?
有沒有一種可能我們之前所說的選項就是這樣實現的呢?
是的沒有錯,Linux中許多指令也是借助了命令行參數才得以支持多模塊實現,如ls指令。
ls -l -a -i
?ls的命令本質是一個程序,而我們之前說ls后面的是選項,今天我們對選項能有更深的理解,它是通過命令行參數匹配從而實現我們的目的。
-l 、 -a 本質是字符串,以一定的方式傳遞給ls內部的"main",在ls內部實現的時候,就可以根據不同的選項,實現類似功能的不同表現形式。
因此我們對指令又有了進一步的理解:指令是特定目錄上執行的二進制程序,而選項則是根據不同的參數傳遞給"main",實現不同表現形式.
環境變量
引出概念:
- 環境變量(environment variables)?般是指在操作系統中?來指定操作系統運?環境的?些參數。如:我們在編寫C/C++代碼的時候,在鏈接的時候,從來不知道我們的所鏈接的動態靜態庫在哪?,但是照樣可以鏈接成功,?成可執?程序,原因就是有相關環境變量幫助編譯器進行查找。
- 環境變量是系統級別的一些全局變量,具備不同的用途(這也是為什么要有環境變量的原因)。
羅列Linux環境變量
那么該如何查看環境變量呢?
env 可以用來查看環境變量 , 這里主要講三個重要的環境變量:PATH、OLDPWD、PWD.
- PATH : 指定命令的搜索路徑
- HOME : 指定用戶的主?作?錄(即??登陸到Linux系統中時,默認的?錄)
- SHELL : 當前Shell,它的值通常是/bin/bash。
PATH
我們前面說過,指令也是一個可執行程序。為什么有些指令可以直接執?,不需要帶路徑,?我們自己的?進制程序需要帶路徑才能執行啊( 否則會報找不到 )這是為什么呢?
通過which命令查看ls所處的路徑,可以看到是在/usr/bin的路徑下。 什么意思呢 ? 即OS要執行該指令時,就需要/usr/bin路徑,那么由誰給它提供呢 ? OS默認會在PATH路徑下查找,若沒有則會報錯。而/usr/bin被包含在PATH環境變量中。
- 因此我只要證明 /usr/bin 不在PATH中時,此時再使用 ls 指令會向我們執行自己的程序一樣報沒有找到 ;
- 或者將我們自己的程序添加到PATH中,再執行自己的程序,若不會報錯, 即可證明OS是在PATH中查找的。?
?
💻擴展:
PATH的環境變量改變了,該怎么進行復原呢?重啟xshell即可,因為環境變量是內存級的。?
OLDPWD
OLDPWD環境變量用來記錄當前用戶最近一次所處路徑。
💻證明: echo $OLDPWD可以展示最近一次所處路徑.
??
PWD
這里總算可以解釋pwd指令的原理了:
我們知道每個進程(包括xshell啊!)都會記錄自己所處的工作路徑,這在之前是已經驗證過的.那么我們的PWD環境變量又從哪里而來呢??
pwd 會讀取 當前進程所處的cwd.
💻pwd指令原理:
當你在 shell?里輸入?pwd,其實是啟動了一個新的進程,它繼承了父進程(你的 shell)的 cwd 。pwd 進程通過系統調用(如?getcwd())讀取自己的?cwd,然后把它打印出來。由于?pwd?進程和你的 shell 進程的 cwd 是一樣的,所以你看到的就是你當前 shell 所在的目錄。
多方法獲取環境變量
獲取環境變量的方法有很多,這里主要介紹三種:
main函數獲取
我們前面說了main函數是可以帶3個參數的,而第3個參數則是環境變量表.下圖中
💻模擬實現env指令:
getenv獲取
getenv是C語言庫提供的函數,它可以用來獲取單個環境變量。
environ獲取
我的進程如何獲取環境變量?
我們大部分的指令以及自己實現的可執行程序,都不是有bash幫我們執行的,而是bash通過創建子進程的方式,讓子進程繼承了bash的環境變量,形成環境變量表。
問題1:為什么子進程可以繼承bash的環境變量?
環境變量表是數據嗎?是數據,并且是父進程的數據。子進程通常會繼承父進程的代碼和數據為副本,因此可以繼承bash的環境變量。
問題2:bash從哪里獲得環境變量的?
bash從系統的配置文件中獲取,先會malloc環境變量表,解析配置文件的內容,把環境變量字符串依次放入到環境變量表里。
那么這就意味著bash一定會有兩張表:
命令行參數表(一直在變)+ 環境變量表(比較穩定,內存級)
💻驗證:
我們可以更改配置文件的信息,寫入一段echo "哈哈,這個配置文件被執行了" 。則每次啟動xshell時,bash都會從這個配置文件中形成環境變量表,在顯示器上打印我們寫入的信息。
?
?
輸出結論:bash獲取環境變量有兩方面:配置文件 + 動態形成。?
環境變量全局屬性
- echo:顯示某個環境變量值
- export: 設置?個新的環境變量
- unset: 清除環境變量
- set: 顯?本地定義的shell變量和環境變量
環境變量是具有全局屬性的,可以被子進程繼承下去;
相對應的本地變量是不具備全局屬性的,這種變量是不能被子進程繼承。
💻下圖中證明本地變量是不可以被子進程所繼承的:
MYENV是本地變量,執行程序時bash創建子進程,子進程以父進程為副本進行繼承,包括環境變量.假設本地2變量可以被繼承下去,那么getenv獲取該變量,如果打印該變量不存在說明本地變量是不能被繼承下去的.
?
內建命令
我們知道命令是可執行程序,其中的大部分命令需要通過創建子進程的性質執行。
那么肯定也存在一些命令是不需要通過創建子進程來執行,而是由bash來執行.那么這個命令在執行的時候是沒有風險的.我們把這種命令叫做內建命令!!!?
💻echo 指令: 無論是本地變量還是環境變量,echo都能顯式變量值。
我們說本地變量是不能被子進程繼承下來的,說
明本地變量只在bash自 身有效,如果能打印出該變量的值,恰恰說明echo指令是一個內建命令。??
?
?