Linux中带或不带export定义变量的区别
Linux中带或不带export定义变量的区别
技术背景
在Linux系统的Bash等shell环境中,变量的定义和使用是日常操作的基础。变量可以用来存储各种信息,如路径、配置参数等。而export
是一个重要的命令,它与变量的作用域密切相关,影响着变量在不同进程间的可见性。理解带或不带export
定义变量的区别,对于编写高效、正确的shell脚本以及进行系统配置至关重要。
实现步骤
不带export定义变量
使用name=value
的形式定义变量,这种变量的作用域通常局限于当前shell。例如:
1 |
|
此时,bar
变量仅在当前shell中有效,如果在子进程(如另一个bash进程)中尝试访问该变量,将无法获取到其值。
带export定义变量
使用export name=value
的形式定义变量,这样可以将变量导出到环境中,使其在子进程中也可以被访问。例如:
1 |
|
在上述示例中,由于foo
变量被导出,所以在新启动的bash子进程中也能正确打印出其值。
核心代码
以下是一些代码示例,用于进一步说明两者的区别:
普通变量作用域示例
1 |
|
运行上述代码,子进程中打印的A
值为空,因为A
没有被导出,子进程无法访问。
导出变量示例
1 |
|
运行上述代码,子进程中可以正确打印出B
的值为Bob
,因为B
被导出到了环境中。
临时设置变量给命令使用示例
1 |
|
在上述示例中,MY_VAR
仅在node my-script.js
这个命令执行期间有效,并且会传递给node
进程。
最佳实践
- 使用场景区分:对于临时变量、循环变量等仅在当前shell中使用的变量,使用
name=value
的形式定义;对于需要在子进程中使用的变量,使用export name=value
的形式定义。 - 避免重复导出:通常操作系统已经将一些重要的环境变量(如
PATH
)导出,不需要重复导出。例如:
1 |
|
- 检查变量是否导出:可以使用
env
命令查看当前环境中的变量,已导出的变量会显示在env
的输出中。
常见问题
子进程修改变量值对父进程的影响
子进程对变量的修改不会影响父进程中的变量值。例如:
1 |
|
运行上述代码,父进程中打印的B
值仍然是Bob
,因为子进程对B
的修改不会传递回父进程。
提前导出未赋值变量
如果提前使用export
导出一个未赋值的变量,后续给该变量赋值后,子进程可以看到赋值后的变量值,但在赋值前子进程看到的是一个空值。例如:
1 |
|
临时赋值给shell函数的问题
在POSIX标准中,VAR=VAL shell_func
这种临时设置和导出环境变量给shell函数的行为是未定义的。不同的shell可能有不同的实现,有些shell可能不会正确导出变量。例如,在dash 0.5.10.2 - 6(Ubuntu 20.04)、FreeBSD 13的/bin/sh
和AT&T ksh中,这种写法可能只会进行临时赋值而不会导出变量。建议使用以下方式:
1 |
|
需要注意的是,使用子shell进行导出时,func
对当前shell变量的修改会在子shell边界丢失。