【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读
版权声明:本文为博主原创文章,未经博主允许不得转载。
这个年代, 大家写点书, 也无非就是为了搞点钱, 基本都是罗列一些知识点, 基本都是写给已经会了的人看的。 真正用心写书的人, 不多。 如果真正用心写书, 且站在读者的角度去写, 那就少之又少了。
关于linux shell环境变量, 我看了四本linux相关书的介绍, 结果, 没有一本书的讲解让我完全满意, 总感觉没有说清楚。所以呢, 我打算自己来写一下,如有不当指出, 请大家指正。
一. 永久环境变量(实际上属于文件, 而不属于shell, 每打开一个shell, 都会加载/导入到shell中, 形成当前shell的临时环境变量)
先说说"永久环境变量", 其实, 我也知道, 没有什么东西是真正永久的, 这里的永久是指: 变量存储在文件中, 不会因为掉电或者关机而消失。下面, 我们打开一个linux shell, 并打印HOME的值, 如下:
- [taoge@localhost Desktop]$ echo $HOME
- /home/taoge
[taoge@localhost Desktop]$ echo $HOME
/home/taoge
我们看到HOME这个变量的值是/home/taoge, 这个变量的值是从哪里来的呢? 我们可以看看用户主目录下的.bashrc文件
- [taoge@localhost Desktop]$ cat ~/.bashrc
[taoge@localhost Desktop]$ cat ~/.bashrc
其中的内容为:
- # .bashrc
- # Source global definitions
- if [ -f /etc/bashrc ]; then
- . /etc/bashrc
- fi
- # 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掉呢? 我们来看一下:
- [taoge@localhost Desktop]$ echo $HOME
- /home/taoge
- [taoge@localhost Desktop]$ unset HOME
- [taoge@localhost Desktop]$ echo $HOME
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $HOME
/home/taoge
[taoge@localhost Desktop]$ unset HOME
[taoge@localhost Desktop]$ echo $HOME [taoge@localhost Desktop]$
我们看到, 当前shell进程中的HOME确实是被unset掉了, 不要着急, 我们另外打开一个shell进程, 然后看看有没有HOME, 如下:
- [taoge@localhost Desktop]$ echo $HOME
- /home/taoge
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $HOME
/home/taoge
[taoge@localhost Desktop]$
可以看到, 第二个shell进程中是有HOME的, 这个不难理解, 因为开启第二个shell进程的时候, 会把~/.bashrc中的永久HOME加载一次, 所以可以看到/home/taoge.
我们暂时来总结一下: 永久环境变量存在于~/.bashrc文件中(掉电或者重启后, 不会消失), 在每个shell启动的时候, 都会将永久环境变量导入到shell中, 并成为shell的临时环境变量, 这个临时的环境变量可以被unset掉后, 但不会影响其他shell, 因为我们即将会说到, 不同shell的临时环境变量是彼此独立的。
你可能还在纠结并不耐烦地发出疑问:在~/.bashrc中没有看到HOME啊, 你不是在扯淡么? 好, 我们自己来把一个变量写入到~/.bashrc文件中, 使之成为永久环境变量, ~/.bashrc文件内容如下:
- # .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"
# .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这个变量, 如下:
- [taoge@localhost Desktop]$ echo $winner
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $winner [taoge@localhost Desktop]$
遗憾的是, 我们没有看到winner, 为什么呢? 因为现在只是把winner变成了永久环境变量, 这个永久环境变量并没有加载到当前的shell中来啊! 好吧, 我们关掉当前的shell, 并打开一个新的shell, 再查看一次, 如下:
- [taoge@localhost Desktop]$ echo $winner
- people who persists
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $winner
people who persists
[taoge@localhost Desktop]$
可以看到, 这次winner有值了, 激动吧。 这样, 无论以后是重启linux, 还是怎么滴, winner就成为了文件的一部分, 就成了永久的环境变量了。 当然, 你要是把~/.bashrc文件中的winner那一行删除了, 然后跟我说:你不是说永久的么? 现在怎么不永久啦? 好吧, 你这是在故意找茬。
二. 临时的环境变量(属于当前shell及其子进程)
上面我们已经说了, winner成了永久的环境变量, 当一个shell开启的时候, 便会加载这个winner变量, 那么在当前shell环境中, 这个winner就会变成临时的环境变量。 之所以说是临时的, 是因为你可以把他unset掉, 之所以说是环境变量, 意思是说(没被unset掉的时候), 当前shell进程的子进程可以访问到该winner, 如下:
- [taoge@localhost Desktop]$ echo $$
- 7203
- [taoge@localhost Desktop]$ echo $winner
- people who persists
- [taoge@localhost Desktop]$ bash
- [taoge@localhost Desktop]$ echo $$
- 7354
- [taoge@localhost Desktop]$ echo $winner
- people who persists
- [taoge@localhost Desktop]$ exit
- exit
- [taoge@localhost Desktop]$ echo $$
- 7203
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $$
7203
[taoge@localhost Desktop]$ echo $winner
people who persists
[taoge@localhost Desktop]$ bash
[taoge@localhost Desktop]$ echo $$
7354
[taoge@localhost Desktop]$ echo $winner
people who persists
[taoge@localhost Desktop]$ exit
exit
[taoge@localhost Desktop]$ echo $$
7203
[taoge@localhost Desktop]$
我们看到, 当前进程pid是7203, 为它再开一个子shell进程, 子进程的pid为7354, 我们可以看到, 在进程中, 也可以访问到winner.
上面的winner是~/.bashrc中永久环境变量加载而来的, 那我们可不可以自定义临时环境变量呢? 可以的。 这次, 我们运行a.sh脚本来做当前shell的子进程, 如下:
- [taoge@localhost Desktop]$ export x="defined in shell"
- [taoge@localhost Desktop]$ vim a.sh
- [taoge@localhost Desktop]$ cat a.sh
- #! /bin/bash
- echo $x
- [taoge@localhost Desktop]$ chmod +x a.sh
- [taoge@localhost Desktop]$ ./a.sh
- defined in shell
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ export x="defined in shell"
[taoge@localhost Desktop]$ vim a.sh
[taoge@localhost Desktop]$ cat a.sh
#! /bin/bash
echo $x
[taoge@localhost Desktop]$ chmod +x a.sh
[taoge@localhost Desktop]$ ./a.sh
defined in shell
[taoge@localhost Desktop]$
可以看到, 在脚本子进程中, 也可以访问x这个临时的环境变量。 好, 我问个问题, 那别的shell能访问这个x么? 我们再开启另外一个shell, 如下:
- [taoge@localhost Desktop]$ echo $x
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ echo $x [taoge@localhost Desktop]$
肯定是没有啊, 上面的一些例子都揭露了临时环境变量的本质: 当前shell的临时环境变量, 能被自己及其子进程(子shell进程, 子脚本进程或者子C程序进程)访问, 但不能被其它shell访问(相互独立)。 对了, 我们上面已经讨论过了, 临时的环境变量可以被unset掉。在实际大型的软件开发中, 编译大工程, 经常需要用到临时环境变量。
三. 普通变量(属于当前shell进程)
shell中的普通变量很简单, 仅能被当前shell访问, 不能被其子进程访问, 更不能被其它shell访问。 当然, 它也可以被unset掉, 测试如下:
- [taoge@localhost Desktop]$ z="f(y)"
- [taoge@localhost Desktop]$ echo $z
- f(y)
- [taoge@localhost Desktop]$ echo $$
- 7578
- [taoge@localhost Desktop]$ bash
- [taoge@localhost Desktop]$ echo $$
- 7653
- [taoge@localhost Desktop]$ echo $z
- [taoge@localhost Desktop]$ exit
- exit
- [taoge@localhost Desktop]$ echo $$
- 7578
- [taoge@localhost Desktop]$ unset z
- [taoge@localhost Desktop]$ echo $z
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ z="f(y)"
[taoge@localhost Desktop]$ echo $z
f(y)
[taoge@localhost Desktop]$ echo $$
7578
[taoge@localhost Desktop]$ bash
[taoge@localhost Desktop]$ echo $$
7653
[taoge@localhost Desktop]$ echo $z [taoge@localhost Desktop]$ exit
exit
[taoge@localhost Desktop]$ echo $$
7578
[taoge@localhost Desktop]$ unset z
[taoge@localhost Desktop]$ echo $z [taoge@localhost Desktop]$
- [taoge@localhost Desktop]$ z="f(y)"
- [taoge@localhost Desktop]$ echo $z
- f(y)
- [taoge@localhost Desktop]$ echo $$
- 7578
- [taoge@localhost Desktop]$ export z
- [taoge@localhost Desktop]$ bash
- [taoge@localhost Desktop]$ echo $$
- 7723
- [taoge@localhost Desktop]$ echo $z
- f(y)
- [taoge@localhost Desktop]$ exit
- exit
- [taoge@localhost Desktop]$ echo $$
- 7578
- [taoge@localhost Desktop]$
[taoge@localhost Desktop]$ z="f(y)"
[taoge@localhost Desktop]$ echo $z
f(y)
[taoge@localhost Desktop]$ echo $$
7578
[taoge@localhost Desktop]$ export z
[taoge@localhost Desktop]$ bash
[taoge@localhost Desktop]$ echo $$
7723
[taoge@localhost Desktop]$ echo $z
f(y)
[taoge@localhost Desktop]$ exit
exit
[taoge@localhost Desktop]$ echo $$
7578
[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://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
【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读的更多相关文章
- Shell变量的作用域:Shell全局变量、环境变量和局部变量
Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他 ...
- js学习之变量、作用域和内存问题
js学习之变量.作用域和内存问题 标签(空格分隔): javascript 变量 1.基本类型和引用类型: 基本类型值:Undefined, Null, Boolean, Number, String ...
- python - 函数的相互调用 及 变量的作用域
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: study_函数的相互调用及变量的作用域.py@ide: PyCharm C ...
- C/C++中变量的作用域和存储类型简介
写在开头 对于很多C/C++的初学者来说,很容易理不清变量的作用域和存储类型这一块的一些概念,也容易将其中的一些概念搞混淆.作为一个C/C++的初学者,笔者希望在这里能够尝试着去理一理这些较为繁杂的概 ...
- linux 中的局部变量、全局变量、shell 变量的总结
系统局部变量和全局变量 一.变量分类局部变量和环境变量,局部变量只适用于当前shell,而环境变量是全局的,它适用于所有当前shell以及其派生出来的任意子进程,有些变量是用户创建的,其他的则是专用 ...
- Linux centosVMware shell 管道符和作业控制、shell变量、环境变量配置文件
一.管道符和作业控制 管道符|,用于将前一个指令的输出作为后一个指令的输入 #cat /etc/passwd|wc -l 作业控制:当运行程序时,可以使它暂停(Ctrl+Z组合键),然后使用fg(f ...
- Shell命令和流程控制[linux常用命令的使用]
在shell脚本中使用三类命令: unix命令 概念:管道.重定向.backtick 流程控制 1 unix命令 echo "some text":在屏幕上输出信息 ls:文件列表 ...
- linux - 怎么自动填写有交互的shell脚本 - SegmentFault
linux - 怎么自动填写有交互的shell脚本 - SegmentFault TCL/Expect交互式自动化测试概要 - - ITeye技术网站 expect是一种基于TCL,能与交互式程序进行 ...
- ./ . 和#!/bin/bash 辨析Linux如何选择当前执行脚本的shell
最近遇到一个有趣的问题,让我搞清楚Linux如何选择当前执行脚本的shell 执行cts的的 media stress test 需要安装 android-cts-media-1.0.zip 把这个文 ...
随机推荐
- Java学习笔记(十一)——通过JDBC操作mysql数据库
[前面的话] 时间总是好快,每次都感觉还没有怎么好好去过,对于好多事情,希望自己可以做的更多一点.心情能够好一点,平淡一点就行了. 学习过程中的知识点总结,基础知识,选择阅读. [JDBC定义] 定义 ...
- Linux搭建主从数据库服务器(主从复制)
配置主机数据库: 1.克隆linux操作系统 2.修改Linux系统主机IP地址 主机IP:192.168.247.150 从机IP:192.168.247.151 3.通过xshell连接Maste ...
- scrapy抓取拉勾网职位信息(一)——scrapy初识及lagou爬虫项目建立
本次以scrapy抓取拉勾网职位信息作为scrapy学习的一个实战演练 python版本:3.7.1 框架:scrapy(pip直接安装可能会报错,如果是vc++环境不满足,建议直接安装一个visua ...
- Continuous Subarray Sum II(LintCode)
Continuous Subarray Sum II Given an circular integer array (the next element of the last element i ...
- shell 文本加密
第一种:[ Python 与 Bash Shell 的结合 ]这个命令会让你输入一个字符串,然后会再输出一串加密了的数字. 加密代码[照直输入]:python -c 'print reduce(lam ...
- 「NOI2018」归程
「NOI2018」归程 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 >\(1\) 个节点. \(m\) 条边的无向连通图(节点的编号从 \( ...
- 【Splay】Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) B. Cards Sorting
Splay要支持找最左侧的最小值所在的位置.类似线段树一样处理一下,如果左子树最小值等于全局最小值,就查左子树:否则如果当前节点等于全局最小值,就查当前节点:否则查右子树. 为了统计答案,当然还得维护 ...
- 【哈希】CDOJ1717 京电的神秘矩阵
对每个矩阵里的元素用两个大素数做双关键字哈希,丢进set即可. #include<cstdio> #include<iostream> #include<set> ...
- bzoj 2073: [POI2004]PRZ
2073: [POI2004]PRZ Description 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 桥已经很旧了, 所以它不能承受太重的东西. 任何时候队伍在桥上的 ...
- 活动中使用提示框(Toast)
任务名称:活动中使用Toast 任务现象:点击button时,会弹出提示框:You Click Button 步骤 1.创建一个项目,新建活动和加载布局.参考: http://8c925c9a.wiz ...