Shell脚本执行方式 #
一、执行方式概述 #
Shell脚本有多种执行方式,每种方式都有其特点和适用场景。
1.1 执行方式一览 #
| 方式 | 命令 | 权限 | Shell环境 |
|---|---|---|---|
| 直接执行 | ./script.sh | 需要执行权限 | 新子Shell |
| 指定解释器 | bash script.sh | 不需要 | 新子Shell |
| source执行 | source script.sh | 不需要 | 当前Shell |
| 点号执行 | . script.sh | 不需要 | 当前Shell |
| exec执行 | exec ./script.sh | 需要执行权限 | 替换当前Shell |
二、直接执行 #
2.1 基本用法 #
bash
# 赋予执行权限
chmod +x script.sh
# 直接执行
./script.sh
# 使用绝对路径
/home/user/scripts/script.sh
2.2 执行过程 #
text
当前Shell
↓
创建子Shell
↓
读取Shebang(#!/bin/bash)
↓
在子Shell中执行脚本
↓
子Shell退出,返回当前Shell
2.3 特点 #
bash
#!/bin/bash
# test.sh
var="子Shell中的变量"
echo "脚本中: var = $var"
执行结果:
bash
$ ./test.sh
脚本中: var = 子Shell中的变量
$ echo $var
# 空输出,变量不存在
特点说明:
- 脚本在子Shell中执行
- 脚本中的变量不会影响当前Shell
- 脚本修改的环境变量不会保留
- 脚本退出后,所有更改丢失
三、指定解释器执行 #
3.1 基本用法 #
bash
# 使用bash执行
bash script.sh
# 使用sh执行
sh script.sh
# 使用指定版本的bash
bash-4.4 script.sh
# 使用debug模式
bash -x script.sh
3.2 常用选项 #
bash
# -x: 显示执行的命令
bash -x script.sh
# -n: 只检查语法,不执行
bash -n script.sh
# -v: 显示脚本内容
bash -v script.sh
# -e: 遇到错误立即退出
bash -e script.sh
# 组合使用
bash -xve script.sh
3.3 特点 #
bash
# 不需要执行权限
$ ls -l script.sh
-rw-r--r-- 1 user user 100 Mar 27 10:00 script.sh
$ bash script.sh
# 可以正常执行
# Shebang会被忽略
$ cat script.sh
#!/bin/zsh
echo "Hello"
$ bash script.sh
Hello # 使用bash执行,而不是zsh
特点说明:
- 不需要执行权限
- 忽略Shebang指定的解释器
- 可以指定不同的Shell执行
- 方便调试和测试
四、source执行 #
4.1 基本用法 #
bash
# source命令执行
source script.sh
# 点号执行(等效)
. script.sh
4.2 执行过程 #
text
当前Shell
↓
在当前Shell中读取脚本
↓
逐行执行脚本命令
↓
执行完成,继续在当前Shell
4.3 特点演示 #
bash
#!/bin/bash
# config.sh
export APP_NAME="MyApp"
export APP_ENV="production"
alias ll='ls -alF'
执行结果:
bash
$ source config.sh
$ echo $APP_NAME
MyApp
$ echo $APP_ENV
production
$ ll
# alias生效
特点说明:
- 在当前Shell中执行
- 变量和函数会保留
- 环境变量会生效
- 别名会保留
- 适用于加载配置文件
4.4 常见应用场景 #
加载环境配置:
bash
# 加载Python虚拟环境
source venv/bin/activate
# 加载NVM
source ~/.nvm/nvm.sh
# 加载自定义配置
source ~/.bashrc
加载函数库:
bash
#!/bin/bash
# utils.sh
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
error() {
echo "[ERROR] $*" >&2
}
bash
# 在其他脚本中使用
source utils.sh
log "开始执行"
error "发生错误"
五、exec执行 #
5.1 基本用法 #
bash
# exec执行脚本
exec ./script.sh
# exec替换当前Shell
exec bash
5.2 执行过程 #
text
当前Shell (PID: 1000)
↓
exec执行脚本
↓
当前Shell被替换
↓
新进程 (PID: 1000) 执行脚本
↓
脚本结束,Shell退出
5.3 特点演示 #
bash
#!/bin/bash
# test_exec.sh
echo "当前PID: $$"
echo "脚本执行中..."
bash
$ echo $$
1000
$ exec ./test_exec.sh
当前PID: 1000
脚本执行中...
# 脚本执行完毕后,Shell退出
# 如果是终端,终端会关闭
5.4 应用场景 #
切换Shell:
bash
# 切换到zsh
exec zsh
# 切换到新版本的bash
exec /usr/local/bin/bash
脚本链式调用:
bash
#!/bin/bash
# main.sh
echo "准备切换到其他脚本..."
exec ./another.sh
echo "这行不会执行"
六、执行方式对比 #
6.1 变量作用域对比 #
创建测试脚本:
bash
#!/bin/bash
# var_test.sh
TEST_VAR="hello"
export EXPORT_VAR="world"
测试结果:
bash
# 方式一:直接执行
$ ./var_test.sh
$ echo $TEST_VAR
# 空
$ echo $EXPORT_VAR
# 空
# 方式二:source执行
$ source var_test.sh
$ echo $TEST_VAR
hello
$ echo $EXPORT_VAR
world
6.2 进程ID对比 #
bash
#!/bin/bash
# pid_test.sh
echo "脚本PID: $$"
echo "父进程PID: $PPID"
bash
$ echo $$
1000
$ ./pid_test.sh
脚本PID: 2000
父进程PID: 1000
$ source pid_test.sh
脚本PID: 1000
父进程PID: 999
6.3 退出状态对比 #
bash
#!/bin/bash
# exit_test.sh
exit 42
bash
$ ./exit_test.sh
$ echo $?
42
$ source exit_test.sh
$ echo $?
# 终端可能退出
七、选择执行方式 #
7.1 选择指南 #
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 运行独立脚本 | ./script.sh | 隔离环境,不影响当前Shell |
| 加载配置文件 | source script.sh | 需要保留变量和函数 |
| 调试脚本 | bash -x script.sh | 方便查看执行过程 |
| 检查语法 | bash -n script.sh | 不执行,只检查 |
| 切换Shell | exec bash | 替换当前Shell |
7.2 最佳实践 #
脚本开头添加检查:
bash
#!/bin/bash
# 检查是否被source执行
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
echo "此脚本应该被source执行"
echo "用法: source $0"
exit 1
fi
# 脚本内容
export MY_VAR="value"
脚本互斥执行:
bash
#!/bin/bash
# 确保脚本只能以特定方式执行
if [[ "${BASH_SOURCE[0]}" != "${0}" ]]; then
echo "错误: 此脚本不能被source执行"
return 1
fi
# 脚本内容
八、高级执行技巧 #
8.1 后台执行 #
bash
# 后台执行
./script.sh &
# 后台执行,忽略输出
./script.sh > /dev/null 2>&1 &
# nohup执行(退出终端不中断)
nohup ./script.sh > output.log 2>&1 &
8.2 定时执行 #
bash
# 使用at执行一次
echo "./script.sh" | at 10:00
# 使用cron定时执行
# 编辑crontab
crontab -e
# 添加定时任务
0 * * * * /home/user/script.sh
8.3 远程执行 #
bash
# SSH远程执行
ssh user@server './script.sh'
# SSH远程执行本地脚本
ssh user@server 'bash -s' < local_script.sh
# 执行并传递参数
ssh user@server 'bash -s' < local_script.sh arg1 arg2
8.4 并行执行 #
bash
#!/bin/bash
# 使用&和wait并行执行
task1() {
echo "任务1开始"
sleep 2
echo "任务1完成"
}
task2() {
echo "任务2开始"
sleep 2
echo "任务2完成"
}
task1 &
task2 &
wait
echo "所有任务完成"
九、总结 #
9.1 执行方式对比表 #
| 方式 | 命令 | 子Shell | 变量保留 | 典型用途 |
|---|---|---|---|---|
| 直接执行 | ./script.sh | 是 | 否 | 独立脚本 |
| 解释器执行 | bash script.sh | 是 | 否 | 调试脚本 |
| source | source script.sh | 否 | 是 | 加载配置 |
| 点号 | . script.sh | 否 | 是 | 加载配置 |
| exec | exec ./script.sh | 替换 | - | 切换Shell |
9.2 下一步 #
你已经掌握了Shell脚本的执行方式,接下来让我们学习 变量基础,深入了解Shell变量的使用!
最后更新:2026-03-27