文章目录
PATH环境变量
系统的ls和我们写的mytest都是可执行程序,所以mytest也可看作是一条指令。
但是当我们执行系统的指令比如ls,pwd等等的时候是不需要带指令的路径的,而我们执行自己编写出来的可执行程序的时候就需要带上路径比如:./mytest。这是为什么呢?
要执行一个指令(程序)首先就是要找到这个程序,我们执行./mytest其中./就是mytest的相对路径,有了路径才能找到这个程序。
通过指令which可以查看系统指令的所在路径。
可以看到这些指令都是/usr/bin目录下的,这个/usr/bin目录实际就是系统安装指令的路径。
那么我们将自己的可执行程序拷贝进这个目录呢?
拷贝要使用sudo提权,因为/usr/bin是系统路径。
拷贝过去之后我们发现,mytest可以直接像系统指令这样执行了。
这种拷贝行为实际就是将mytest这个程序安装到了系统的指令库,拷贝就是相当于安装。
注意:记得将mytest从/usr/bin目录下删除,因为我们自己的程序是没有进经过测试的,会污染系统的命令池。
由此我们可以知道在/usr/bin目录下的文件可以直接执行,下面我们来看一下环境变量PATH。
echo $PATH(环境变量名)
这条指令的作用就是查看环境变量。
通过echo查看到了系统的PATH环境变量,里面是一串路径,不同路径之间用冒号分隔。/usr/bin显然也在其中。
这些路径的意义就是当我们执行指令的时候系统会在这些路径下面查找如果找不到,那么就会报错。当我们使用which查找指令的时候也是在这些路径下查找的。
想要不带路径执行mytest还有一种方法就是将mytest所在的路径添加到环境变量PATH中,这样就将mytest的路径添加到了系统的默认搜索路径中,系统进行查找的时候就能找到mytest了。
export 指令
export指令的作用是导入修改环境变量。
如果用这种方式修改环境变量PATH我们发现修改完之后PATH中就只剩下mytest的路径了,此时我们的ls,clear等等指令路径都不在PATH中,也就找不到了。
正确的导入指令应如下:
$PATH:就是先将以前的输入进去,用冒号分隔再加上新的路径地址。
export第二个作用就是将本地变量导成环境变量。
export第三个作用就是直接添加环境变量。
重置PATH环境变量
想要恢复初始的PATH只需重新登录一次就可以了。
重新登录后PATH就恢复了。
为什么重新登录后PATH会变成上面的内容呢?
在我们当前用户的家目录下有两个文件:.bash_profile和.bashrc
使用vim查看.bash_profile
这是一段shell脚本,if这里的意思是判断家目录下.bashrc文件是否存在,存在就执行.bashrc文件。
下面就是给PATH导入新的路径。
我们用vim查看一下.bashrc文件
这里的if意思是判断/etc/bashrc文件是否存在,如果系统目录下bashrc文件存在就执行这个bashrc文件。
下面我们再来看一下/etc/bashrc这个文件。
这个文件很长,有100行,这个文件的内容呢就是给PATH导入那些我们刚刚看到的指令路径。
所以为什么重新登录的时候PATH会恢复到默认的路径内容呢?因为每次我们启动bash(shell外壳程序)命令行解释器,bash都会先执行.bash_profile文件完成环境变量的设置。
其他环境变量
除了PATH外,Linux系统下还有很多环境变量。
通过echo可以查看具体的环境变量的内容
HOME是当前用户的工作目录
HOSTNAME是主机名
LOGNAME是当前登录用户名
HISTSIZE是bash记录历史指令的最大条数
我们可以通过方向键盘的上下间查找以前输入过的历史指令,HISTSIZE就是bash所能保存的最多的历史指令的条数。
history指令可以将所有的历史指令打印出来
使用wc对history总共有多少条指令进行计数
history | wc -l
环境变量的概念
环境变量就是操作系统给我们提供的一些全局性的,且具有特殊作用的内存级变量。
全局性就是指环境变量不仅能在当前进程中使用,在子进程中同样可以使用。bash执行指令的方式就是通过派生子进程的方式,比如执行hostname指令的时候,为什么hostname指令能获取到当前的主机名?因为hostname这个进程能访问到环境变量HOSTNAME。
内存级变量,可用来存储数据,定义内存变量时需为它取名并赋初值,内存变量建立后存储于内存中。
环境变量有很多种,是操作系统为了满足不同的应用场景,在操作系统启动bash做命令行解释的时候,预先设置好的一批未来可能会用到的变量。
环境变量的意义
环境变量虽然有很多,但是每个环境变量都是具有自己的作用的。
比如:USER
USRE环境变量的最大意义就是可以标识当前登录Linux的用户。
USER就可以用做身份验证,比如当我们访问别人的文件的时候,ls或者cd命令就会通过USER环境变量知道当前登录的用户是谁,是不是该文件的拥有者,所属组。
而sudo指令提权的本质就是将环境变量USER从普通用户改成root。
而ls这些指令进行身份验证的时候能访问到USER环境变量也说明了环境变量的全局性,因为ls是bash的子进程,环境变量能被子进程所继承。
USER环境变量如果使用su直接切换成root用户,当前所处的路径是不会改变的,并且USER此时还是普通用户。只有使用su -重新登录后USER才会变成root
PWD,这个环境变量记录着我们当前所处的路径,每次cd更改路径后,都会将PWD也一起更改。
例如,我们每次使用ls显示当前所处路径下的文件的时候,系统是怎么知道我当前在那个路径下?
就是通过PWD环境变量,PWD里记录的是我当前所处的路径,并且会随着路径切换而更新。
HOME
HOME环境变量保存的是当前用户的家目录。
当我们切换成root用户,家目录也会跟着改变。
HOME环境变量的作用就是当我们登录到shell后,导入环境变量完成,此时bash会执行一条指令,cd ~也可以写成cd $HOME,因此我们每次登录上去才会处于用户的家目录。
每个环境变量都是具有自己的特殊的作用的。
所以再次解释了环境变量就是操作系统为了满足不同的应用场景而预先设置好的一批未来可能用到的全局变量。
本地变量
本地变量就是在命令行上直接定义的变量。
变量myval就是本地变量,本地变量只在当前进程(bash)内有效,无法被继承到子进程。
而环境变量能被子进程继承,从bash往后的所有变量都可以访问到环境变量。
本地变量不是环境变量,所以使用env是查看不到的。
环境变量的指令操作
echo指令
echo $PATH(环境变量名)
作用是显示某个环境变量的值,也可以用来显示本地变量。
export指令
作用设置新的环境变量,或者修改环境变量
- 修改环境变量用PATH举例
- 将本地变量设置成环境变量。
转换后就能在环境变量中查看到myenv了。
- 添加新的环境变量。
通过export直接添加环境变量,让环境变量直接等于,后面的33333其实是被看作是字符串的,所以我们不用写双引号也是可以的,但是如果我们的环境变量里面有空格,此时就需要用双引号括起来标识一个整体了。
env指令
通过env指令我们可以查看到所有的环境变量
set指令
set可以显示本地定义的shell变量和环境变量。
因为set里面的内容太多了,所以我们先定义几个本地变量然后查看其是否在set中。
可以看到在set中既可以查看到本地变量也可以查看到环境变量。
unset指令
清楚环境变量或者本地变量。
我们直接定义了一个环境变量然后清除掉,之后就在env中查找不到这个环境变量了, 如果清楚后发现还是能在env中显示出环境变量或者是显示一半的环境变量,那么等一会再查也就没了,因为环境变量的清除需要一定的时间。
使用unset指令也是可以清除本地变量的。
命令行参数
命令行参数是什么
在C语言的某些书中会写,main函数其实也是有参数的。
int main(int argc ,char* argv[] ,char* env[])
{}
main函数的三个形参就叫做命令行参数。
命令行参数有什么用
想要知道命令行参数有什么作用我们可以将参数的内容都打印出来。
首先argc是标识着argv这个指针数组里面的有效元素的个数。
这是测试argv内容的代码。
我们调用mytest的时候输入的内容是一个长字符串
"./mytest -a -b -c"这个长字符串被按空格分割。
“./mytest” “-a” “-b” "-c"分割成了这四部分小字符串
这个表格就是argv,前四个指针分别指向分割后的字符串,结束位置以NULL填充。
将长字符串分割并填入argv表中的工作是shell和操作系统一起做的。
argc和argv的作用就是将运行程序时候的选项剥离出来,以便程序内部对不同的选项执行不同的功能
这个代码,当我们输入一个选项的时候,选项不同就会执行不同的功能
所以命令行参数的作用就是,通过命令行选项控制同一个程序执行不同的功能。
Windows也有命令行参数,就是win + r调出cmd
这些都是shutdown的指令,我们可以使用shutdown -s -t 60 ,设定计算机在60s后关机,同时也可以通过shutdown -a取消关机。
环境变量表
首先说一下在代码中获取环境变量的第一种方法。
getenv()函数调用
getenv的参数就是一个字符串,这个字符串是环境变量名,返回值是一个字符串,如果name环境变量存在,返回值就是环境变量的内容,如果name环境变量不存在返回的就是NULL。
使用xzj用户调用该程序的时候输出的是xzj
重新登录root后调用mytest输出的是root,环境变量USER是跟随用户的改变而改变的。
main函数有三个参数,第一个是命令行参数表的内容个数,第二个就是命令行参数表,这第三个char* env[ ]就是环境变量表。
使用这个代码可以输出env数组的所有内容,并且通过是否越界来判断env数组的结尾是不是NULL。
所以env环境变量表的结构也是以NULL结尾的。
第三种获取环境变量的方式,char** environ。
environ是一个系统在创建好环境变量表之后定义的一个二级指针,environ指针指向的就是env数组的第一个元素。在写main函数的时候就算我们参数不写env数组,这个数组也是会被创建出来的。
在使用environ的时候要提前声明
如果不在使用environ前声明,编译器就不认识这个二级指针变量。
编译运行上述代码:
其实main函数的char* env[ ]数组就是将environ作为形参传过去,一个字符指针数组传参的时候会发生降维,实际传递的类型是数组元素的地址,字符指针的地址就是一个二级指针。
所以上述就提供了我们在代码中获取环境变量的三种方法。
- char* getenv(const char* name)
- char* env[ ]
- char** environ
这三种方式里更推荐使用getenv,因为getenv可以准确的获取到某个环境变量的内容,23方法还需要对字符串进行解析才能拿到想要的环境变量。