【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读

2015-05-08 00:15 3896人阅读 评论(10) 收藏 举报

本文章已收录于:

分类:

软件开发进阶(419)

作者同类文章X

Unix/Linux杂项(118)

作者同类文章X

版权声明:本文为博主原创文章,未经博主允许不得转载。

这个年代, 大家写点书, 也无非就是为了搞点钱, 基本都是罗列一些知识点, 基本都是写给已经会了的人看的。 真正用心写书的人, 不多。 如果真正用心写书, 且站在读者的角度去写, 那就少之又少了。

关于linux shell环境变量, 我看了四本linux相关书的介绍, 结果, 没有一本书的讲解让我完全满意, 总感觉没有说清楚。所以呢, 我打算自己来写一下,如有不当指出, 请大家指正。

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

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $HOME
  2. /home/taoge
[[email protected] Desktop]$ echo $HOME
/home/taoge 

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ cat ~/.bashrc
[[email protected] Desktop]$ cat ~/.bashrc 

其中的内容为:

[plain] view plain copy print?

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

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions

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

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $HOME
  2. /home/taoge
  3. [[email protected] Desktop]$ unset HOME
  4. [[email protected] Desktop]$ echo $HOME
  5. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $HOME
/home/taoge
[[email protected] Desktop]$ unset HOME
[[email protected] Desktop]$ echo $HOME

[[email protected] Desktop]$ 

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $HOME
  2. /home/taoge
  3. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $HOME
/home/taoge
[[email protected] Desktop]$

可以看到, 第二个shell进程中是有HOME的, 这个不难理解, 因为开启第二个shell进程的时候, 会把~/.bashrc中的永久HOME加载一次, 所以可以看到/home/taoge.

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

 

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

[plain] view plain copy print?

  1. # .bashrc
  2. # Source global definitions
  3. if [ -f /etc/bashrc ]; then
  4. . /etc/bashrc
  5. fi
  6. # User specific aliases and functions
  7. # define permanent variable by taoge
  8. winner="people who persists"
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions

# define permanent variable by taoge
winner="people who persists"

我定义winner这个变量的值为“people who persists”, 好, 保存文件, 我们来查看一下winner这个变量, 如下:

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $winner
  2. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $winner

[[email protected] Desktop]$  

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $winner
  2. people who persists
  3. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $winner
people who persists
[[email protected] Desktop]$ 

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

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

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $$
  2. 7203
  3. [[email protected] Desktop]$ echo $winner
  4. people who persists
  5. [[email protected] Desktop]$ bash
  6. [[email protected] Desktop]$ echo $$
  7. 7354
  8. [[email protected] Desktop]$ echo $winner
  9. people who persists
  10. [[email protected] Desktop]$ exit
  11. exit
  12. [[email protected] Desktop]$ echo $$
  13. 7203
  14. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $$
7203
[[email protected] Desktop]$ echo $winner
people who persists
[[email protected] Desktop]$ bash
[[email protected] Desktop]$ echo $$
7354
[[email protected] Desktop]$ echo $winner
people who persists
[[email protected] Desktop]$ exit
exit
[[email protected] Desktop]$ echo $$
7203
[[email protected] Desktop]$ 

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

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

[plain] view plain copy print?

  1. [[email protected] Desktop]$ export x="defined in shell"
  2. [[email protected] Desktop]$ vim a.sh
  3. [[email protected] Desktop]$ cat a.sh
  4. #! /bin/bash
  5. echo $x
  6. [[email protected] Desktop]$ chmod +x a.sh
  7. [[email protected] Desktop]$ ./a.sh
  8. defined in shell
  9. [[email protected] Desktop]$
[[email protected] Desktop]$ export x="defined in shell"
[[email protected] Desktop]$ vim a.sh
[[email protected] Desktop]$ cat a.sh
#! /bin/bash
echo $x
[[email protected] Desktop]$ chmod +x a.sh
[[email protected] Desktop]$ ./a.sh
defined in shell
[[email protected] Desktop]$ 

可以看到, 在脚本子进程中, 也可以访问x这个临时的环境变量。 好, 我问个问题, 那别的shell能访问这个x么?  我们再开启另外一个shell, 如下:

