linux shell 解读 “永久环境变量” “临时环境变量”和普通变量

el/2024/7/17 21:21:56


        一. 永久环境变量(实际上属于文件, 而不属于shell, 每打开一个shell, 都会加载/导入到shell中, 形成当前shell的临时环境变量)

        先说说"永久环境变量", 其实, 我也知道, 没有什么东西是真正永久的, 这里的永久是指: 变量存储在文件中, 不会因为掉电或者关机而消失。下面, 我们打开一个linux shell, 并打印HOME的值, 如下:

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $HOME  
  2. /home/taoge   

       我们看到HOME这个变量的值是/home/taoge, 这个变量的值是从哪里来的呢? 我们可以看看用户主目录下的.bashrc文件

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ cat ~/.bashrc   

      其中的内容为:

[plain]  view plain  copy
  1. # .bashrc  
  2.   
  3. # Source global definitions  
  4. if [ -f /etc/bashrc ]; then  
  5.         . /etc/bashrc  
  6. fi  
  7.   
  8. # User specific aliases and functions  

       啊? 居然没有HOME? 不要着急, 先姑且认为是在/etc/bashrc中进行了HOME的设置吧, 在此, 我们不深究, 只需要有这个认识: HOME与文件~/.bashrc密切相关, 即使断电或者掉电, 也不怕消失。


      实际上, 当我们开启一个shell进程的时候, HOME这个永久环境变量会自动导入到当前的shell中来(为当前shell设置了一个临时的环境变量), 那这个HOME可不可以被unset掉呢? 我们来看一下:

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $HOME  
  2. /home/taoge  
  3. [taoge@localhost Desktop]$ unset HOME  
  4. [taoge@localhost Desktop]$ echo $HOME  
  5.   
  6. [taoge@localhost Desktop]$   

      我们看到, 当前shell进程中的HOME确实是被unset掉了, 不要着急, 我们另外打开一个shell进程, 然后看看有没有HOME,  如下:

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $HOME  
  2. /home/taoge  
  3. [taoge@localhost Desktop]$  
      可以看到, 第二个shell进程中是有HOME的, 这个不难理解, 因为开启第二个shell进程的时候, 会把~/.bashrc中的永久HOME加载一次, 所以可以看到/home/taoge.


      我们暂时来总结一下: 永久环境变量存在于~/.bashrc文件中(掉电或者重启后, 不会消失), 在每个shell启动的时候, 都会将永久环境变量导入到shell中, 并成为shell的临时环境变量, 这个临时的环境变量可以被unset掉后, 但不会影响其他shell, 因为我们即将会说到, 不同shell的临时环境变量是彼此独立的。


      你可能还在纠结并不耐烦地发出疑问:在~/.bashrc中没有看到HOME啊, 你不是在扯淡么? 好, 我们自己来把一个变量写入到~/.bashrc文件中, 使之成为永久环境变量, ~/.bashrc文件内容如下:

[plain]  view plain  copy
  1. # .bashrc  
  2.   
  3. # Source global definitions  
  4. if [ -f /etc/bashrc ]; then  
  5.         . /etc/bashrc  
  6. fi  
  7.   
  8. # User specific aliases and functions  
  9.   
  10.   
  11. # define permanent variable by taoge  
  12. winner="people who persists"  
      我定义winner这个变量的值为“people who persists”, 好, 保存文件, 我们来查看一下winner这个变量, 如下:
