Ubuntu shell 脚本执行
ubuntu 执行脚本命令 使用bash xxx.sh 和直接 . xxx.sh运行脚本两种方式有什么区别
在 Ubuntu(以及其他 Linux/Unix 系统)中,使用 bash xxx.sh 和 . xxx.sh(即 source xxx.sh)运行脚本有本质的区别。
主要的区别在于 脚本运行的上下文环境 以及 对当前 Shell 的影响。
核心区别对比表
| 特性 | bash xxx.sh | . xxx.sh (或 source xxx.sh) |
|---|---|---|
| 执行环境 | 启动一个新的子 Shell (Subshell) | 在当前 Shell 进程中执行 |
| 环境变量 | 脚本内的变量修改仅在子 Shell 有效,脚本结束即失效 | 脚本定义的变量/函数会保留在当前 Shell 中 |
| 目录切换 | 脚本内的 cd 命令只影响子 Shell | 脚本内的 cd 命令会改变当前 Shell 的路径 |
| 进程 ID ($$) | 脚本运行时拥有一个新的 PID | PID 与当前 Shell 相同 |
| 权限要求 | 需要读取权限 (Read) | 需要读取权限 (Read) |
| 主要用途 | 执行一次性任务,避免污染当前环境 | 加载配置文件、环境变量、函数库 |
详细解析
1. bash xxx.sh (子 Shell 执行)
当你运行 bash xxx.sh 时,系统会启动一个新的 bash 进程(子 Shell)来读取并执行脚本中的命令。
- 隔离性:脚本中定义的变量、别名或函数在脚本执行完毕后会随子 Shell 一起销毁,不会 影响你当前的终端环境。
- 目录切换:如果脚本里写了
cd /tmp,只有那个子 Shell 会进入/tmp。脚本执行完后,你当前的终端依然停留在原来的目录下。 - 适用场景:绝大多数应用程序脚本、安装脚本、数据处理脚本。
2. . xxx.sh (当前 Shell 执行 / Source)
. 命令(点命令)是 source 命令的简写。当你运行 . xxx.sh 时,脚本中的命令是直接在 当前 的 Shell 进程中逐行执行的,就像是你手动把脚本里的每一行命令敲进终端一样。
- 持久性:脚本中定义的变量、导出的环境变量(
export)、函数都会直接加载到你当前的 Shell 中,并一直保留直到你关闭终端。 - 目录切换:如果脚本里执行了
cd /var/log,脚本运行完后,你会发现你的终端提示符已经变到了/var/log目录下。 - 适用场景:
- 加载配置文件(如
~/.bashrc或~/.bash_profile)。 - 激活虚拟环境(如 Python 的
source venv/bin/activate)。 - 导入常用的函数库供当前会话使用。
- 加载配置文件(如
举例说明
假设有一个脚本 test.sh,内容如下:
#!/bin/bash
cd /tmp
my_var="Hello World"
echo "Inside script: PID = \$$"
(1) 使用 bash test.sh 运行:
$ echo "Current PID = \$$"
Current PID = 1234
$ bash test.sh
Inside script: PID = 5678 <-- PID 不同,是子进程
$ echo $my_var
<-- 为空,变量没带出来
$ pwd
/home/user <-- 目录没变
(2) 使用 . test.sh 运行:
$ echo "Current PID = \$$"
Current PID = 1234
$ . test.sh
Inside script: PID = 1234 <-- PID 相同,是同一进程
$ echo $my_var
Hello World <-- 变量被保留了
$ pwd
/tmp <-- 目录被改变了
总结
- 如果你只是想运行一个程序,并且不希望它弄乱你的环境变量或当前目录,请使用
bash xxx.sh(或者给脚本+x权限后直接./xxx.sh)。 - 如果你想加载配置或者让脚本改变当前 Shell 的状态(例如设置环境变量),请使用
. xxx.sh。