< Linux >:环境变量

2023-11-03

目录

问题:

注意:可执行程序 等价于 命令/指令/工具/软件/程序/二进制文件、

        由上可知,process 是一个可执行程序(64byte),因此,我们也可以称 process 为命令/指令/工具/软件/程序/二进制文件,其次,对于 ls 和 pwd 等等而言,它们可以被称为:命令/指令/工具/软件/程序/二进制文件,也可以被称为可执行程序(64byte)、

        我们自己生成的可执行程序与系统(以 Linux 操作系统为例)指令之间没有区别,他们都是可执行程序,那么为什么系统的可执行程序可以直接运行,不需要添加路径,比如直接运行:ls,ll,whoami 等等,但是我们自己生成的可执行程序要想运行,就必须要加上路径呢? 比如:./process,若运行自己生成的可执行程序但不添加路径时,则会出现以下问题:

原因:

        在 Linux 操作系统中存在相关的环境变量PATH,其次要知道,要想成功运行一个可执行程序(包括自己生成的可执行程序和系统的可执行程序),就必须要先找到它, 当运行的可执行程序(包括自己生成的可执行程序和系统的可执行程序)不添加路径时,Linux 操作系统会默认在环境变量PATH中所存储的路径下去寻找该系统的或者我们自己生成的可执行程序,又因该环境变量PATH中存储了所有的系统可执行程序的所在路径,所以当运行系统的可执行程序但不添加路径时,Linux 操作系统根据环境变量PATH中的路径能够找到该系统的可执行程序,因此当运行系统的可执行程序但不添加路径时,能够成功运行,但是,环境变量PATH中并未保存自己生成的可执行程序的所在路径,因此,当运行自己生成的可执行程序但不添加路径时,Linux 操作系统根据环境变量PATH中的路径不能找到该自己生成的可执行程序, 因此当运行自己生成的可执行程序但不添加路径时,不能成功运行,会报错:command not found 、

        当我们运行一个可执行程序(包括系统的可执行程序和自己生成的可执行程序)但不添加路径时,Linux 操作系统默认会根据环境变量PATH中的内容(多个路径),从第一个路径中开始搜索是否其中存在该可执行程序(包括系统的可执行程序和自己生成的可执行程序),若能找到,则可以成功运行,此时搜索结束,若找不到,则在下一个路径中继续搜索, 如果所有路径下都不存在该可执行程序(包括系统的可执行程序和自己生成的可执行程序),则会报错:command not found 、

        当运行的可执行程序(包括自己生成的可执行程序和系统的可执行程序)主动添加路径时,则Linux 操作系统会根据该主动添加的路径去寻找该系统的或者我们自己生成的可执行程序,而不会再去环境变量PATH中所存储的路径下去寻找该系统的或者我们自己生成的可执行程序,若我们主动添加的路径下能够找到该自己生成的可执行程序和系统的可执行程序, 则就能够成功运行,若找不到,则就会报错,不能成功运行、

拓展:

        若想直接成功运行一个我们自己生成的可执行程序但不带路径,则有如下两种方法:

方法一:

        可以将我们自己生成的可执行程序拷贝一份放到环境变量PATH中的任何一个路径下,其次,由于系统的可执行程序都存储于 /usr/bin 路径下,而环境变量PATH中又包含了该路径,因此,可将我们自己生成的可执行程序拷贝一份放到 /usr/bin 路径下,由此可知,我们能够在环境变量PATH中的 /usr/bin 路径下找到我们自己生成的可执行程序,故,当我们运行该自己生成的可执行程序但不带路径时,也是可以成功运行的,如下所示:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ ls /usr/bin/process
ls: cannot access /usr/bin/process: No such file or directory
[HJM@hjmlcc ~]$ su -
Password: 
Last login: Wed Jan  4 13:22:37 CST 2023 on pts/1
Last failed login: Fri Jan  6 13:25:21 CST 2023 from 175.23.169.25 on ssh:notty
There were 3623 failed login attempts since the last successful login.
[root@hjmlcc ~]# cp process /usr/bin
cp: cannot stat ‘process’: No such file or directory
[root@hjmlcc ~]# cd /home/HJM
[root@hjmlcc HJM]# ls
Makefile  process  process.c
[root@hjmlcc HJM]# cp process /usr/bin
//注意:此处必须要切换到root用户再进行拷贝,或者可以通过sudo cp process /usr/bin指令来完成
//拷贝、
[root@hjmlcc HJM]# su HJM
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ ls /usr/bin/process
/usr/bin/process
[HJM@hjmlcc ~]$ process   //此时直接运行我们自己生成的可执行程序且不带路径,则可以成功运行、
Hello,Lcc!
Hello,Lcc!
^C
[HJM@hjmlcc ~]$ 

        注意:最好不要将自己生成的可执行程序拷贝放到环境变量PATH中的某些路径下,因为可能会造成指令(工具/可执行程序等等)污染,比如:我们如上所示的自己生成的可执行程序放到了环境变量PATH中的路径 /usr/bin 下,如果我们更改了普通文件process.c中的内容,并重新生成了一个名字也为process的自己生成的可执行程序,此时,该名称为process的自己生成的可执行程序与之前放入到环境变量PATH中的路径 /usr/bin 下的名称为process的自己生成的可执行程序并不是同一个自己生成的可执行程序,则有可能会造成混淆,所以最好不要使用这种方法,通过下面的操作将刚刚拷贝到环境变量PATH中的路径 /usr/bin 下的自己生成的可执行程序删除掉:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ process
Hello,Lcc!
Hello,Lcc!
^C
[HJM@hjmlcc ~]$ su    //su -也是可以的、
Password: 
[root@hjmlcc HJM]# ls
Makefile  process  process.c
[root@hjmlcc HJM]# rm /usr/bin/process
rm: remove regular file ‘/usr/bin/process’? y
[root@hjmlcc HJM]# ls /usr/bin/process
ls: cannot access /usr/bin/process: No such file or directory
[root@hjmlcc HJM]# su HJM
[HJM@hjmlcc ~]$ process
bash: process: command not found
[HJM@hjmlcc ~]$ 

也可以通过指令:sudo rm /usr/bin/process 进行删除、


方法二:

        预备知识:在 Linux 命令行以及系统中,也可以定义变量(命令行变量),通常可以定义两种变量(命令行变量),如下所示:

