最近在被Shell脚本中的export
关键字所困!记录一下,谈谈自己的理解。
目录:
0、预热:粗略了解Linux父、子进程
1、Shell执行脚本的几种方式
----1.0 source [script_file_name]
执行
----1.1 . [script_file_name]
点符号执行
----1.2 指定某个shell来执行
----1.3 相对或绝对路径/script_file_name
执行
----1.4 实例
2、export关键字终出场
----2.0 Linux中变量类型知多少
---- 2.1 export实践
这里仅做我自己的简要理解,因为每一个深究都是一门大学问,没必要,但再次深深感觉到计算机基本组成原理知识的重要性。在此只是为了有助于利于export
。
Linux是一个多用户多任务的操作系统,必须要支持多个用户同时登录同一个操作系统的操作。当一个用户登录一次时,操作系统就为这个用户创建一个新会话(比如Shell(就是我们常说的【终端】))。
Linux系统中,进程之间有一个明显的继承关系,所有进程都是 PID 为1的 init 进程
的后代。内核在系统启动的最后阶段启动 init 进程
。该进程读取系统的初始化脚本(initscript)
并执行其他的相关程序,最终完成系统启动的整个过程。
用户登陆Linux,就获得一个bash(Shell),之后你的bash(Shell)就是一个独立的进程(Shell 父进程)。之后你在bash(Shell)下面执行的任何命令都是由这个bash所衍生的,那些被执行的命令被称为子进程(Shell子进程)。
子进程只会继承父进程的环境变量,子进程不会继承父进程的自定义变量。那么你原本bash中的自定义变量在进入子进程后就会消失不见,一直到你离开子进程并回到原本的父进程后,这个变量才会出现。除非把自定义变量设置为环境变量 export name
Linux中的进程及进程控制
分为两大类,4小类。本质上都得指明脚本文件所在路径,即怎么找到它。
1、在当前shell中执行【相对或绝对路径下都行】,这两个本质是一样的
source script_file_name
. script_file_name 中间有1个空格
2、在当前shell(父进程)开启一个【子shell(子进程)】中执行,
脚本一旦执行完后子shell环境将随即关闭,然后又回到父shell中,而无法再访问脚本中的变量的(不管有没有export)。
【无论脚本中是否有#!/bin/bash这行,都会开启子shell去执行】
sh script_file_name
相对或绝对路径/script_file_name【若脚本无#!/bin/bash,则会选择系统默认shell执行它】
一个规范的Shell脚本在第一行指出由哪个程序(解释器)来执行脚本的内容,而这一行内容在Linux bash一般为:
#!/bin/bash
#或
#!/bin/sh
#sh为bash的软链接。更规范的写法是bash。
创建一个hello.sh
脚本
[root@master Cshell]# pwd
/usr/local/src/Cshell
[root@master Cshell]# vim hello.sh
#!/bin/bash
a="hello"
export MY_VAR="MY_VAR"
echo "Hello World!"
source [script_file_name]
执行[root@master Cshell]# pwd
/usr/local/src/Cshell
[cyg@master Cshell]$ source hello.sh #当前工作路径下
Hello World!
[cyg@master Cshell]$ cd ..
[cyg@master src]$ pwd
/usr/local/src
[cyg@master src]$ source /usr/local/src/Cshell/hello.sh #绝对路径下
Hello World!
[cyg@master src]$ source ./Cshell/hello.sh #相对路径下
Hello World!
常见例子:source /etc/profile
,作用是使【设置的针对所有用户(不只是root)登录时都会运行的系统级别的环境变量的配置文件/etc/profile
】立即生效,而不必注销并重新登录。
. [script_file_name]
点符号执行[root@master Cshell]# pwd
/usr/local/src/Cshell
[cyg@master Cshell]$ . hello.sh
Hello World!
[cyg@master Cshell]$ cd ..
[cyg@master src]$ pwd
/usr/local/src
[cyg@master src]$ . /usr/local/src/Cshell/hello.sh
Hello World!
[cyg@master src]$ . ./Cshell/hello.sh
Hello World!
小结:source
或 .
(点符号)功能是:读入脚本并执行脚本
source
是bash内置命令;点符号是source
另一名称[root@master Cshell]# echo $a # a是hello.sh中的一个普通变量
[root@master Cshell]# source hello.sh
Hello World!
[root@master Cshell]# echo $a
hello
[root@master Cshell]# ll
-rw-r--r-- 1 root root 67 May 31 16:08 hello.sh
[root@master Cshell]# sh hello.sh
Hello World!
[bash] [file_name.sh]
。由这里指定的shell运行这个脚本,与Linux登录的哪个用户也无关(如root、或其他用户);sh命令
来执行。即 此时不是hello.sh
自己来执行,而是被sh
所调用来执行,所以甚至可以不要:
#!/bin/bash
,指定bash路径相对或绝对路径/script_file_name
执行PATH
的内容之中(echo $PATH
可查看)。[cyg@master src]$ pwd
/usr/local/src
[cyg@master src]$ ./Cshell/hello.sh #相对路径
bash: ./Cshell/hello.sh: Permission denied
[cyg@master src]$ /usr/local/src/Cshell/hello.sh #绝对路径
bash: /usr/local/src/Cshell/hello.sh: Permission denied
[cyg@master src]$ cd Cshell
[cyg@master Cshell]$ ./hello.sh #当前路径
bash: ./hello.sh: Permission denied
都提示Permission denied
,没有执行权限,无法执行。
[cyg@master Cshell]$ ll #可看到该文件拥有者是root,只有它才有能力修改权限
-rw-r--r-- 1 root root 67 May 31 16:08 hello.sh
[cyg@master Cshell]$ su
Password:
[root@master Cshell]# chmod a+x hello.sh
[root@master Cshell]# /usr/local/src/Cshell/hello.sh
Hello World!
[root@master Cshell]# ./hello.sh #这里的点 是指当前路径,不要点符号搞混了!
Hello World!
[root@master Cshell]# cd ..
[root@master src]# ./Cshell/hello.sh
Hello World!
source 或. /script_file_name
),对于脚本中的变量,变量不管是否有export
,一旦执行脚本完毕,是还可以在当前shell中访问脚本中的变量的。相对或绝对路径/script_file_name
或 [bash] [file_name.sh]
执行),一旦执行完毕,随即返回父shell,脚本中的变量将无法访问。实例
[root@master Cshell]# pwd
/usr/local/src/Cshell
[root@master Cshell]# vim w.sh
h="hello"
export w="world"
echo $h
[root@master Cshell]# chmod +x w.sh
[root@master Cshell]# ./w.sh
hello
[root@master Cshell]# echo $h #不管有无export,都将无法再访问这两个变量了。
[root@master Cshell]# echo $w
[root@master Cshell]# . ./w.sh
hello
[root@master Cshell]# echo $h
hello
[root@master Cshell]# echo $w
world
到目前为止,export
还没真正登场,只有预热。前面的预热都是为了更好地掌握export
。
这里只说下个人理解的人为分类。
再次回到一句话:Linux是多用户多任务操作系统。在一个Linxu系统上,用户一般情况下一定有两类:
为了更好地理解export
,在此仅将变量分为两大类:
所以,为了方便管理和持久化,会将环境变量写入一些配置文件中。相应地也分成了系统级、用户级配置文件:
/etc/profile
、/etc/bashrc
、等,对其的修改将影响到每一个用户。~/.profile
、~/.bashrc
等,对其的修改只对该用户有影响。常见环境变量有PATH
、HOME
、HISTSIZE
、SHELL
、PS1
、LANG
、RANDOM
等等。
在执行时,对于环境变量(包括不同级别的配置文件)、普通变量,是有顺序的。
Linux环境变量文件介绍
Shell变量之自定义变量、环境变量
import 译作:进口、输入、引进、导入
export 译作:出口、输出、调出、导出
在python、scala语言中,经常看到import
关键字,但没有export
关键字。而export出现在了shell
这个脚本语言中。为什么?
个人理解,因为环境变量在Linux中大部分都存于配置文件中,要访问某个环境变量时,就需要将它导出、读出(export
)。从而Shell或Linux没有 import
一说了。
实例:
[root@master Cshell]# t1="t1_no_export"
[root@master Cshell]# export t2="t2_yes_export"
[root@master Cshell]# vim test_export.sh
#!/bin/bash
echo "TERM = $TERM"
export TERM
echo "TERM = $TERM"
echo "t1 = ${t1}"
echo "t2 = ${t2}"
[root@master Cshell]# sh test_export.sh
TERM = linux
TERM = linux
t1 =
t2 = t2_yes_export
[root@master Cshell]#
小结:
export
在子shell中运行的脚本中取不到数据(如t1
);而t2
这个【非环境变量】加了export
(在此变成了环境变量,不过未持久化),在子shell中运行的脚本中能取到它的数据。说明子进程(子shell)在继承父进程(父shell)时,“拷贝”了一份t2
给自己(子shell也可以修改它,不过父shell看不到修改),而t1
是父shell独有的。export
都无区别。还可参考【菜鸟教程:Linux export命令】