[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $winner  
  2.   
  3. [taoge@localhost Desktop]$    

      遗憾的是, 我们没有看到winner, 为什么呢? 因为现在只是把winner变成了永久环境变量, 这个永久环境变量并没有加载到当前的shell中来啊! 好吧, 我们关掉当前的shell, 并打开一个新的shell,  再查看一次, 如下:(source  ~/.bashrc)

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $winner  
  2. people who persists  
  3. [taoge@localhost Desktop]$   

      可以看到, 这次winner有值了, 激动吧。 这样, 无论以后是重启linux, 还是怎么滴, winner就成为了文件的一部分, 就成了永久的环境变量了。 当然, 你要是把~/.bashrc文件中的winner那一行删除了, 然后跟我说:你不是说永久的么? 现在怎么不永久啦?  好吧, 你这是在故意找茬。


      二. 临时的环境变量(属于当前shell及其子进程)

       上面我们已经说了, winner成了永久的环境变量, 当一个shell开启的时候, 便会加载这个winner变量, 那么在当前shell环境中, 这个winner就会变成临时的环境变量。 之所以说是临时的, 是因为你可以把他unset掉,之所以说是环境变量, 意思是说(没被unset掉的时候), 当前shell进程的子进程可以访问到该winner, 如下:

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $$  
  2. 7203  
  3. [taoge@localhost Desktop]$ echo $winner  
  4. people who persists  
  5. [taoge@localhost Desktop]$ bash  
  6. [taoge@localhost Desktop]$ echo $$  
  7. 7354  
  8. [taoge@localhost Desktop]$ echo $winner  
  9. people who persists  
  10. [taoge@localhost Desktop]$ exit  
  11. exit  
  12. [taoge@localhost Desktop]$ echo $$  
  13. 7203  
  14. [taoge@localhost Desktop]$   

      我们看到, 当前进程pid是7203, 为它再开一个子shell进程(bash) , 子进程的pid为7354, 我们可以看到, 在进程中, 也可以访问到winner.   

      上面的winner是~/.bashrc中永久环境变量加载而来的, 那我们可不可以自定义临时环境变量呢? 可以的。 这次, 我们运行a.sh脚本来做当前shell的子进程, 如下:

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ export x="defined in shell"  
  2. [taoge@localhost Desktop]$ vim a.sh  
  3. [taoge@localhost Desktop]$ cat a.sh   
  4. #! /bin/bash  
  5. echo $x  
  6. [taoge@localhost Desktop]$ chmod +x a.sh   
  7. [taoge@localhost Desktop]$ ./a.sh   
  8. defined in shell  
  9. [taoge@localhost Desktop]$   
     可以看到, 在脚本子进程中, 也可以访问x这个临时的环境变量。 好, 我问个问题, 那别的shell能访问这个x么?  我们再开启另外一个shell, 如下:
[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ echo $x  
  2.   
  3. [taoge@localhost Desktop]$    

     肯定是没有啊, 上面的一些例子都揭露了临时环境变量的本质: 当前shell的临时环境变量, 能被自己及其子进程(子shell进程, 子脚本进程或者子C程序进程)访问, 但不能被其它shell访问(相互独立)。 对了, 我们上面已经讨论过了, 临时的环境变量可以被unset掉。在实际大型的软件开发中, 编译大工程, 经常需要用到临时环境变量。


      三. 普通变量(属于当前shell进程)

      shell中的普通变量很简单, 仅能被当前shell访问, 不能被其子进程访问, 更不能被其它shell访问。 当然, 它也可以被unset掉, 测试如下:(使用bash命令,开启一个子进程。exit退出子进程。)

[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ z="f(y)"  
  2. [taoge@localhost Desktop]$ echo $z  
  3. f(y)  
  4. [taoge@localhost Desktop]$ echo $$  
  5. 7578  
  6. [taoge@localhost Desktop]$ bash  
  7. [taoge@localhost Desktop]$ echo $$  
  8. 7653  
  9. [taoge@localhost Desktop]$ echo $z  
  10.   
  11. [taoge@localhost Desktop]$ exit  
  12. exit  
  13. [taoge@localhost Desktop]$ echo $$  
  14. 7578  
  15. [taoge@localhost Desktop]$ unset z  
  16. [taoge@localhost Desktop]$ echo $z  
  17.   
  18. [taoge@localhost Desktop]$  
可见, 确实不能被子shell访问, 当然, 肯定更不能被其它shell访问了。   普通变量要提升了临时的环境变量, 那也很简单, 加一下 export就可以了, 如下:
[plain]  view plain  copy
  1. [taoge@localhost Desktop]$ z="f(y)"  
  2. [taoge@localhost Desktop]$ echo $z  
  3. f(y)  
  4. [taoge@localhost Desktop]$ echo $$  
  5. 7578  
  6. [taoge@localhost Desktop]$ export z  
  7. [taoge@localhost Desktop]$ bash  
  8. [taoge@localhost Desktop]$ echo $$  
  9. 7723  
  10. [taoge@localhost Desktop]$ echo $z  
  11. f(y)  
  12. [taoge@localhost Desktop]$ exit  
  13. exit  
  14. [taoge@localhost Desktop]$ echo $$  
  15. 7578  
  16. [taoge@localhost Desktop]$   


       啰嗦地总结一下: shell中的普通变量, 仅能被当前shell访问, 不能被其子进程访问, 更不能被其它shell访问。 当然, 它也可以被unset掉。


      OK,  我觉得我应该说清楚了, 早休息!



       补充: 

      1. 实际上, 我们也可以在~/.bashrc中设置alias别名, 这个用起来很方便, 每个shell(包括子shell)都可以用到。 修改好后, 不用再关掉shell打开shell了, 直接在当前shell中执行source ~/.bashrc即可。

      2. 如果自己在当前shell中定义一个alias, 那么仅在当前shell进程中有效, 我们没法用export使得它在子shell中生效, 毕竟, alias和上面讲的变量还是有所区别的。 如果是在脚本中定义alias, 则也必须用source来执行, 使得alias在当前shell中生效, 我经常这么玩。





http://www.ngui.cc/el/5557143.html

相关文章

SQL左连接、右连接、笛卡尔积的表现形式

表A记录如下: aID aNum 1 a20050111 2 a20050112 3 a20050113 4 a20050114 5 a20050115 表B记录如下: bID bName 1 2006032401 2 2006032402 3 2006032…

Shell脚本中执行sql语句,操作mysql数据库

对于自动化运维,诸如备份恢复之类的,DBA经常需要将SQL语句封装到shell脚本。本文描述了在Linux环境下mysql数据库中,shell脚本下调用sql语句的几种方法,供大家参考。对于脚本输出的结果美化,需要进一步完善和调整。以下…

django get_object_or_404

django get_object_or_404 是django shortcuts模块里面一个比较简便的方法,特别是用django get来操作数据库的时候,可以帮 我们少写一些代码,加快开发速度。 get_object_or_404的介绍: 我们原来调用django 的get方法,…

sql语句每个关键字的执行顺序

SQL 不同于与其他编程语言的最明显特征是处理代码的顺序。在大数编程语言中,代码按编码顺序被处理,但是在SQL语言中,第一个被处理的子句是FROM子句,尽管SELECT语句第一个出现,但是几乎总是最后被处理。 每个步骤都会产…

Linux下进程在后台可靠运行(nohup/)和前后台运行程序切换

我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败。如何让命令提交后不受本地关闭终端窗口、网络断开连接的干扰呢? 下面举了一些例子&…

Java线程池(newCachedThreadPool、newFixedThreadPool、newScheduledThreadPool 、newSingleThreadExector )

1、new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() {Overridepublic void run() {// TODO Auto-generated method stub}} ).start(); 那你就out太多了,new Thread的弊端如下: a. 每次new Thread新建…

linux如何设置无密码登录mysql(如何设置无密码登陆mysql)

Linux下每次用mysql连接连接服务器,常常用如下方式: [rootlocalhost ~]# mysql ( -hlocalhost ) -uroot -proot 每次都输入用户名,密码,多折腾人啊,有没有更方便的方式? 我们只需要简单地配置下my.cnf文件…

Django model字段类型详解

Django 通过 models 实现数据库的创建、修改、删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField:一个自动递增的整型字段,添加记录时它会自动增长。你通常不需要直接使用这个字段;…

django的request、session没有获取到值,赋默认值

接受request的数据 从post中取得数据,如果不存在则默认值为1 pageNumber request.POST.get(pageNumber,1) 从get中取得数据,如果不存在则默认值为1 pageNumber request.GET.get(pageNumber,1) 从所有请求中取得数据,如果不存在则默认值为1 …

你知道 Linux 内核是如何构建的吗?

介绍 我不会告诉你怎么在自己的电脑上去构建、安装一个定制化的 Linux 内核,这样的资料太多了,它们会对你有帮助。本文会告诉你当你在内核源码路径里敲下make 时会发生什么。 当我刚刚开始学习内核代码时,Makefile 是我打开的第一个文件&…