一、概念介紹(來源:比特就業課)
-
環境變量一般是指在操作系統中用來指定操作系統運行環境的一些參數
-
環境變量通常具有某些特殊用途,并且在系統中通常具有全局特性
二、現象引入與解答
1.為什么像ls這樣的系統指令可以直接執行,而我們生成的可執行程序不能像這樣運行呢,而應該寫成路徑+文件名的形式呢?
解答:因為系統指令ls會自動默認的去環境變量PATH中去查找,若能夠在眾多路徑下找到,便能夠成功執行,否則報以上錯誤。可以見一見:
可以看到ls是可以找到的,PATH環境變量的值中路徑用:分隔,查找時從左到右依次查找。(解決方法最后)
2.main函數有沒有參數呢?
解答:其實是有的,那么參數有哪些呢?這里我把他們全部展示出來,見如下:
3.這些參數是由哪個傳遞的呢?
解答:其實是該程序的父進程Shell(bash)傳遞的。
4.前連個參數具體代表什么呢?
解答:我們在命令行中輸入的任何指令,比如“ ls -a -l”都是以字符串(整體)的形式給到bash進程進行分割處理,得到“ls”, “-a”,“-l”,然后用一個char* argv[]把分割的字符串給管理起來,這樣一張表就叫做“命令行參數表”,“ls”就是我們要執行的程序,“-a,“-l”是選項,用于實現該程序的不同的子功能,其中argc就是分割后字符串的個數,argv用NULL結尾,表示參數傳遞完畢。為了能夠更形象,可見下圖:
5.最后一個參數代表什么呢?
解答:首先我們需要明確,要執行一個程序,必須先找到它,其次系統中的環境變量(PATH)是用來幫助系統找到要執行的目標二進制文件,是系統中搜索指令的默認搜索路徑!環境變量的形式為:名稱=內容(這種類似鍵值的形式)。如何理解環境變量呢?需要從存儲的角度,即bash會形成一張環境變量表,該環境變量表同命令行參數表一樣也是char* argv[]類型的,那么環境變量,最開始是從哪里來的呢?答案是從系統的相關配置文件中來的,見圖如下:
舉例說明:比如執行ls命令就回到PATH中去找,又比如cd ~指令,就會找到HOME這個環境變量。
結論:bash會有兩張表,一張叫命令行參數表argv,另一張叫環境變量表env。(重要)
推導:如果Linux系統有10個用戶登錄,就存在10個bash,那么每個bash都會有從配置文件中來的環境變量,形成一張環境變量表
三、獲取環境變量的方法
指令方式:
①export 環境變量(需要注意的是,export屬于內建命令,不會創建新進程,export會被bash直接執行,調用相關的系統調用)
②env(直接運行該指令便可以看到所有的環境變量,如果做了第一個操作,那么也可在看到)
③echo $環境變量(直接顯示該環境變量的內容)
④unset 環境變量 (直接刪除該環境變量)
代碼方式:
①方法一:父進程(bash)的環境變量可以被子進程繼承
②方法二:使用getenv()
③方法三:extern char** environ,使用全局指針(需聲明)
四、理解環境變量的特性
①環境變量具有全局特性
②bash會記錄兩套變量:環境變量、本地變量(本地變量不會被子進程繼承,只會在bash內部被使用)
五、認識更多的環境變量
常見的:
HOSTNAME:主機名
TREM:終端類型(如xterm、xterm-256color、screen、vt100等)
SHELL:命令行解釋器的類型
USER:用戶名
PATH:默認搜索路徑
PWD:記錄當前用戶所在的路徑
HOME:家目錄
LOGNAME:登錄用戶名
OLDPWD:記錄舊的路徑(舉例:cd -)
HISTSIZE:定義Shell歷史命令巨鹿的最大條數
LANG:定義系統的默認語言和字符編碼
六、解決方法
①方法一:直接將程序移動到PATH環境變量中的任何一個路徑下
②方法二:直接將程序所在的路徑追加到PATH環境變量值之后(例:export PATH=$PATH:想要添加的路徑)
③方法三:修改配置文件.bash_profile(適用于登錄Shell)/.bashrc(適用于交互式Shell)
echo 'export MY_VAR="value"' >> ~/.bash_profile
source ~/.bash_profile
echo 'export MY_VAR="value"' >> ~/.bashrc # 追加到文件末尾
source ~/.bashrc # 立即生效(無需重啟)
方法四:使用export直接設置
export MY_VAR="value" # 設置環境變量
echo $MY_VAR # 檢查是否生效
//特點:
//僅在當前 Shell 及其子進程(如新開的終端、腳本)中有效。
//重新連接 SSH 后會消失(因為新會話會重新加載 Shell 配置文件)。
七、相關代碼
#include<stdio.h>
#include<stdlib.h>
//main有參數嗎?有
#include<unistd.h>
int main(int argc,char* argv[],char* env[]){(void)argv;(void)argc;(void)env;extern char** environ;for(int i=0;environ[i];i++){printf("env[%d]=>%s\n",i,environ[i]);}return 0;
}//int main(int argc,char* argv[],char* env[]){
// (void)argv;
// (void)argc;
// (void)env;
// char* path=getenv("PATH");
// printf("PATH=%s\n",path);
// return 0;
//}//int main(int argc,char* argv[],char* env[]){
// (void)argv;
// (void)argc;
// for(int i=0;env[i];i++){
// printf("env[%d]=>%s\n",i,env[i]);
// }
// return 0;
//}//int main(int argc,char* argv[]){
// for(int i=0;i<argc;i++){
// printf("argv[%d]:%s\n",i,argv[i]);
// }
// return 0;
//}