UNIX再学习 -- 环境变量
生活随笔
收集整理的這篇文章主要介紹了
UNIX再学习 -- 环境变量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
之前講gcc編譯的時候,參看:C語言再學習 -- GCC編譯過程?提到過靜態庫和共享庫,那時只是簡單的講了下它們相關的編譯鏈接,接下來就該詳細介紹它們了。不過再講解之前還需了解一下編程相關的環境變量。
一、環境變量
參看:百度百科--環境變量 環境變量一般是指在操作系統中用來指定操作系統運行環境的一些參數,如:臨時文件夾位置和系統文件夾位置等。 環境變量時在操作系統中一個具有特定名字的對象,它包含了一個或者多個應用程序所將使用的信息。1、Windows下的環境變量
(1)環境變量配置
右擊我的電腦->屬性->高級系統設置->高級->環境變量->系統變量->選中Path?點擊編輯->在Path變量值的最后增加分號(;),再增加新的路徑。 注意:(千萬不要改動之前的變量值)->一路點擊確定即可(2)常見環境變量:(了解)
%ALLUSERSPROFILE% 局部 返回所有“用戶配置文件”的位置。%APPDATA% 局部 返回默認情況下應用程序存儲數據的位置。%CD% 局部 返回當前目錄字符串。%CMDCMDLINE% 局部 返回用來啟動當前的 Cmd.exe 的準確命令行。%CMDEXTVERSION% 系統 返回當前的“命令處理程序擴展”的版本號。%COMPUTERNAME% 系統 返回計算機的名稱。%COMSPEC% 系統 返回命令行解釋器可執行程序的準確路徑。%DATE% 系統 返回當前日期。使用與 date /t?命令相同的格式。由 Cmd.exe 生成。有關 date?命令的詳細信息,請參閱 Date。%ERRORLEVEL% 系統 返回使用過的命令的錯誤代碼。通常用非零值表示錯誤。%HOMEDRIVE% 系統 返回連接到用戶主目錄的本地工作站驅動器號。基于主目錄值的設置。用戶主目錄是在“本地用戶和組”中指定的。%HOMEPATH% 系統 返回用戶主目錄的完整路徑。基于主目錄值的設置。用戶主目錄是在“本地用戶和組”中指定的。%HOMESHARE% 系統 返回用戶的共享主目錄的網絡路徑。基于主目錄值的設置。用戶主目錄是在“本地用戶和組”中指定的。%LOGONSEVER% 局部 返回驗證當前登錄會話的域控制器的名稱。%NUMBER_OF_PROCESSORS% 系統 指定安裝在計算機上的處理器的數目。%OS% 系統 返回操作系統的名稱。Windows 2000 將操作系統顯示為 Windows_NT。%PATH% 系統 指定可執行文件的搜索路徑。%PATHEXT% 系統 返回操作系統認為可執行的文件擴展名的列表。%PROCESSOR_ARCHITECTURE% 系統 返回處理器的芯片體系結構。值: x86,IA64。%PROCESSOR_IDENTIFIER% 系統 返回處理器說明。%PROCESSOR_LEVEL% 系統 返回計算機上安裝的處理器的型號。%PROCESSOR_REVISION% 系統 返回處理器修訂號的系統變量。%PROMPT% 局部 返回當前解釋程序的命令提示符設置。由 Cmd.exe 生成。%RANDOM% 系統 返回 0 到 32767 之間的任意十進制數字。由 Cmd.exe 生成。%SYSTEMDRIVE% 系統 返回包含 Windows XP 根目錄(即系統根目錄)的驅動器。%SYSTEMROOT% 系統 返回 Windows XP 根目錄的位置。%TEMP% and %TMP% 系統和用戶 返回對當前登錄用戶可用的應用程序所使用的默認臨時目錄。有些應用程序需要 TEMP,而其它應用程序則需要 TMP。%TIME% 系統 返回當前時間。使用與 time /t 命令相同的格式。由 Cmd.exe 生成。有關 time?命令的詳細信息,請參閱 Time。%USERDOMAIN% 局部 返回包含用戶帳戶的域的名稱。%USERNAME% 局部 返回當前登錄的用戶的名稱。%UserProfile% 局部 返回當前用戶的配置文件的位置。%WINDIR% 系統 返回操作系統目錄的位置。2、Linux下的環境變量(重點)
參看:Linux環境變量 linux是一個多用戶的操作系統,每個用戶登錄系統之后,都會有一個專用的運行環境。通常每個用戶默認的環境都是相同的。這個默認的環境實際上就是一組環境變量的定義,用戶可以對自己的運行環境進行定制,其方法就是修改相應的系統環境變量。 在linux中,環境變量一般用大寫加下劃線命名(例如,PATH、ORACLE_HOME)。環境變量就相當于一個指針,當我們要查看指針所指向的值的時候需要解引用。同樣的,當我們想要查看環境變量里面的值的時候,需要在前面加 $ 引用。 linux的變量分為環境變量和本地變量: 環境變量:是一種全局變量,存在所有的shell中,在登錄的時候就有系統定義的環境變量了。linux的環境變量具有繼承性,即shell會繼承父shell的環境變量。 本地變量:當前shell中的變量,本地變量中包含環境變量。Linux的本地變量的非環境變量不具備繼承性。 在Linux下面的變量按照生存周期可分為兩類: 永久的:需要修改配置文件,變量永久生效。 臨時的:使用export命令聲明即可,變量在關閉shell時失效。修改和查看環境變量的指令
(1)echo:查看單個環境變量 例如,顯示環境變量HOME # echo $HOME /root(2)env:查看所有環境變量 例如,查看所有的環境變量,可以看一下都有哪些環境變量。# env LC_PAPER=en_US.UTF-8 LC_ADDRESS=en_US.UTF-8 SSH_AGENT_PID=1768 LC_MONETARY=en_US.UTF-8 GPG_AGENT_INFO=/tmp/keyring-rB9csr/gpg:0:1 TERM=xterm SHELL=/bin/bash XDG_SESSION_COOKIE=619793d1806621208703bfca00000005-1489544306.787815-2133755939 WINDOWID=31457285 LC_NUMERIC=en_US.UTF-8 GNOME_KEYRING_CONTROL=/tmp/keyring-rB9csr USER=root .....也可以和grep一起使用查看某一類的環境變量# env | grep SH SSH_AGENT_PID=1768 SHELL=/bin/bash SSH_AUTH_SOCK=/tmp/keyring-rB9csr/ssh SHLVL=1(3)set:查看本地定義的環境變量 root@ubuntu:~# set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=() BASH_SOURCE=() BASH_VERSINFO=([0]="4" [1]="2" [2]="24" [3]="1" [4]="release" [5]="i686-pc-linux-gnu") BASH_VERSION='4.2.24(1)-release' .....(4)export:設置一個新的環境變量 (臨時的,重啟后消失) 注意,一般環境變量都用大寫加下劃線來命名。 例如,新建環境變量HELLO # export HELLO="hello" # echo $HELLO hello(5)unset:清除環境變量 例如,清除環境變量HELLO,清除后再查看為空 # unset HELLO # echo $HELLO# (6)readonly:設置只讀環境變量 例如,將環境變量HELLO設為只讀,再修改或者清除該環境變量時會提示為只讀變量,不能再對它進行操作。但是因為它是一個臨時性的環境變量,所以用戶退出登錄以后就會自動失效。
# export HELLO="hello" # readonly HELLO="hello" # export HELLO="hello" world bash: HELLO: 只讀變量 # unset HELLO bash: unset: HELLO: 無法反設定: 只讀 variable
Linux系統常用的環境變量
(1)PATH:決定了shell將到哪些目錄中尋找命令或程序 # echo $PATH /usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/bin我們可以看到在當前目錄下,默認的PATH的值。它表示當我們在當前目錄下執行一條命令時命令的搜索路徑。每一個目錄都是以冒號隔開的。例如:export PATH=$PATH:/opt/arm-2009q1-203/bin: 當我們執行一個可執行的程序時,系統就會到這些目錄下面去找,在這些目錄下找到的話才執行,否則不執行。 (2)HOME:指定用戶的主目錄(即用戶登錄到Linux系統時的默認目錄) 環境變量是一個變量,會隨著用戶的不同,它的值也就不同。 普通用戶下的主目錄: # echo $HOME /home/admin root超級用戶下的主目錄:# echo $HOME /root(3)HISTSIZE:保存歷史命令記錄的條數 在linux中可以查找以前輸入的命令,HISTSIZE這個環境的值就表示最多保存的記錄的數目。 # echo $HISTSIZE 1000可以看到,上面顯示能夠保存1000條。 (4)LOGNAME:顯示當前用戶的登錄名 ? (同 指令logname) echo $LOGNAME root(5)HOSTNAME:顯示主機的名字 (同 指令hostname) echo $HOSTNAME ubuntu(6)SHELL:指當前用戶使用的shell類型 echo $SHELL /bin/bash (7)LANG/LANGUGE:語言相關的環境變量,多語言可以修改此環境變量 echo $LANG zh_CN.UTF-8 (8)MAIL:當前用戶的郵件存放的目錄 (無郵件) # echo $MAIL (9)PS1:命令基本提示符,對root是 #,對普通用戶是 $
# echo $PS1 \[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$ (10)PS2:附屬提示符,默認是 >
# echo $PS2 >
存放環境變量的文件
(1)/etc/profile (所有用戶) 這個文件是每個用戶登錄時都會運行的環境變量設置,當用戶第一次登陸時該文件被執行,并從/etc/profile.d目錄的配置文件中搜索shell的設置。這個文件的作用就是當用戶登錄的時候用于獲取系統的環境變量,只在登錄的時候獲取一次。 所以說,在/etc/profile文件中添加的變量,對所有用戶永久的生效。 之前用到過,參看:Hi3516A開發--安裝交叉編譯器 gedit /etc/profile 添加 export PATH="/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH" 執行 source /etc/profile 需要注意的是,修改完文件后想要馬上生效還要運行 source /etc/profile 不然只能在下次重進此用戶時生效。 再如: #gcc找到頭文件的路徑 $C_INCLUDE_PATH=/opt/example/include $export C_INCLUDE_PATH #g++找到頭文件的路徑 $CPLUS_INCLUDE_PATH=/opt/example/include $export CPLUS_INCLUDE_PATH #找到靜態庫的路徑 $LIBRARY_PATH=/opt/example/lib $export LIBRARY_PATH #找到動態鏈接庫的路徑 LD_LIBRARY_PATH=/opt/example/lib ? export LD_LIBRARY_PATH (2)~/.bash_profile (單個用戶) 每個用戶都可以使用該文件輸入自己專用的shell信息,當用戶登錄時,該文件僅僅執行一次。默認情況下,它設置一些環境變量,執行用戶的.bashrc文件。單個用戶對此文件的修改只會影響到它以后的每一次登錄。 也就是說,在用戶目錄下的.bash_profile文件中增加變量,僅對當前用戶永久生效,操作同 /etc/profile (3)/etc/bashrc (所有用戶)在執行完 /etc/profile 內容后,如果用戶運行 bash shell 的話,則就執行這個文件,當每次一個新的bash shell 被打開時,該文件被讀取。所以,如果每打開一個bash都執行某些操作,就可以在這個文件里面設置。(4)~/.bashrc ?(單個用戶) 該文件只包含專用于你的bash信息,當你登錄時以及每次打開新的shell時,該文件就會自動被讀取。 操作參看:DM368開發攻略——開發環境搭建 gedit .bashrc 添加 export PATH=$PATH:/opt/arm-2009q1-203/bin: 執行 source .bashrc (5)~/.bash_logout 每次在退出shell的時候會執行該文件,它提供了定制用戶環境的功能,比如刪除賬號內的臨時文件等命令就可以放在bash_logout 文件內,如果這個文件不存在的話則就執行其他的命令。3、編程相關的環境變量
(1)CPATH/C_INCLUDE_PATH? C頭文件的附加搜索路徑,相當于gcc的 -I 選項 (2)CPLUS_INCLUDE_PATH C++頭文件的附加搜索路徑 (3)LIBRARY_PATH 鏈接時查找靜態庫和共享庫的路徑,相當于 -I 選項 (4)LD_LIBRARY_PATH 運行時查找共享庫的路徑參看:LIBRARY_PATH和LD_LIBRARY_PATH的區別 關于Linux gcc中的 LIBRARY_PATH 和 LD_LIBRARY_PATH 參數說明
下面摘取了兩篇較權威的說明資料:
1、 GNU 上關于LIBRARY_PATH的說明:
LIBRARY_PATH The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH. When configured as a native compiler, GCC tries the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX. Linking using GCC also uses these directories when searching for ordinary libraries for the -l option (but directories specified with -L come first). 2、 man7 上關于LD_LIBRARY_PATH的說明: LD_LIBRARY_PATH A colon-separated list of directories in which to search for ELF libraries at execution-time. Similar to the PATH environment variable. Ignored in set-user-ID and set-group-ID programs.后面發現 StackOverflow 上關于 LIBRARY_PATH 和 LD_LIBRARY_PATH 的解釋更直白: LIBRARY_PATH is used by gcc before compilation to search for directories containing libraries that need to be linked to your program.LD_LIBRARY_PATH is used by your program to search for directories containing the libraries after it has been successfully compiled and linked.EDIT: As pointed below, your libraries can be static or shared. If it is static then the code is copied over into your program and you don't need to search for the library after your program is compiled and linked. If your library is shared then it needs to be dynamically linked to your program and that's when LD_LIBRARY_PATH comes into play.
Linux gcc編譯鏈接時的共享庫搜索路徑
GCC編譯、鏈接生成可執行文件時,共享庫的搜索路徑順序如下(注意不會遞歸性地在其子目錄下搜索):
1、gcc編譯、鏈接命令中的-L選項;
2、gcc的環境變量的LIBRARY_PATH(多個路徑用冒號分割);
3、gcc默認共享庫目錄:/lib:/usr/lib:usr/lib64:/usr/local/lib。
執行二進制文件時的共享庫搜索路徑
鏈接生成二進制可執行文件后,在運行程序加載共享庫文件時,搜索的路徑順序如下:
1、編譯目標代碼時指定的共享庫搜索路徑:用選項 -Wl,rpath 和 include 指定的共享庫的搜索路徑,比如 gcc -Wl,-rpath,include -L. -ldltest hello.c,在執行文件時會搜索路徑 `./include`;
2、環境變量LD_LIBRARY_PATH(多個路徑用冒號分割);
3、在 /etc/ld.so.conf.d/ 目錄下的配置文件指定的共享庫絕對路徑(通過ldconfig生效,一般是非root用戶時使用);
4、gcc默認共享庫目錄:/lib:/usr/lib:usr/lib64:/usr/local/lib等。
其中,Linux GCC默認的共享庫搜索路徑可以通過 ld --verbose 命令查看: SEARCH_DIR("/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib"); 總結下來就是,共享庫編譯的時候與靜態庫一樣依賴 LIBRARAY_PATH,運行的旪候依賴 LD_LIBRARY_PATH 。 這也就是我們為什么講了這么長時間的環境變量。
4、環境列表
環境列表就是指環境變量的集合,而每個進程都擁有一張獨立的環境列表,來保存和當前進程相關的環境變量信息。環境列表,采用字符指針數組來存儲所有的環境變量。 例如: PATH ? ? ? ? ? ? ? ? ? ? ? ? 0X01 ?//運行程序所有路徑 CPATH ? ? ? ? ? ?0X02 ?//C語言路徑 LIBRARY_PATH ? ?0X03 ?//靜態庫 LD_LIBRARY_PATH ? 0X04 ?//共享庫 char* arr[5] = {0x01, 0x02, 0x03, 0x04}; 環境列表采用字符指針數組來存儲所有的環境變量,使用全局變量char** environ來記錄環境表的首地址,使用NULL?來代表環境表的結束。所以訪問環境表則需要借助environ變量。 //示例一 #include <stdio.h>int main(void) {//聲明全局變量extern char** environ;//給環境表首地址指定替身char** p = environ;while(*p != NULL){printf("%s\n",*p);//指向下一個p++;}return 0; }功能等同指令env,可自行嘗試//示例二 #include <stdio.h> #include <string.h>int main(void) {//聲明全局變量extern char** environ;//給環境表首地址指定替身char** p = environ;//練習:查找名字為SHELL的環境變量,獲取SHELL的值存到buf的字符數組中,然后進行打印char buf[20] = {0};p = environ;while(*p != NULL){//比較前6個字符是否相等if(!strncmp(*p,"SHELL=",6)){//跳過環境變量名=strcpy(buf,*p+6);break;}//比較下一個p++;}printf("SHELL=%s\n",buf);return 0; } 輸出結果: SHELL=/bin/bash功能等同指令echo $SHELL,可自行嘗試
5、環境變量函數
(1)getenv函數#include <stdlib.h>
char *getenv (const char *name);
函數功能:
表示根據參數指定的環境變量名去環境表進行查找 返回該環境變量所對應的環境值,查找失敗則返回NULL.
#include <stdio.h> #include <stdlib.h>int main (void) {char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);return 0; } 輸出結果: SHELL = /bin/bash使用echo指令 # echo $SHELL /bin/bash(2)setenv函數
#include <stdlib.h>
int setenv (const char *name, const char *value, int overwrite);
第一個參數:環境變量名
第二個參數:環境變量值
第三個參數:是否修改
函數功能: 改變或增加環境變量,如果參數指定的環境變量不存在則增加。如果存在并且 overwrite 是非0,則修改環境名變量值,否則環境變量不變
成功返回 0,失敗返回 -1 #include <stdio.h> #include <stdlib.h>int main (void) {char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);setenv ("SHELL", "ABC", 1);printf ("修改后的SHELL = %s\n", getenv ("SHELL"));return 0; } 輸出結果: SHELL = /bin/bash 修改后的SHELL = ABC(3)putenv函數
#include <stdlib.h>
int putenv (char *string);
函數功能:
表示按照參數的內容增加/修改環境變量,其中string的格式為:name=value,如果不存在則添加,存在則刪除
成功返回0,失敗返回-1#include <stdio.h> #include <stdlib.h>int main (void) {char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);int res = putenv ("SHELL=abc");if (res)perror("putenv"),exit(-1);printf ("修改后的SHELL = %s\n", getenv ("SHELL"));putenv("CSDN=666");printf("增加的環境值是:%s\n",getenv("CSDN"));//123return 0; } 輸出結果: SHELL = /bin/bash 修改后的SHELL = abc 增加的環境值是:666(4)unsetenv函數
#include <stdlib.h>
int unsetenv (const char *name);
函數功能:
表示根據參數指定的環境變量去環境表中進行刪除
成功返回0,失敗返回-1#include <stdio.h> #include <stdlib.h>int main (void) {putenv("CSDN=666");printf("增加的環境值是:%s\n",getenv("CSDN"));//123unsetenv("CSDN");printf("刪除的結果是:%s\n",getenv("CSDN"));return 0; } 輸出結果: 增加的環境值是:666 刪除的結果是:(null)(5)clearenv函數
#include <stdlib.h>
int clearenv (void);
函數功能:
表示清空整個環境表
成功返回0,失敗返回-1
#include <stdio.h> #include <stdlib.h>int main (void) {int res;putenv("CSDN=666");printf("增加的環境值是:%s\n",getenv("CSDN"));//123res = clearenv ();if(res)perror("clearenv"), exit(-1);printf("清空整個環境表結束\n");printf("CSDN = %s\n",getenv("CSDN"));return 0; } 輸出結果: 增加的環境值是:666 清空整個環境表結束 CSDN = (null)
6、主函數的原型
我們之前將函數的時候提到過,參看:C語言再學習 -- 函數main函數原型:
int main (int argc, char * argv[], char * envp[]) {....}
第一個參數:命令行參數的個數
第二個參數:命令行參數的地址信息
第三個參數:環境表的首地址
參數argc表示輸入參數的個數(含命令名),如果有命令行參數,argc應不小于1;argv表示傳入的參數的字符串,是一個字符串數組,argv[0]表示命令名,argv[1]指向第一個命令行參數;至于第三個參數env,它與全局變量environ相比也沒有帶來更多益處,所以POSIX.1也規定應使用environ而不使用第三個參數。通常用getenv和putenv函數來存取特定的環境變量,而不是直接使用environ變量。例如:
//main函數原型的使用 #include <stdio.h> int main(int argc,char* argv[],char* envp[]) { printf("argc=%d\n",argc); int i=0; for(i=0;i<argc;i++) { printf("感謝%s\n",argv[i]); } //聲明全局變量 extern char** environ; printf("environ=%p,envp=%p\n",environ,envp);//直接訪問環境表 return 0; } 輸出結果為: argc=1 感謝./a.out environ=0xbfab74cc,envp=0xbfab74cc
總結
以上是生活随笔為你收集整理的UNIX再学习 -- 环境变量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 产品人如何在小企业中夹缝生存?
- 下一篇: UNIX再学习 -- 静态库与共享库