//一:
//1、
[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ aaaaa=100          //如此定义的变量为本地(普通)变量、
[HJM@hjmlcc ~]$ echo $aaaaa
100
[HJM@hjmlcc ~]$ env | grep aaaaa   //由于这不是环境变量,所以查不到、
[HJM@hjmlcc ~]$ 

//2、
[HJM@hjmlcc ~]$ export bbbbb=123   
//如此定义的变量为环境变量(具有全局属性),在定义本地(普通)变量的同时将其导出,则该本地(普通)变
//量就会变成环境变量,也可以理解为通过这种方式直接定义了环境变量、
[HJM@hjmlcc ~]$ env | grep bbbbb
bbbbb=123
[HJM@hjmlcc ~]$ echo $bbbbb
123
[HJM@hjmlcc ~]$ 

//注意:
//echo $aaaaa可以将普通(本地)变量的内容打印在屏幕上,也可以将环境变量的内容打印在屏幕上,
//如:echo $bbbbb,其次,此处的本地(普通)变量和环境变量均具有临时性,当关闭Xshell且重新登陆用户时
//,之前设置的所有的环境变量和所有的本地(普通)变量均会消失不见、


//二:
//删除变量:
//删除本地(普通)变量或删除环境变量:
//1、删除环境变量、
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ export bbbbb=1234
[HJM@hjmlcc ~]$ echo $bbbbb
1234
[HJM@hjmlcc ~]$ env | grep bbbbb
bbbbb=1234
[HJM@hjmlcc ~]$ unset bbbbb
[HJM@hjmlcc ~]$ echo $bbbbb

[HJM@hjmlcc ~]$ env | grep bbbbb
[HJM@hjmlcc ~]$

//2、删除普通(本地)变量、
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ aaaaa=1000
[HJM@hjmlcc ~]$ echo $aaaaa
1000
[HJM@hjmlcc ~]$ env | grep aaaaa
[HJM@hjmlcc ~]$ unset aaaaa
[HJM@hjmlcc ~]$ echo $aaaaa

[HJM@hjmlcc ~]$ env | grep aaaaa
[HJM@hjmlcc ~]$ 

 注意:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ echo $PATH   //将环境变量PATH的内容打印在屏幕上、
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ export PATH=/home/HJM  //该操作会把环境变量PATH的内容更改为:/home/HJM
[HJM@hjmlcc ~]$ echo $PATH
/home/HJM
[HJM@hjmlcc ~]$ ls
-bash: ls: command not found
[HJM@hjmlcc ~]$ touch
-bash: touch: command not found
[HJM@hjmlcc ~]$ ll
-bash: ls: command not found
[HJM@hjmlcc ~]$ 

//由于在 Linux 命令行上设置(修改)的环境变量的内容具有临时性,当关闭Xshell,再次重启登录用户时,会
//发现环境变量PATH中的内容又会恢复
//到:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
//,这是因为,Linux 操作系统中的环境变量存在于内存中,且不是以文件的形式存在,当再次重启Xshell,登
//录用户时,会重新读取系统中的配置文件,重新生成环境变量,若想要改变原来的环境变量中的内容且保持永
//久有效,即重启Xshell再登录用户时也会保持修改后的内容,则需要更改配置文件,配置文件在系统中,与云
//服务器无关,上述修改环境变量中的内容只是在内存层面进行的修改,不会修改到系统中相关的配置文件,在
//系统中关于每次重启Xshell再登录用户时相关的配置文件一般可以在.bash profile和.bashrc两个普通
//文件中进行设置,了解即可、

        可以将自己生成的可执行程序所在的路径直接添加到环境变量PATH中,这样也可以解决问题,如下所示:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ process
-bash: process: command not found
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ export PATH=$PATH:/home/HJM
//$PATH即拿到了原来的环境变量PATH中的所有内容,再使用:将其与/home/HJM分隔开来,整体再赋值给新
//的环境变量PATH,此时再查看新的环境变量PATH的内容就会出现下面这样的情况,要知道,此处
//的$PATH:/home/HJM等价于/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin
//:/home/HJM/.local/bin:/home/HJM/bin:/home/HJM、
[HJM@hjmlcc ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin:/home/HJM
[HJM@hjmlcc ~]$ process
Hello,L!
Hello,L!
Hello,L!
^C
[HJM@hjmlcc ~]$ vim process.c
[HJM@hjmlcc ~]$ make
gcc process.c -o process
[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ process
Hello,Lcc!
Hello,Lcc!
^C
[HJM@hjmlcc ~]$ 

[HJM@hjmlcc ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ which ls
alias ls='ls --color=auto'
	/usr/bin/ls
[HJM@hjmlcc ~]$ which touch
/usr/bin/touch
[HJM@hjmlcc ~]$ which process
/usr/bin/which: no process in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin)
[HJM@hjmlcc ~]$ export PATH=$PATH:/home/HJM
[HJM@hjmlcc ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin:/home/HJM
[HJM@hjmlcc ~]$ which process
~/process
[HJM@hjmlcc ~]$ 

        注意:which 指令(工具/可执行程序等)是根据环境变量PATH中的所有路径去查找可执行程序(包括自己生成的可执行程序和系统的可执行程序)的、


        在 Linux 操作系统中,存在相关的环境变量PATH,该环境变量PATH中默认保存了所有系统可执行程序的搜索路径,环境变量是在开机或者登录用户时,在 Linux 操作系统中自动形成的一组变量,只要是变量,就一定存在变量名和变量内容,不同的环境变量拥有不同的应用场景,在Linux 操作系统中,存在相关的环境变量,查看环境变量的方式如下所示:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ env    //查看 Linux 操作系统中的环境变量、
XDG_SESSION_ID=571347
HOSTNAME=hjmlcc
TERM=xterm
SHELL=/bin/bash
HISTSIZE=3000
SSH_CLIENT=111.33.240.197 14986 22
SSH_TTY=/dev/pts/0
USER=HJM
LD_LIBRARY_PATH=:/home/HJM/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/HJM
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
PWD=/home/HJM
LANG=en_US.utf8
SHLVL=1
HOME=/home/HJM
LOGNAME=HJM
SSH_CONNECTION=111.33.240.197 14986 10.0.8.8 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
XDG_RUNTIME_DIR=/run/user/1002
HISTTIMEFORMAT=%F %T 
_=/usr/bin/env
[HJM@hjmlcc ~]$ 
[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ env | grep 'PATH'
LD_LIBRARY_PATH=:/home/HJM/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ env | grep PATH
LD_LIBRARY_PATH=:/home/HJM/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ 
//两种写法得到一样的结果、

打印出环境变量中的内容:

[HJM@hjmlcc ~]$ echo "aaaaa"  //将字符串"aaaaa"打印在屏幕上、
aaaaa
[HJM@hjmlcc ~]$ echo PATH     //此时PATH会被认作是字符串"PATH",并打印在屏幕上、
PATH
[HJM@hjmlcc ~]$ echo $PATH    //将环境变量PATH的内容打印在屏幕上、
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$               //:作为分隔符,分隔多个路径、

        注意:以上均是以 Linux 操作系统为例,但还要知道,在 Windows 操作系统中也存在相关的环境变量,此电脑—属性—高级系统设置—环境变量、

拓展:

当运行系统的可执行程序时,我们也可以为其添加路径,如下所示:

[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ /usr/bin/ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ /usr/bin/pwd
/home/HJM
[HJM@hjmlcc ~]$ 

常见的环境变量

[HJM@hjmlcc ~]$ env  //查看Linux操作系统下所有的环境变量、
XDG_SESSION_ID=582015
HOSTNAME=hjmlcc
TERM=xterm
SHELL=/bin/bash
HISTSIZE=3000
SSH_CLIENT=111.30.235.195 14463 22
...
...
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
XDG_RUNTIME_DIR=/run/user/1002
HISTTIMEFORMAT=%F %T 
_=/usr/bin/env
[HJM@hjmlcc ~]$ 

MANPATH:代表man手册的搜索路径、

HOSTNAME:代表当前使用的云服务器的机器名、

HISTSIZE:在 Linux 命令行中,可以使用上下键调出历史使用过的指令,该环境变量代表最多记录的历史指令条数,使用指令 history 便可查看记录下来的历史指令,还要知道,查询出来的历史指令的编号并不一定是从1开始的,可以使用指令 history | wc -l 来统计所记录下来的历史指令的条数、

PWD:代表当前使用的用户所处的路径(指定当前用户的主工作目录,即用户登陆到Linux操作系统中时,默认的目录)、

HOME:代表当前用户的家目录、

PATH:指定命令(可执行程序等等)的搜索路径、

SHELL: 当前Shell,它的值通常是/bin/bash、

        环境变量都写在配置文件中,当每一次打开Xshell,登录用户时,Linux操作系统都会自动执行相关的配置文件,从而导出环境变量,我们在Linux命令行中修改环境变量的内容时,不会改变配置文件中环境变量里的内容,所以我们每次打开Xshell,登录用户时,Linux操作系统会再次自动执行相关的配置文件,因此,我们在Linux命令行中修改的环境变量的内容具有临时性,当每一次打开Xshell,登录用户时,环境变量中的内容总保持与配置文件中的环境变量里的内容一致、

拓展:

[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ ls
Makefile  process  process.c
[HJM@hjmlcc ~]$ cd ..
[HJM@hjmlcc home]$ pwd
/home
[HJM@hjmlcc home]$ cd -  // - 代表的是家目录,此处cd -代表的就是进入普通用户HJM的家目录下、 
/home/HJM
[HJM@hjmlcc ~]$ 

基本概念

1、环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找、
2、环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性、

查看环境变量内容的方法

echo $NAME //NAME:环境变量的名称、

测试环境变量PATH

测试环境变量 PATH 请见上述所示、


拓展:

//1、
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ aaa=123  //本地(普通)变量、
[HJM@hjmlcc ~]$ echo $aaa
123
[HJM@hjmlcc ~]$ env | grep aaa
[HJM@hjmlcc ~]$ export aaa=321  //环境变量、
[HJM@hjmlcc ~]$ echo $aaa
321
[HJM@hjmlcc ~]$ env | grep aaa
aaa=321
//在定义本地(普通)变量的同时将其导出,则该本地(普通)变量就会变成环境变量,也可以理解为通过这种
//方式直接定义了环境变量、
[HJM@hjmlcc ~]$ 
//注意:此处的变量aaa由本地(普通)变量变成了环境变量、

//2、
[HJM@hjmlcc ~]$ pwd
/home/HJM
[HJM@hjmlcc ~]$ aaa=123  //本地(普通)变量、
[HJM@hjmlcc ~]$ echo $aaa
123
[HJM@hjmlcc ~]$ env | grep aaa
[HJM@hjmlcc ~]$ export aaa=123  //环境变量、
[HJM@hjmlcc ~]$ echo $aaa
123
[HJM@hjmlcc ~]$ env | grep aaa
aaa=123
//将定义好的本地(普通)变量导出,该本地(普通)变量就会变成环境变量,也可以理解为通过这种方式直接
//定义了环境变量、
//注意:此处的变量aaa由本地(普通)变量变成了环境变量、

//3、
[HJM@hjmlcc ~]$ export zzz=100  //环境变量、
[HJM@hjmlcc ~]$ echo $zzz
100
[HJM@hjmlcc ~]$ env | grep zzz
zzz=100
[HJM@hjmlcc ~]$ zzz=123  //仍是环境变量、
[HJM@hjmlcc ~]$ echo $zzz
123
[HJM@hjmlcc ~]$ env | grep zzz
zzz=123
[HJM@hjmlcc ~]$ 
[HJM@hjmlcc ~]$ qwe=100  //本地(普通)变量、
[HJM@hjmlcc ~]$ echo $qwe
100
[HJM@hjmlcc ~]$ env | grep qwe
[HJM@hjmlcc ~]$ set | grep qwe  //可以查看本地(普通)变量、
qwe=100
[HJM@hjmlcc ~]$ export ewq=200  //环境变量、
[HJM@hjmlcc ~]$ echo $ewq
200
[HJM@hjmlcc ~]$ env | grep ewq
ewq=200
[HJM@hjmlcc ~]$ set | grep ewq  //也可以查看环境变量、
ewq=200
[HJM@hjmlcc ~]$ 

与环境变量相关的命令

  • 1、echo:显示某个环境变量的内容、
  • 2、export:设置一个新的环境变量、
  • 3、env:显示所有的环境变量、
  • 4、unset:清除环境变量或普通(本地)变量、
  • 5、set:显示本地定义的shell变量(普通变量/本地变量)和环境变量、

Linux操作系统下C/C++程序代码中获取环境变量的方式

        Linux操作系统中,在Linux命令行中可以直接使用Linux操作系统拥有的环境变量,而在Linux系统下自己的C/C++程序中没有办法直接使用Linux操作系统拥有的环境变量,需要先获取,再使用,那么如何获取呢?

预备知识:


main函数可以不带参数(形参),也可以带参数,最多可以带三个参数、

int main(int argc, char* argv[], char* envp[])
{
	return 0;
}
//char* argv[]:字符指针数组、
//int argc:该字符指针数组char* argv[]的元素个数为argc+1个、
//char* envp[]:字符指针数组、

我们先谈一下它的前两个参数,先来一段代码作为测试用例:

        如上图所示,argc即为4,我们给main函数传递的形参:int argc 和 char* argv[ ] ,传递的内容本质上就是在Linux命令行中输入的可执行程序的程序名(或是./+可执行程序的程序名)和选项、

        main函数所接收到的前两个形参的来源,具体在后期进程控制时再进行阐述、

        命令行参数是指命令行中给定的参数、


拓展:

        命令行的参数以空格隔开,但是,若命令行的参数本身包含空格时,则该参数必须用一对双引号括起来、

[LCC@hjmlcc ~]$ ls
hjm.c  process.c  test.c
[LCC@hjmlcc ~]$ cat hjm.c
#include<stdio.h>
int main(int argc,char* argv[])
{
  int i;
  for(i=0;i<argc;i++)
  {
    printf("argv[%d]:%s\n",i,argv[i]);
  }
  return 0;
}
[LCC@hjmlcc ~]$ gcc hjm.c
[LCC@hjmlcc ~]$ ls
a.out  hjm.c  process.c  test.c
[LCC@hjmlcc ~]$ ./a.out
argv[0]:./a.out
[LCC@hjmlcc ~]$ ./a.out -a -b
argv[0]:./a.out
argv[1]:-a
argv[2]:-b
[LCC@hjmlcc ~]$ ./a.out -a -b "- c"
argv[0]:./a.out
argv[1]:-a
argv[2]:-b
argv[3]:- c
[LCC@hjmlcc ~]$ 

main函数的前两个形参存在的意义是什么?

通过下面这个例子来回答这个问题:

        实现一个Linux命令行版的计算器,通过在命令行中输入:./process -a 10 20 ,即可自动完成两个 int 类型的整数的相加,通过在命令行中输入:./process -s 10 20 ,即可自动完成两个 int 类型的整数的相减,其他功能具体见如下代码所示:

[HJM@hjmlcc ~]$ ls
Makefile  mycal.c
[HJM@hjmlcc ~]$ cat mycal.c
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(int argc,char* argv[])
{
  //char* argv[]:字符指针数组,该数组有argc+1个元素、
  if(argc!=4)
  {
    printf("Usage:%s [-a|-s|-m|-d] one_data two_data\n",argv[0]);
    return 0;
  }
  int x=atoi(argv[2]);  //将字符指针指向的内容转换为整数、 
  int y=atoi(argv[3]);
  if(strcmp("-a",argv[1])==0)
  {
    //加法
    printf("%d+%d=%d\n",x,y,x+y);
  }
  else if(strcmp("-s",argv[1])==0)
  {
    //减法
    printf("%d-%d=%d\n",x,y,x-y);
  }
  else if(strcmp("-m",argv[1])==0)
  {
    //乘法
    printf("%d*%d=%d\n",x,y,x*y);
  }
  else if(strcmp("-d",argv[1])==0 && y!=0)
  {
    //除法
    printf("%d/%d=%d\n",x,y,x/y);
  }
  else{
    printf("Usage:%s [-a|-s|-m|-d] one_data two_data\n",argv[0]);
  }
  return 0;
}
[HJM@hjmlcc ~]$ make
gcc mycal.c -o mycal
[HJM@hjmlcc ~]$ ./mycal -a 10 20
10+20=30
[HJM@hjmlcc ~]$ ./mycal -s 10 20
10-20=-10
[HJM@hjmlcc ~]$ ./mycal -m 10 20
10*20=200
[HJM@hjmlcc ~]$ ./mycal -d 10 20
10/20=0
[HJM@hjmlcc ~]$ ./mycal 
Usage:./mycal [-a|-s|-m|-d] one_data two_data
[HJM@hjmlcc ~]$ ./mycal -d 10 0
Usage:./mycal [-a|-s|-m|-d] one_data two_data
[HJM@hjmlcc ~]$ 

意义:

        同一份程序代码,通过接收不同的参数(形参),让同一份程序代码有不同的执行逻辑,从而得到不同的执行结果,在Linux命令行中,Linux操作系统会根据不同的选项,让不同的命令(可执行程序等等),可以有不同的表现,这就是指令(命令等等)中各个选项的由来和起作用的方式!!这也就是Linux命令行参数存在的意义,同样也就是main函数中前两个参数存在的意义,在Windows系统下,也是如此、


拓展:

如上图所示,可以完成批量替换,将所有的 process 一次性全部替换成 mycal 、 

实际上,main函数可以带第三个参数(形参),下面我们来具体谈一下:

// C或C++程序代码中获取环境变量的方式:

//方案一:
[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
int main(int argc,char* argv[],char* env[])
{
  //char* env[]:字符指针数组,该字符指针数组的最后一个元素指向空指针NULL、
  int i=0;
  for(i=0;env[i];i++)
  {
    printf("env[%d]:%s\n",i,env[i]);
  }
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
env[0]:XDG_SESSION_ID=586394
env[1]:HOSTNAME=hjmlcc
env[2]:TERM=xterm
env[3]:SHELL=/bin/bash
env[4]:HISTSIZE=3000
env[5]:SSH_CLIENT=111.30.235.195 14443 22
env[6]:SSH_TTY=/dev/pts/1
env[7]:USER=HJM
env[8]:LD_LIBRARY_PATH=:/home/HJM/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
env[9]:LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
env[10]:MAIL=/var/spool/mail/HJM
env[11]:PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
env[12]:PWD=/home/HJM
env[13]:LANG=en_US.utf8
env[14]:SHLVL=1
env[15]:HOME=/home/HJM
env[16]:LOGNAME=HJM
env[17]:SSH_CONNECTION=111.30.235.195 14443 10.0.8.8 22
env[18]:LESSOPEN=||/usr/bin/lesspipe.sh %s
env[19]:PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
env[20]:XDG_RUNTIME_DIR=/run/user/1002
env[21]:HISTTIMEFORMAT=%F %T 
env[22]:_=./a.out
[HJM@hjmlcc ~]$          //注意:字符指针数组char* env[]的元素个数与int整型变量argc无关、


//方案二:
//C语言自动定义一个第三方变量(指针变量)environ,属于全局变量、
//1、
[HJM@hjmlcc ~]$ man environ
EXEC(3P)                         POSIX Programmer's Manual                       EXEC(3P)             
PROLOG
       This manual page is part of the POSIX Programmer's Manual.  The Linux implementation of this interface may differ (con‐
       sult the corresponding Linux manual page for details of Linux behavior), or the interface may  not  be  implemented  on
       Linux.

NAME
       environ, execl, execv, execle, execve, execlp, execvp - execute a file

SYNOPSIS
       #include <unistd.h>

       extern char **environ;
       int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
       int execv(const char *path, char *const argv[]);
       int execle(const char *path, const char *arg0, ... /*,
              (char *)0, char *const envp[]*/);
       int execve(const char *path, char *const argv[], char *const envp[]);
       int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
       int execvp(const char *file, char *const argv[]);

DESCRIPTION
       The  exec  family of functions shall replace the current process image with a new process image. The new image shall be
       constructed from a regular, executable file called the new process image file. There shall be no return from a success‐
       ful exec, because the calling process image is overlaid by the new process image.

       When  a  C-language  program is executed as a result of this call, it shall be entered as a C-language function call as
       follows:

 Manual page environ(3p) line 1 (press h for help or q to quit)

//2、
[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  extern char** environ;  //仅仅是声明,不是程序员自己定义的,而是C语言自动定义的、
  int i=0;
  for(i=0;environ[i];i++)
  {
    printf("environ[%d]:%s\n",i,environ[i]);
  }
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
environ[0]:XDG_SESSION_ID=586394
environ[1]:HOSTNAME=hjmlcc
environ[2]:TERM=xterm
environ[3]:SHELL=/bin/bash
environ[4]:HISTSIZE=3000
environ[5]:SSH_CLIENT=111.30.235.195 14443 22
environ[6]:SSH_TTY=/dev/pts/1
environ[7]:USER=HJM
environ[8]:LD_LIBRARY_PATH=:/home/HJM/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
environ[9]:LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
environ[10]:MAIL=/var/spool/mail/HJM
environ[11]:PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
environ[12]:PWD=/home/HJM
environ[13]:LANG=en_US.utf8
environ[14]:SHLVL=1
environ[15]:HOME=/home/HJM
environ[16]:LOGNAME=HJM
environ[17]:SSH_CONNECTION=111.30.235.195 14443 10.0.8.8 22
environ[18]:LESSOPEN=||/usr/bin/lesspipe.sh %s
environ[19]:PROMPT_COMMAND=history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
environ[20]:XDG_RUNTIME_DIR=/run/user/1002
environ[21]:HISTTIMEFORMAT=%F %T 
environ[22]:_=./a.out
[HJM@hjmlcc ~]$          //注意:用此方法所打印出来的环境变量的个数与int整型变量argc无关、


//方案三:
//1、
[HJM@hjmlcc ~]$ man 3 getenv
GETENV(3)                      Linux Programmer's Manual                        GETENV(3)
NAME
       getenv, secure_getenv - get an environment variable

SYNOPSIS
       #include <stdlib.h>

       char *getenv(const char *name);

       char *secure_getenv(const char *name);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       secure_getenv(): _GNU_SOURCE

DESCRIPTION
       The getenv() function searches the environment list to find the environment variable name, and returns a pointer to the
       corresponding value string.

       The GNU-specific secure_getenv() function is just like getenv() except that it returns NULL in cases where "secure exe‐
       cution"  is required.  Secure execution is required if one of the following conditions was true when the program run by
       the calling process was loaded:

       *  the process's effective user ID did not match its real user ID or the process's effective group ID did not match its
          real group ID (typically this is the result of executing a set-user-ID or set-group-ID program);

       *  the effective capability bit was set on the executable file; or

       *  the process has a nonempty permitted capability set.
 Manual page getenv(3) line 1 (press h for help or q to quit)
    
//2、
[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>            
#include<stdlib.h>
int main()                   //通过putenv在C或C++程序代码中设置环境变量,在后期再进行阐述、
{
  char* val=getenv("PATH");  //返回环境变量PATH中的内容(常量字符串)首元素的地址、
  printf("%s\n",val);
  return 0;                  //常用getenv和putenv函数来访问特定的环境变量、
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/HJM/.local/bin:/home/HJM/bin
[HJM@hjmlcc ~]$ 

main函数所接收到的第三个形参(char* env[ ])的来源,具体也在后期进程控制时再进行阐述、

总结:一个进程是会被传入环境变量参数的(char* env[ ])、

拓展1:

[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
void fun()
{
  //此处即使没有任何形参,但在该调用函数内部照样可以通过某种方式读取到传递过来的实参:10和20.5,但是过程比较麻烦,了解一下即可、
  printf("Hello,Lcc\n");
}
int main()
{
  fun(10,20.5); 
//当某一个调用函数的声明和定义都没有任何形参时,如上所示:
//此时传实参也能够成功编译的,此处的两个实参也会压栈,也会形成临时变量等等,只不过是在调用函数
//fun内部没有接收而已,在Linux操作系统下编译时不会报错,但是在Windows系统下的Vs编译器下进行编
//译时会报错,这就取决于编译器了,但是如果写成void fun(void)的话,则在Linux下编译时也会报错,
//在Windows下的Vs编译器下进行编译时也会报错,此时在main函数中只能写成fun()才可以,我们之前
//写main函数时一般都不带任何形参,但要知道,本质上是已经给main函数传递了三个参数,只不过是main
//函数并没有接收而已,在Windows下的Vs编译器下编译时,main函数不带任何形参是不会报错的,这一点与
//该例子不同,要注意、
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc
[HJM@hjmlcc ~]$ 

拓展2:

预备知识:

        首先要明白,环境变量USER的值并不能简单的取决于当前用户,即:环境变量USER的值并不是简单的取决于通过指令whoami得到的值(当前用户),而是,环境变量USER的值代表的是当前登录用户,若当前登录用户发生了改变,那么环境变量USER的值就会随之发生改变,而对于指令 su 而言,只是改变了当前用户(将当前用户改变为root用户),但是并未改变当前登录用户,所以环境变量USER的值不会发生改变,而对于 su - 指令而言,不仅会改变当前用户(将当前用户改变为root用户),还会改变当前登录用户,因此环境变量USER的值也会随之改变,但是要注意,指令su 普通用户,此时不仅会改变当前用户,还会改变当前登录用户,因此环境变量USER的值也会随之改变、

总结:

        通过指令whoami得到的结果只是当前用户,而环境变量USER代表的是当前登录用户

在大部分情况下,当前用户与当前登录用户是一致的,但在部分情况下,指令whoami得到的结果和环境变量USER的值是不一样的(比如普通用户HJM仅仅通过 su 指令,将当前用户切换到了root用户,但是当前登录用户仍是普通用户HJM,因此环境变量USER的值仍是普通用户HJM,而不是root用户),所以我们不能简单的把指令whoami得到的结果(当前用户)直接看做环境变量USER的值、

        环境变量是用来定义操作系统环境的,因此如果操作系统环境没有随用户身份(当前用户)切换的话,很多命令都无法正确执行,su 指令只是切换了当前用户(将当前用户改变为root用户),但是Shell环境并未发生改变,而指令 su - 不仅切换了当前用户(将当前用户改变为root用户),也切换了Shell环境,只用 su 指令不会读取目标用户的环境配置文件,但 su - 指令则会读取,所以我们之后再切换当前用户时,最好都带上 - ,避免出现不必要的错误,su 和 su - 指令在Linux和AIX操作系统下存在一定的区别,在AIX操作系统中一定要加上 - 、

具体请见博客:

su 和su -的区别_水墨胭脂的博客-CSDN博客_su和su -参考文章:(总结)Linux下su与su -命令的本质区别   我一直是习惯使用su username来切换用户的,而且并不知道su和su -有什么区别,一直以为是没啥区别的,但是在一个测试中,在测试的同事的指导下,他说你su - ××× 之后×××,那一刻突然福至心灵觉得可能二者是有区别的,然后执行了su - 用户 之后,果然得到了su 用户的时候得不到的结果。。。。。然后还发现,以前执行dbhttps://blog.csdn.net/nayanminxing/article/details/76424115?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167335462916800182133259%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=167335462916800182133259&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-76424115-null-null.142%5Ev70%5Eone_line,201%5Ev4%5Eadd_ask&utm_term=su%E5%92%8Csu%20-&spm=1018.2226.3001.4187(总结)Linux下su与su -命令的本质区别http://www.ha97.com/4001.html为什么要获取环境变量(在Linux操作系统下的C/C++程序中为什么要获取环境变量)? 

        若在Linux操作系统下写一个只能当前登录用户(以普通用户HJM为例,即环境变量USER的值为普通用户HJM)运行的C/C++程序代码,此时就需要在Linux操作系统下的C/C++程序中获取环境变量,如下所示:

[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
  char* id=getenv("USER");
  if(strcasecmp(id,"HJM")!=0)  //比较时忽略大小写、
  { 
    printf("权限拒绝!\n");
  }
  else{
    printf("成功执行!\n");
  }
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ whoami
HJM
[HJM@hjmlcc ~]$ echo $USER
HJM
[HJM@hjmlcc ~]$ ./a.out
成功执行!
[HJM@hjmlcc ~]$ su -
Password: 
Last login: Wed Jan 11 11:32:38 CST 2023 on pts/1
[root@hjmlcc ~]# pwd
/root
[root@hjmlcc ~]# cd /home/HJM
[root@hjmlcc HJM]# ls
a.out  Makefile  mycal.c  process.c
[root@hjmlcc HJM]# whoami
root
[root@hjmlcc HJM]# echo $USER
root
[root@hjmlcc HJM]# ./a.out
权限拒绝!
[root@hjmlcc HJM]# su - HJM
Last login: Wed Jan 11 11:34:01 CST 2023 on pts/1
[HJM@hjmlcc ~]$ su
Password: 
[root@hjmlcc HJM]# pwd
/home/HJM
[root@hjmlcc HJM]# whoami
root
[root@hjmlcc HJM]# echo $USER
HJM
[root@hjmlcc HJM]# ls
a.out  Makefile  mycal.c  process.c
[root@hjmlcc HJM]# ./a.out
成功执行!
[root@hjmlcc HJM]# su -
Last login: Wed Jan 11 11:35:15 CST 2023 on pts/1
[root@hjmlcc ~]# su - LCC
Last login: Wed Jan 11 10:52:43 CST 2023 on pts/1
[LCC@hjmlcc ~]$ pwd
/home/LCC
[LCC@hjmlcc ~]$ whoami
LCC
[LCC@hjmlcc ~]$ echo $USER
LCC
[LCC@hjmlcc ~]$ pwd
/home/LCC
[LCC@hjmlcc ~]$ cd /home/HJM
[LCC@hjmlcc HJM]$ ls
a.out  Makefile  mycal.c  process.c
[LCC@hjmlcc HJM]$ ./a.out
权限拒绝!
[LCC@hjmlcc HJM]$ su -
Password: 
Last login: Wed Jan 11 11:58:26 CST 2023 on pts/1
[root@hjmlcc ~]# whoami
root
[root@hjmlcc ~]# echo $USER
root
[root@hjmlcc ~]# su LCC
[LCC@hjmlcc root]$ whoami
LCC
[LCC@hjmlcc root]$ echo $USER
LCC
[LCC@hjmlcc root]$ cd /home/HJM
[LCC@hjmlcc HJM]$ ls
a.out  Makefile  mycal.c  process.c
[LCC@hjmlcc HJM]$ ./a.out
权限拒绝!
[LCC@hjmlcc HJM]$ 

//综上,环境变量一定在某些地方有特殊用途,上面粗略的展示了其中一个方面、 
//由上述例子可推断,我们之前学习 权限 时,底层实现逻辑与此处该例子类似、

环境变量的组织方式        

        每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以字符 '\0' 结尾的环境常量字符串、


环境变量通常具有全局属性

        本地(普通)变量只在本Shell内有效,而环境变量则是全局有效,我们从Linux系统的角度来理解一下:

[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
#include<unistd.h>
int main()
{
  while(1)
  {
    printf("Hello,Lcc,PID:%d,PPID:%d\n",getpid(),getppid());
    sleep(2);
  }
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc,PID:30455,PPID:26215  //PID:30455,PPID:26215
Hello,Lcc,PID:30455,PPID:26215
^C
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc,PID:30472,PPID:26215  //PID:30472,PPID:26215
Hello,Lcc,PID:30472,PPID:26215
^C
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc,PID:30480,PPID:26215  //PID:30480,PPID:26215
Hello,Lcc,PID:30480,PPID:26215
^C
[HJM@hjmlcc ~]$ 

//1、
//当运行一个可执行程序时则会得到一个进程,Linux操作系统会为其分配PID,结束(退出)该进程,再次运
//行该可执行程序时又会得到一个新的进程,这两个进程并不是同一个进程,Linux操作系统则会为新的进
//程重新分配PID,所以会得到两个不同的PID,但是这两个进程的父进程是同一个进程(bash进程),所以
//PPID的值是不会发生改变的,其中,当我们打开Xshell并登录用户时,此时bash进程就会被启动,直
//到Xshell被关闭退出时,bash进程才会结束(退出),在此期间,bash进程是一直时实运行的,bash进程就
//是当我们打开Xshell并登录用户时,Linux操作系统给我们创建的一个命令行解释器、

//2、
//若在另外一个SSH渠道中通过指令kill -9 26215来杀掉原来的SSH渠道中的bash进程,则此时在原来的
//SSH渠道中再输入的任何内容都将不会再有任何反应,相当于该SSH渠道下的Linux命令行就挂掉了,这是
//因为,我们在Linux命令行中正常使用指令时(指令又是可执行程序,使用指令就相当于是运行可执行程序
//因此会得到一个进程),这些指令本质上是需要首先被其对应的bash进程(父进程)所获取的,当其对应的
//bash进程(父进程)被杀掉后,我们再使用这些指令时,其对应的bash进程(父进程)就无法正常的获取这些
//指令,因此,这些指令将不再能够正确地发挥其作用了、

//3、
//bash也是一个进程,bash进程所对应的可执行程序所存在的路径为:/usr/bin,当每一次通过Xshell或者其
//他登录软件进行用户登录时,Linux操作系统就会为当前用户创建一个bash进程,因此当我们再一次打
//开Xshell,登录用户时,Linux操作系统就会为当前用户创建一个新的bash进程,再运行可执行程序
//a.out时,该新的bash进程就是该运行可执行程序a.out所得到的进程的父进程,此时PPID就会发生变化,
//因为此时的bash进程和之前的bash进程并不是同一个进程,所以,PPID的值会发生改变、
[HJM@hjmlcc ~]$ ls /usr/bin/bash
/usr/bin/bash
[HJM@hjmlcc ~]$ 

//4、
//bash进程也是使用C/C++写的,因此我们可以使用bash进程对应的可执行程序对应的代码中的scanf或
//cin来获取当前用户在Linux命令行中输入的内容、

//5、
//若打开Xshell登录用户后,新建多个会话,则Linux操作系统会为多个会话各自创建一个bash进程,这多
//个bash进程并不是同一个进程,所以这多个bash进程的PID的值是不同的、

        在Linux命令行中启动的进程(包括运行自己生成的可执行程序与运行系统的可执行程序所得到的进程)的父进程全部都是bash进程,bash进程的底层逻辑也是通过fork的形式来创建子进程的,至于fork之后,Linux操作系统是如何将自己生成的可执行程序或系统的可执行程序加载进来并被运行从而形成进程的,以及bash进程的子进程又是如何被启动并为子进程传递Linux命令行参数和环境变量参数的问题,在后期的进程控制中再进行具体的阐述、


环境变量通常具有全局属性:

[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ cat process.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
  while(1)
  {
    printf("Hello,Lcc,PID:%d,PPID:%d,myenv=%s\n",getpid(),getppid(),getenv("LCC"));
    sleep(1);
  }
  return 0;
}
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc,PID:29911,PPID:9456,myenv=(null)     //不存在环境变量LCC、
Hello,Lcc,PID:29911,PPID:9456,myenv=(null)
Hello,Lcc,PID:29911,PPID:9456,myenv=(null)
Hello,Lcc,PID:29911,PPID:9456,myenv=(null)
Hello,Lcc,PID:29911,PPID:9456,myenv=(null)
^C
[HJM@hjmlcc ~]$ LCC=100                        //定义在bash进程内部的本地(普通)变量、
[HJM@hjmlcc ~]$ gcc process.c
[HJM@hjmlcc ~]$ ls
a.out  Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ ./a.out
//此时在Linux命令行中运行可执行程序a.out则会启动一个进程,该进程的父进程是bash进程,而本地(普通
//)变量LCC定义在bash进程的内部,但本地(普通)变量不能被子进程继承下去,所以对于bash进程的子进
//程(此处由运行可执行程序a.out所得的进程)而言,是不能从bash进程内部继承到本地(普通)变量LCC的,
//所以此处对于该子进程而言,仍然不存在环境变量LCC、
Hello,Lcc,PID:30316,PPID:9456,myenv=(null)
Hello,Lcc,PID:30316,PPID:9456,myenv=(null)     //不存在环境变量LCC、
Hello,Lcc,PID:30316,PPID:9456,myenv=(null)
^C
[HJM@hjmlcc ~]$ echo $LCC
100
[HJM@hjmlcc ~]$ env | grep LCC
[HJM@hjmlcc ~]$ set | grep LCC
LCC=100
[HJM@hjmlcc ~]$ export LCC
//将定义好的本地(普通)变量导出,该本地(普通)变量就会变成环境变量,该环境变量也相当于是定义在bash进程内部的、
[HJM@hjmlcc ~]$ echo $LCC
100
[HJM@hjmlcc ~]$ set | grep LCC
LCC=100
[HJM@hjmlcc ~]$ env | grep LCC
LCC=100
[HJM@hjmlcc ~]$ ./a.out
Hello,Lcc,PID:31302,PPID:9456,myenv=100     //存在环境变量LCC、
Hello,Lcc,PID:31302,PPID:9456,myenv=100
Hello,Lcc,PID:31302,PPID:9456,myenv=100
^C
[HJM@hjmlcc ~]$ 
//此时在Linux命令行中运行可执行程序a.out则会启动一个进程,该进程的父进程是bash进程,环境变量
//LCC定义在bash进程的内部,但环境变量能够被子进程继承下去,所以对于bash进程的子进程(此处由运行
//可执行程序a.out所得的进程)而言,是能够从bash进程内部继承到环境变量LCC的,所以此处对于该子进
//程而言,可以使用环境变量LCC,故得出上述结果、

总结:

        当我们打开Xshell,登录用户后,bash进程便被启动了,我们此时所在的页面就是在bash进程内部,因此,在Linux命令行中定义的本地(普通)变量或环境变量都是在bash进程内部定义的,而所谓的环境变量具有全局性,在全局均有效的意思即指:环境变量是能够被子进程继承下去的!!!,若我们在Linux命令行中定义了一个环境变量,即相当于在bash进程的内部定义了一个环境变量,又因环境变量能够被子进程继承,所以,该环境变量会被bash进程的所有子进程均继承,而对于bash进程的子进程而言,也存在与之对应的子进程,并且环境变量能够被子进程继承,所以该环境变量能够被bash进程的子进程的子进程继承,由此可知,若在bash进程内部定义了一个环境变量,则该环境变量会被bash进程的所有子进程继承,所谓继承也即代表着能够使用该环境变量,由于在bash进程的内部定义的该环境变量,所以对于bash进程而言可以使用该环境变量,再由上可知,bash进程的所有的子进程均能使用该定义在bash进程内部的环境变量,总结来说就是,bash进程以及bash进程后面所有的子进程均可使用该定义在bash进程内部的环境变量,这就是所谓的环境变量具有全局性,即在全局均有效、

        在Linux命令行中定义的本地(普通)变量也是在bash进程的内部定义的,但是本地(普通)变量不会被子进程继承下去,也就是说,由于本地(普通)变量是在bash进程内部定义的,所以在bash进程的内部是可以使用该本地(普通)变量的,但又因为本地(普通)变量不会被子进程继承下去,所以在bash进程的所有子进程中(bash进程除外)都不能使用该本地(普通)变量,只能在bash进程内部使用该本地(普通)变量,所谓的本地(普通)变量只在本Shell内有效,即指本地(普通)变量只能在bash进程内部有效,要注意,此处不考虑bash进程与其所有子进程的包含与被包含关系,默认为bash进程与其所有的子进程之间两两互相独立、

残留问题:

        在Linux命令行中输入的所有内容,一定需要先被bash进程读取,在bash进程内部对这些内容进行分析,将本地(普通)变量和环境变量保存在bash进程内部的变量列表中,保存在bash进程内部的进程上下文中、


[HJM@hjmlcc ~]$ ls
Makefile  mycal.c  process.c
[HJM@hjmlcc ~]$ local_val=hello     //本地(普通)变量、
[HJM@hjmlcc ~]$ echo $local_val
hello
[HJM@hjmlcc ~]$ 

//问:
//由上可知,变量loacl_val是本地(普通)变量,echo指令也是可执行程序,运行(使用)他的时候将会启动一个
//进程,而在Linux命令行中启动的进程的父进程都是bash进程,所以通过指令echo $local_val得到的进程
//是bash进程的子进程,我们又知道,对于普通(本地)变量local_val而言,是定义在bash进程内部的,并且本
//地(普通)变量不能被子进程继承,那么为什么通过指令echo $local_val得到的进程(bash进程的子进程)
//能够读取到该本地(普通)变量local_val的值并将其打印在屏幕上的呢?

//答:
//在Linux操作系统中,在Linux命令行中运行的指令大部分都是以bash进程的子进程(先创建子进程,让子进
//程完成这些指令相对应的功能)的方式执行的,但是还存在一部分在Linux命令行中运行的指令并不是通
//过bash进程的子进程的方式进行执行的,而是由bash进程自己运行(不会创建子进程,而是bash进程直接调
//用自己对应的函数来完成特定的功能),比如指令:echo,set,exoprt,cd等等,我们称这类指令为内建命令,
//即一些bash进程非常信任的命令,此时bash进程并不会通过其子进程帮其运行这些命令,而是bash进程自己
//运行这些命令,对于指令:set | grep local_val的原理也是如上、

补充:关于指令:export  cd 为什么是内建命令的原因请见视频:

进程地址空间:00:23:00 - 00:26:10、

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

< Linux >:环境变量 的相关文章

  • 如何查明 Ubuntu 上安装了哪个版本的 GTK+?

    我需要确定 Ubuntu 上安装了哪个版本的 GTK 男人似乎不帮忙 这个建议 https stackoverflow com a 126145 会告诉您安装了哪个 2 0 的次要版本 不同的主要版本将具有不同的包名称 因为它们可以在系统上
  • 如何成功使用RDAP协议代替whois

    我对新的 RDAP 协议有点困惑 也不知道何时进一步追求它有意义 在我看来 每个人都同意它是 whois 的继承者 但他们的数据库似乎是空的 在 ubuntu 上我尝试了 rdapper nicinfo 甚至他们的 RESTful API
  • 如何获取 linux 实用程序 tail 的源代码?

    这个命令确实非常有用 但是我可以在哪里获取源代码以查看内部发生的情况 thanks tail 实用程序是 Linux 上 coreutils 的一部分 源压缩包 ftp ftp gnu org gnu coreutils coreutils
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 无法执行'x86_64-conda_cos6-linux-gnu-gcc':没有这样的文件或目录(pysam安装)

    我正在尝试安装 pysam 执行后 python path to pysam master setup py build 这个错误的产生是 unable to execute x86 64 conda cos6 linux gnu gcc
  • 为 Qt 应用程序创建 Linux 安装

    我刚刚用 Qt Creator 制作了一个很棒的程序 我对自己很满意 如何将其从台式机移至笔记本电脑 那么 最好的方法是安装程序 对吗 对于 Ubuntu 这是一个 Debian 软件包 对吗 我怎么做 有人这样做过吗 他们可以分享 QT
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • 如何查找连接到 AF_INET 套接字的客户端的 UID?

    有什么方法或类似的东西ucred for AF UNIX如果是AF INET插座 TCP在我的例子中 找出连接到我的套接字的客户端的UID 还有 proc net tcp但它显示了UID of the creator插座的而不是连接的cli
  • Docker:处理 tar 文件时出错(退出状态 1):设置枢轴目录时出错:不是目录

    我是 Docker 新手 不知道是什么原因导致此错误或如何诊断它 任何有关此问题的具体帮助或有关首先检查何处以诊断此类问题的提示将不胜感激 我的 Dockerfile FROM java 8 Install maven RUN apt ge
  • 没有可用的符号表信息

    我正在测试第三方的库 它崩溃了 当我想查看崩溃的原因时 我的 gdb 告诉我没有可用的调试符号 Program received signal SIGSEGV Segmentation fault Switching to Thread 0
  • 在 /dev/input/eventX 中写入事件需要哪些命令?

    我正在开发一个android需要将触摸事件发送到 dev input eventX 的应用程序 我知道C执行此类操作的代码结构如下 struct input event struct timeval time unsigned short
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 在主目录中安装库

    在 Linux Ubuntu 中 我尝试运行一个工具 但它显示错误 库丢失 我无权在系统中安装任何内容 或者根本无法从我的用户帐户执行 sudo 是否可以在我的主目录 没有 sudo 中安装缺少的库 在我的例子中为 libstdc so 6
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • Godaddy 托管上的 CakePHP 控制台

    我一直在努力让我的 CakePHP 网站在 Godaddy 网格托管 帐户上运行 我的蛋糕应用程序设置是从帐户的子目录托管的 并且可以通过子域访问 我必须调整我的 htaccess 文件才能使其正常工作 现在我需要让 CakePHP 控制台
  • 从 PL/SQL 调用 shell 脚本,但 shell 以 grid 用户而非 oracle 身份执行

    我正在尝试使用 Runtime getRuntime exec 从 Oracle 数据库内部执行 shell 脚本 在 Red Hat 5 5 上运行的 Oracle 11 2 0 4 EE CREATE OR REPLACE proced
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 创建 jar 文件 - 保留文件权限

    我想知道如何创建一个保留其内容的文件权限的 jar 文件 我将源代码和可执行文件打包在一个 jar 文件中 该文件将在使用前提取 人们应该能够通过运行批处理 shell 脚本文件立即运行示例和演示 然后他们应该能够修改源代码并重新编译所有内
  • Bash 解析和 shell 扩展

    我对 bash 解析输入和执行扩展的方式感到困惑 对于输入来说 hello world 作为 bash 中的参数传递给显示其输入内容的脚本 我不太确定 Bash 如何解析它 Example var hello world displaywh

随机推荐

  • Tomcat安装及部署

    Aphorism 安装 忽略下载过程 1 解压文件 把 tomcat 安装包解压到 D Program Files 下 2 启动 tomcat 在 tomcat 文件包的 bin 文件夹中 双击 startup bat 文件启动tomcat
  • 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。(C++实现)

    题目介绍 给定一个链表 删除链表的倒数第 n 个节点 并且返回链表的头结点 示例 给定一个链表 1 gt 2 gt 3 gt 4 gt 5 和 n 2 当删除了倒数第二个节点后 链表变为 1 gt 2 gt 3 gt 5 说明 给定的 n
  • Oil Deposits

    http poj org problem id 1562 Oil Deposits Description The GeoSurvComp geologic survey company is responsible for detecti
  • 10个超炫超有用的js库/插件

    原文地址 http blog csdn net shyy123 article details 7471782 1 CodeMirror CodeMirror 是一款 Online Source Editor 基于 Javascript 短
  • MyEclipse集成PMD代码检测插件自定义规则配置文件

    把我今天最新更新的MyEclipse2014集成PMD代码检测插件自定义规则配置文件JAVA版发布出来吧 方便自己以后回顾的同时 也看看能不能帮到有这方面需求的小伙伴们 文件名 cplatform pmd5 2 3 rules xml
  • Android.bp文件简介

    Android bp Android bp的出现就是为了替换Android mk文件 bp跟mk文件不同 它是纯粹的配置 没有分支 循环等流程控制 不能做算数逻辑运算 如果需要控制逻辑 那么只能通过Go语言编写 语法 根据设计 Androi
  • 为什么opencv用GPU实现比用CPU实现的慢?

    问题 打算通过OpenCV的GPU模块优化现有代码的运行效率 怀抱着美好愿望开始了代码的改写工作 改写的过程并不顺利 遇到了不少问题 例如 gpu模块提供的接口非常坑爹 相当一部分不支持浮点类型 像histogram integral这类常
  • SpringCloud实践(四) 通过Feign组件实现消费者

    在前面使用了RestTemplate和Ribbon来实现了服务消费者 Feign 是一个集成了Ribbon和Eureka的组件 通过声明的方式 就可以实现Http客户端 简化了http客户端 服务消费者 对于Feign 我们只要记得两个特点
  • Aspose工具实现word和ppt转pdf功能及遇到的一些问题

    Aspose工具包从word和ppt转到pdf的实现过程 直接放项目地址 说一下实现过程中遇到的坑 直接放项目地址 https github com lichangliu1098 File2Pdf 说一下实现过程中遇到的坑 jar包的引入
  • Zabbix部署详细步骤

    以下是在Ubuntu上安装Zabbix的详细步骤 1 更新系统 使用以下命令更新Ubuntu系统 sudo apt get update sudo apt get upgrade 2 安装依赖项 在安装Zabbix之前 需要先安装一些依赖项
  • 教你快速上手Flex弹性盒布局(容器属性)

    目录 简介 一 Flex布局语法 1 1 display flex 二 Flex属性 三 容器属性 3 1 flex direction 3 2 flex direction row 3 3 flex direction row rever
  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为 2023A卷和2023B卷 你收
  • Tachyon内存文件系统

    Tachyon内存文件系统 Tachyon是以内存为中心的分布式文件系统 拥有高性能和容错能力 能够为集群框架 如Spark MapReduce 提供可靠的内存级速度的文件共享服务 从软件栈的层次来看 Tachyon是位于现有大数据计算框架
  • 使用GitHub的一些小知识合集

    文章目录 一 FastGithub 1 稳定可靠的github加速神器 FastGithub 2 github加速神器 FastGithub 二 README md添加图片 1 怎么给README md添加图片 两种方法 图文教程 2 在R
  • OpenCV代码提取:morphologyEx函数的实现

    Morphological Operations A set of operations that process images based on shapes Morphological operations apply a struct
  • keil软件安装与破解

    目录 目录 下载 安装 破解 下载 学习51单片机必要的开发工具是 KEIL C51 下载密码dsfs 安装 按照一般安装软件顺序即可 此处随便填写 破解 注意 需以管理员身份 运行 按照如下图片步骤 弹出如下对话框 再打开软件按如下操作
  • 解决pycharm错误:Error updating package list: connect timed out解决

    方法是在 Manage Repositories 中 修改数据来源 默认的是 https pypi python org simple 我们可将其替换为如下的几个数据来源 这些都是国内的pip镜像 清华 https pypi tuna ts
  • Vue3 emits选项将Emit派发事件可以对参数进行验证。

    Vue官方建议我们在组件中所有的emit事件都能在组件的emits选项中声明 emits参数有俩种形式对象和数组 对象里面可以配置带校验emit事件 为null的时候代表不校验 校验的时候 会把emit事件的参数传到校验函数的参数里面 当校
  • Python第三方库之MedPy

    文章目录 1 MedPy简介 2 MedPy安装 3 MedPy常用函数 3 1 medpy io load image 3 2 medpy metric binary dc result reference 3 3 medpy metri
  • < Linux >:环境变量

    目录 环境变量 常见的环境变量 基本概念 查看环境变量内容的方法 测试环境变量PATH 与环境变量相关的命令 Linux操作系统下C C 程序代码中获取环境变量的方式 环境变量的组织方式 环境变量通常具有全局属性 环境变量 问题 注意 可执