一.環(huán)境變量
1.什么是環(huán)境變量?
環(huán)境變量是有特殊用途的系統(tǒng)變量。
如:我們?cè)诰帉?xiě)C/C++代碼的時(shí)候,在鏈接的時(shí)候,從來(lái)不知道我們的所鏈接的動(dòng)態(tài)靜態(tài)庫(kù)在哪里,但是照樣可以鏈接成功,生成可執(zhí)行程序,原因就是有相關(guān)環(huán)境變量幫助編譯器進(jìn)行查找。
2.windows下配置PATH環(huán)境變量的原理
這里推薦一個(gè)B站迷糊老師的一個(gè)視頻哦:迷糊老師:windows環(huán)境變量
學(xué)習(xí)Java的朋友都經(jīng)歷過(guò)配置環(huán)境變量:
大家在安裝JDK的時(shí)候,驗(yàn)證是否安裝成功,都會(huì)在命令行里輸入java和javac命令來(lái)驗(yàn)證,那你明白這背后的原理嗎?
我們知道java和javac其實(shí)都是可執(zhí)行程序.exe:
javac.exe作用: 編譯代碼
java.exe作用:執(zhí)行代碼
它們?cè)谟脖P(pán)上都有自己的路徑,如下圖:
配置PATH環(huán)境變量的原理
那么如果我們?cè)诰帉?xiě)好Hello.java代碼文件,準(zhǔn)備使用javac.exe去編譯代碼的時(shí)候,去使用javac.exe的前提是找到j(luò)avac.exe,但是如果沒(méi)有把javac.exe的路徑添加到PATH環(huán)境變量,也就是沒(méi)有配置好環(huán)境變量的話,系統(tǒng)就找不到j(luò)avac.exe在哪里,自然也就無(wú)法編譯Hello.java代碼文件。
相反的,如果我配置好了環(huán)境變量,你想編譯代碼的時(shí)候,系統(tǒng)就能按照PATH環(huán)境變量所提供的路徑去找Javac.exe工具,找到后就可以使用起來(lái),編譯我們寫(xiě)好的代碼!
windows下環(huán)境變量和我們今天講的Linux下環(huán)境變量的原理和作用都是類似的,只不過(guò)是使用和細(xì)節(jié)上有差異!
例如:一個(gè)環(huán)境變量存儲(chǔ)的字符串可能由多條路徑組成,在windows下和Linux下它們的路徑分隔符就有所差異
windows下:
Linux:
3.一覽常見(jiàn)的環(huán)境變量
當(dāng)前登入用戶:
USER=li
當(dāng)前登入用戶的家目錄:
HOME=/home/li
當(dāng)前工作目錄:
PWD=/home/li
系統(tǒng)默認(rèn)搜索路徑:
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/li/.local/bin:/home/li/bin
4.指令方式如何查看環(huán)境變量
方法一:顯示某一特定環(huán)境變量
echo $環(huán)境變量名
例如echo $PATH
方式二: **env **
顯示所有的環(huán)境變量
5.PATH-存放系統(tǒng)默認(rèn)搜索路徑的環(huán)境變量
,指令也是程序,那為什么我們執(zhí)行我們自己寫(xiě)的可執(zhí)行程序要帶./filename路徑,而執(zhí)行系統(tǒng)安裝的可執(zhí)行程序卻不要帶上任何路徑!
其實(shí)要執(zhí)行指令,前提都是要找到該指令的路徑,只不過(guò)系統(tǒng)安裝的可執(zhí)行程序所在的位置已經(jīng)被添加到了PATH的環(huán)境變量中,而PATH環(huán)境變量存放了系統(tǒng)的搜索路徑,簡(jiǎn)而言之就是系統(tǒng)的可執(zhí)行程序系統(tǒng)能自動(dòng)搜索到,所以執(zhí)行時(shí)可以不帶路徑;
但是我們自己寫(xiě)的可執(zhí)行程序不在系統(tǒng)的搜索路徑下,也就是系統(tǒng)自動(dòng)查找你的可執(zhí)行程序查找不到,所以你在執(zhí)行代碼的時(shí)候得自己帶上./相對(duì)路徑,這用絕對(duì)路徑來(lái)執(zhí)行也是可以的!
6.兩種方法使運(yùn)行我們寫(xiě)的可執(zhí)行程序不帶路徑
要想使得我們
方法一:間接法—我叫別人騎車帶我過(guò)去
前面我們說(shuō)到,系統(tǒng)指令所在的目錄被添加到了PATH環(huán)境變量中, 在執(zhí)行可執(zhí)行程序的時(shí)候,系統(tǒng)就能通過(guò)依次查找PATH中的記錄路徑來(lái)查找到系統(tǒng)指令,所以我只要把我寫(xiě)的可執(zhí)行程序加入到系統(tǒng)安裝的系統(tǒng)指令的目錄,這樣系統(tǒng)默認(rèn)的搜索路徑中就可找到我寫(xiě)的可執(zhí)行程序了!
ps:
- 系統(tǒng)安裝的系統(tǒng)指令目錄是:/usr/bin/
- 提權(quán)su- 切換到root或者sudo 提權(quán)執(zhí)行,拷貝(安裝)操作
[li@VM-8-5-centos test]$ ./hello
hello world
[li@VM-8-5-centos test]$ hello
-bash: hello: command not found
[li@VM-8-5-centos test]$ sudo cp hello /usr/bin
[li@VM-8-5-centos test]$ hello
hello world
但是這種方法我們極不推薦,因?yàn)槲覀儗?xiě)的可執(zhí)行程序沒(méi)有經(jīng)過(guò)測(cè)試,就放到系統(tǒng)安裝指令的路徑,可能會(huì)造成指令的污染!
方法二:直接法–我自己騎車過(guò)去
話接上文,我們還可以直接把我們自己寫(xiě)的可執(zhí)行程序所在路徑添加到系統(tǒng)默認(rèn)搜索路徑PATH中.
//刪除文件用rm -rf,刪除一個(gè)環(huán)境變量/本地變量用unset
[li@VM-8-5-centos test]$ sudo rm -rf /usr/bin/hello
[li@VM-8-5-centos test]$ ./hello
hello world
[li@VM-8-5-centos test]$ hello
-bash: /usr/bin/hello: No such file or directory
[li@VM-8-5-centos test]$ pwd
/home/li/1-16/test
//export導(dǎo)入環(huán)境變量
//PATH環(huán)境變量名,$PATH環(huán)境變量的內(nèi)容
//export PATH=/home/li/1-16/test會(huì)覆蓋掉原來(lái)的$PATH,所以用冒號(hào)分隔不同路徑,意為相加
[li@VM-8-5-centos test]$ export PATH=$PATH:/home/li/1-16/test
[li@VM-8-5-centos test]$ hello
hello world
[li@VM-8-5-centos test]$
二.環(huán)境變量和本地變量
env命令只能夠顯示所有的環(huán)境變量,但是set命令能顯示所有的環(huán)境變量+所有的本地變量
[li@VM-8-5-centos ~]$ myval=100
[li@VM-8-5-centos ~]$ env | grep myval
[li@VM-8-5-centos ~]$ set | grep myval
myval=100
[li@VM-8-5-centos ~]$ export youval=200
[li@VM-8-5-centos ~]$ env | grep youval
youval=200
[li@VM-8-5-centos ~]$ set | grep youval
youval=200
環(huán)境變量類似全局變量,具有全局屬性,本地變量類似局部變量,類似局部變量.
全局還是局部屬性體現(xiàn)在當(dāng)創(chuàng)建子進(jìn)程的時(shí)候是否繼承父進(jìn)程能夠被繼承!
但是注意:環(huán)境變量具有全局屬性也只是針對(duì)本次登入,要永久有效需要修改.bashrc文件!(這涉及到剛登入bash的時(shí)候?yàn)槭裁淳陀协h(huán)境變量的原因,只需了解,不用深究)
ps:
- .bashrc在每一個(gè)用戶的家目錄中都能通過(guò)ls -al找到
[li@VM-8-5-centos ~]$ cd ~
[li@VM-8-5-centos ~]$ pwd
/home/li
[li@VM-8-5-centos ~]$ ls -al | grep .bashrc
-rw-r--r-- 1 li li 350 Dec 28 20:51 .bashrc
- .bashrc文件內(nèi)容是腳本語(yǔ)言編寫(xiě),如果/etc/bashrc存在,就導(dǎo)入/etc/bashrc的內(nèi)容,每一次登入bash,因?yàn)?font color="green">每一個(gè)用戶的家目錄都有這么一個(gè).bashrc文件,所以對(duì)應(yīng)用戶的家目錄中的.bashrc文件的內(nèi)容就會(huì)被導(dǎo)入到env環(huán)境變量中(此條均為自己猜測(cè),個(gè)人理解)。
- 環(huán)境變量是既然是內(nèi)存級(jí)別的東西,那么下次登入就類似內(nèi)存掉電失去,需要修改,bashrc相關(guān)文件才能永久性更改環(huán)境變量。
殘留問(wèn)題:我們知道echo是bash的子進(jìn)程,本地變量不會(huì)被父進(jìn)程在創(chuàng)建子進(jìn)程的時(shí)候被繼承,那為什么可以通過(guò)echo $本地變量名
的方式打印到命令行終端?-----內(nèi)建命令!
解答:
Linux下大部分命令都是通過(guò)子進(jìn)程的方式執(zhí)行的!
但是,還有一部分命令,不通過(guò)子進(jìn)程的方式執(zhí)行,而是由bash自己執(zhí)行,這種命令叫做內(nèi)建命令!
三.和環(huán)境變量相關(guān)的命令
- echo: 顯示某個(gè)環(huán)境變量值
- export: 設(shè)置一個(gè)新的環(huán)境變量
- env: 顯示所有環(huán)境變量
- set: 顯示本地定義的shell變量(本地變量)和環(huán)境變量
- unset: 清除環(huán)境a變量
1.echo:顯示某一特定環(huán)境變量
[li@VM-8-5-centos ~]$ echo $PWD
/home/li
2.export: 設(shè)置新的環(huán)境變量
[li@VM-8-5-centos ~]$ export youval=200
3.env: 顯示所有環(huán)境變量
4.set:查看本地定義的本地變量
5.unset:清除環(huán)境變量
</刪除文件用rm -rf, 刪除一個(gè)環(huán)境變量/本地變量用unset
unset 環(huán)境變量名
驗(yàn)證unset刪除一個(gè)本地變量
[li@VM-8-5-centos test]$ myval=400
[li@VM-8-5-centos test]$ echo $myval
400
[li@VM-8-5-centos test]$ unset myval
[li@VM-8-5-centos test]$ set | grep myval
驗(yàn)證unset刪除一個(gè)本地變量
[li@VM-8-5-centos test]$ export youval=800
[li@VM-8-5-centos test]$ echo $youval
800
[li@VM-8-5-centos test]$ unset youval
[li@VM-8-5-centos test]$ echo $youval
[li@VM-8-5-centos test]$ env | grep youval
[li@VM-8-5-centos test]$ set | grep youval
四.命令行參數(shù)
1.cmd下的命令行參數(shù)
在windows下相信你肯定寫(xiě)過(guò)所謂的關(guān)機(jī)小程序,那你肯定用到過(guò)這個(gè):
或許你會(huì)說(shuō)這不就是一個(gè)選項(xiàng)嘛,啊,他確實(shí)是選項(xiàng),可是這選項(xiàng)的背后原理依賴的就是命令行參數(shù)!
2.main函數(shù)的三個(gè)參數(shù)
熟悉C語(yǔ)言的童鞋們都知道m(xù)ain函數(shù)也是有三個(gè)參數(shù),函數(shù)main()可以有或沒(méi)有參數(shù)列表,通常最多支持3個(gè)參數(shù):
- int main()
- int main(int argc, char *argv[])
- int main( int
argc
, char *argv
[] , char *env
[])
main()函數(shù)一般用int或者void形的。用int型定義main更好些,因?yàn)樵诮Y(jié)束的時(shí)候可以返回給操作系統(tǒng)一個(gè)值以表示執(zhí)行情況。
這里先講一講前兩個(gè)參數(shù)的情況:
- argc全稱:Argument count 參數(shù)個(gè)數(shù)
- argv全稱:Argument vector 參數(shù)向量
1 #include<stdio.h>
2 int main(int argc,char* argv[])
3 {
4 for(int i=0;i<argc;i++)
5 {
6 printf("argv[%d]->%s\n",i,argv[i]);
7 }
8 return 0;
9 }
當(dāng)我們?cè)赽ash輸入命令的時(shí)候,輸入的命令就以空格為間隔,把命令劃分為一個(gè)個(gè)小的子字符串,然后他們的首字符的地址被存入到argv中,argv是一個(gè)指針數(shù)組,數(shù)組里面存放著argc個(gè)元素,每一個(gè)元素的類型是char*類型.
3.指令的選項(xiàng)制作原理
#include<stdio.h>
#include<string.h>
int main(int argc,char* argv[])
{
for(int i=0;i<argc;i++)
{
if(argc!=2)
{
printf("Usage:\n\t%s [-a/-b/-c/-ab/-ac/-bc/-abc]\n",argv[0]);
return 1;
}
if(strcmp("-a",argv[1])==0)
{
printf("功能a\n");
return 1;
}
if(strcmp("-b",argv[1])==0)
{
printf("功能b\n");
return 1;
}
if(strcmp("-c",argv[1])==0)
{
printf("功能c\n");
return 1;
}
if(strcmp("-ab",argv[1])==0)
{
printf("功能ab\n");
return 1;
}
if(strcmp("-ac",argv[1])==0)
{
printf("功能ac\n");
return 1;
}
if(strcmp("-bc",argv[1])==0)
{
printf("功能bc\n");
return 1;
}
if(strcmp("-abc",argv[1])==0)
{
printf("功能abc\n");
return 1;
}
}
return 0;
}
選項(xiàng)的原理我想通過(guò) 看懂上面這段代碼你就能夠明白了!
五.代碼獲取環(huán)境變量的三種方式
1.char* getenv(const char* str)
a.getenv參數(shù)的介紹:
/return搜索返回值
b.getenv獲取指定環(huán)境變量
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
printf("USER:%s\n",getenv("USER"));
return 0;
}
2.char * env[]
#include<stdio.h>
#include<string.h>
int main(int argc,char* argv[],char* env[])
{
//env沒(méi)有個(gè)數(shù)的限制NULL->0
for(int i=0;env[i];i++)
{
printf("env[%d]->%s\n",i,env[i]);
}
return 0;
}
3.extern char** environ
- #include <unistd.h>
- extern char **environ;
#include<stdio.h>
#include<string.h>
#include<unistd.h>
int main()
{
//使用第三方變量envieron
//extern告訴編譯器,我要用庫(kù)里的environ這個(gè)變量了,鏈接的時(shí)候你給我鏈接進(jìn)來(lái)
extern char** environ;
for(int i=0;environ[i];i++)
{
printf("environ[%d]->%s\n",i,environ[i]);
}
return 0;
}
其實(shí)方法2的char * env[] 和方法3中的char** environ本質(zhì)上是一樣的:
char* env[]作為形參,其實(shí)是降維成一個(gè)二級(jí)指針的,可寫(xiě)作char** env,另外參數(shù)名也是自定義的,本質(zhì)是char env 和char* environ就是一個(gè)形參一個(gè)實(shí)參的關(guān)系
六.環(huán)境變量具體應(yīng)用
1.身份驗(yàn)證
我們?cè)趺从铆h(huán)境變量來(lái)實(shí)現(xiàn)某個(gè)用戶是否有某個(gè)文件的各種權(quán)限吶?除了我們之前講的文件權(quán)限的內(nèi)容之外,我們還有一個(gè)前提就是系統(tǒng)怎么知道當(dāng)前登入用戶是誰(shuí)?
其實(shí)這環(huán)境變量信息在我們登入shell的時(shí)候就被導(dǎo)入進(jìn)來(lái)了,只是一個(gè)strcmp的過(guò)程!簡(jiǎn)單,安排!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
char* who=getenv("USER");
//strcmp
if(strcmp(who,"root")==0)
{
printf("USER:root\n");
printf("USER:root\n");
printf("USER:root\n");
printf("USER:root\n");
printf("USER:root\n");
}
else
{
printf("權(quán)限不足\n");
}
return 0;
}
2.su 和su -的區(qū)別
su和su -都可以從普通用戶切換到root,區(qū)別在于su切換的前后環(huán)境變量的USER都是普通用戶
而su -切換的前后環(huán)境變量的USER發(fā)生從普通用戶到root的改變.
su展示:
su -展示:
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-790865.html
從兩張圖我們可以看出,su-是重登了用戶,完全改變了身份,可能和.bashrc的重新加載有關(guān),所以路徑也在su-的時(shí)候發(fā)生改變.文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-790865.html
到了這里,關(guān)于【Linux操作系統(tǒng)】環(huán)境變量和命令行參數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!