[plain] view plain copy print?

  1. [[email protected] Desktop]$ echo $x
  2. [[email protected] Desktop]$
[[email protected] Desktop]$ echo $x

[[email protected] Desktop]$  

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

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

shell中的普通变量很简单, 仅能被当前shell访问, 不能被其子进程访问, 更不能被其它shell访问。 当然, 它也可以被unset掉, 测试如下:

[plain] view plain copy print?

  1. [[email protected] Desktop]$ z="f(y)"
  2. [[email protected] Desktop]$ echo $z
  3. f(y)
  4. [[email protected] Desktop]$ echo $$
  5. 7578
  6. [[email protected] Desktop]$ bash
  7. [[email protected] Desktop]$ echo $$
  8. 7653
  9. [[email protected] Desktop]$ echo $z
  10. [[email protected] Desktop]$ exit
  11. exit
  12. [[email protected] Desktop]$ echo $$
  13. 7578
  14. [[email protected] Desktop]$ unset z
  15. [[email protected] Desktop]$ echo $z
  16. [[email protected] Desktop]$
[[email protected] Desktop]$ z="f(y)"
[[email protected] Desktop]$ echo $z
f(y)
[[email protected] Desktop]$ echo $$
7578
[[email protected] Desktop]$ bash
[t[email protected] Desktop]$ echo $$
7653
[[email protected] Desktop]$ echo $z

[[email protected] Desktop]$ exit
exit
[[email protected] Desktop]$ echo $$
7578
[[email protected] Desktop]$ unset z
[[email protected] Desktop]$ echo $z

[[email protected] Desktop]$

可见, 确实不能被子shell访问, 当然, 肯定更不能被其它shell访问了。   普通变量要提升了临时的环境变量, 那也很简单, 加一下export就可以了, 如下:

[plain] view plain copy print?

  1. [[email protected] Desktop]$ z="f(y)"
  2. [[email protected] Desktop]$ echo $z
  3. f(y)
  4. [[email protected] Desktop]$ echo $$
  5. 7578
  6. [[email protected] Desktop]$ export z
  7. [[email protected] Desktop]$ bash
  8. [[email protected] Desktop]$ echo $$
  9. 7723
  10. [[email protected] Desktop]$ echo $z
  11. f(y)
  12. [[email protected] Desktop]$ exit
  13. exit
  14. [[email protected] Desktop]$ echo $$
  15. 7578
  16. [[email protected] Desktop]$
