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