[[email protected] Desktop]$ z="f(y)"
[[email protected] Desktop]$ echo $z
f(y)
[[email protected] Desktop]$ echo $$
7578
[[email protected] Desktop]$ export z
[[email protected] Desktop]$ bash
[[email protected] Desktop]$ echo $$
7723
[[email protected] Desktop]$ echo $z
f(y)
[[email protected] Desktop]$ exit
exit
[[email protected] Desktop]$ echo $$
7578
[[email protected] 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://blog.csdn.net/stpeace/article/details/45567977

Shell if else语句:http://c.biancheng.net/cpp/view/7005.html

http://www.jb51.net/article/34332.htm

http://zhidao.baidu.com/link?url=Autj00HdRPo5jA_Y5739uGonHER4rfWXR_uGnpuEMwl829D5jmftWPBJ9fYUI0kvxqaurUEcH4VyMrz2Ts0rSK

时间: 2024-11-08 22:11:09

【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读的相关文章

Shell变量的作用域:Shell全局变量、环境变量和局部变量

Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱.但是如果同一个班级中有两个叫小明的同学,就必须用类似于“大小明”.“小小明”这样的命名来区分他们. Shell 变量的作用域可以分为三种: 有的变量只能在函数内部使用,这叫做局部变量(local variable)

《javascript高级程序设计》读书笔记(三)变量、作用域和内存问题

 第四章:变量.作用域和内存问题 检测类型:typeof是确定一个变量是字符串.数值.布尔值,还是undefined的最佳工具,但是如果变量的值是一个对象或null,typeof只会返回"object",使用typeof检测函数时,会返回"function". 要是检测引用数据类型,可以用instanceof操作符,所用引用类型都是Object的实例. 垃圾收集 1.标记清除(mark-and-sweep) 2.引用计数 (reference counting) 管

【javascript基础】3、变量和作用域

原文:[javascript基础]3.变量和作用域 前言 这篇和大家说一下javascript中的变量和作用域,由于是将基础嘛,主要给大家捋一下知识,不想翻开书复习的道友可以看一下,打算刚开始学习javascript的同学可以扫一眼. PS:jQuery源码交流群( 239147101)等你来,群里高手云集,让我受益匪浅,尽量少灌水. 变量 javascript中有两种变量,分别是基本类型和引用类型,基本类型是Null,Undefined,String,Boolean,Number这五种,前面简

python - 函数的相互调用 及 变量的作用域

# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: study_函数的相互调用及变量的作用域.py@ide: PyCharm Community Edition@time: 2018-11-10 10:04@blog: https://www.cnblogs.com/gotesting/ ''' # 1. 函数的相互调用# 从上往下按顺序执行 def print_msg(content): print('我想说:{}'.fo

C/C++中变量的作用域和存储类型简介

写在开头 对于很多C/C++的初学者来说,很容易理不清变量的作用域和存储类型这一块的一些概念,也容易将其中的一些概念搞混淆.作为一个C/C++的初学者,笔者希望在这里能够尝试着去理一理这些较为繁杂的概念,主要当作自己备忘之用.当然,由于笔者水平有限,经验不足,在这里也只能罗列一些常用概念和使用方法,且可能会有些许不专业之处,望君理解并指正. 一定要把变量的作用域和存储类型分开来看 很多人很容易把变量的作用于和存储类型搞混,但其实只要我们从它们定义出发来看,这个问题是很容易解决的.作用域是一个变量

《跟老男孩学Linux运维之shell编程实战》-第二章 shell变量的核心基础

这篇文章主要讲解 shell变量的核心基础. 1.变量是什么? 变量是什么?可能有好多人不明白,简单地说,变量就是用一个固定的字符串(也可能是字符.数字等的组合)代替更多.更复杂的内容,该内容里可能还会包含变量.路径.字符串等其他的内容. 变量的赋值方式为:先写变量名称,紧接着是"="这个字符,最后是值,中间无任何空格(变量的内容一般要加双引号,以防止出错,特别是当值里的内容之间有空格时). 如何打印变量?通过echo命令加上$变量名 打印变量的值: 例如:定义变量和打印变量: [[e

linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读

这个年代, 大家写点书, 也无非就是为了搞点钱, 基本都是罗列一些知识点, 基本都是写给已经会了的人看的. 真正用心写书的人, 不多. 如果真正用心写书, 且站在读者的角度去写, 那就少之又少了. 关于linux shell环境变量, 我看了四本linux相关书的介绍, 结果, 没有一本书的讲解让我完全满意, 总感觉没有说清楚.所以呢, 我打算自己来写一下,如有不当指出, 请大家指正. 一. 永久环境变量(实际上属于文件, 而不属于shell, 每打开一个shell, 都会加载/导入到shell

linux下的shell命令的编写,以及java如何调用linux的shell命令(java如何获取linux上的网卡的ip信息)

程序员都很懒,你懂的! 最近在开发中,需要用到服务器的ip和mac信息.但是服务器是架设在linux系统上的,对于多网口,在获取ip时就产生了很大的问题.下面是在windows系统上,java获取本地ip的方法.贴代码: package com.herman.test; import java.net.InetAddress; /** * @see 获取计算机ip * @author Herman.Xiong * @date 2014年5月16日 09:35:38 */ public class

Linux操作系统基础解析之(七)——Bash(Shell)基础知识(1)

在日常交际英语中,Shell可以翻译成壳,大多指能够对内部核心起到保护作用的一种装置或结构.在计算机科学中,shell其实是指:为操作者提供的.能够通过系统调用或库调用使用整个计算机资源的访问接口. 它既是一种命令解析器又是一种程序设计语言.作为命令解析器,它可以解释和执行用户输入的命令,也可以自动地解释和执行预先编写好并保存在某个文本文件中的一系列的命令:作为程序设计语言,shell特别定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和条件分支,让我们可以像使用高级语言