执行shell脚本的各种方法小结

作者:

文章目录
  • 目录
    • 1. 基础执行方法
      • 方法1:使用解释器直接执行
      • 方法2:添加执行权限后执行
      • 方法3:使用source或点命令
    • 2. 各种执行方式的区别
      • 子shell执行 vs 当前shell执行
      • 执行方式对比表
    • 3. 带参数执行
      • 传递参数给脚本
      • 参数处理示例
    • 4. 调试模式执行
      • 各种调试选项
      • 脚本内调试设置
    • 5. 环境变量控制执行
      • 设置环境变量
      • 修改PATH后执行
    • 6. 输入输出重定向
      • 重定向标准输入输出
      • 使用here document
    • 7. 后台执行和作业控制
      • 后台执行脚本
      • 作业控制
    • 8. 定时执行和自动化
      • 使用cron定时执行
      • 使用at命令单次执行
    • 9. 条件执行和管道
      • 条件执行
      • 管道执行
    • 10. 安全执行方式
      • 安全执行最佳实践
      • 权限控制
    • 11. 高级执行技巧
      • 使用exec替换当前进程
      • 使用trap处理信号
      • 使用coproc协程
    • 12. 实用执行脚本示例
      • 批量执行脚本
      • 监控脚本执行
    • 13. 执行方式选择指南
      • 根据场景选择执行方式
      • 最佳实践总结

    # 添加执行权限
    chmod +x script.sh
    
    # 然后直接执行
    ./script.sh
    
    # 或者使用绝对路径
    /home/user/script.sh
    /path/to/script.sh
    

    # 在当前shell环境中执行
    source script.sh
    
    # 简写形式(功能相同)
    . script.sh
    

    #!/bin/bash
    # demo.sh
    export MY_VAR="子shell变量"
    echo "MY_VAR: $MY_VAR"
    
    # 测试不同执行方式
    echo "=== 方法1: bash script.sh ==="
    bash demo.sh
    echo "执行后MY_VAR: $MY_VAR"  # 空值(变量在子shell中)
    
    echo "=== 方法2: ./script.sh ==="
    chmod +x demo.sh
    ./demo.sh
    echo "执行后MY_VAR: $MY_VAR"  # 空值(变量在子shell中)
    
    echo "=== 方法3: source script.sh ==="
    source demo.sh
    echo "执行后MY_VAR: $MY_VAR"  # 有值(变量在当前shell)
    

    执行方式 是否需要执行权限 是否创建子shell 变量是否保持 退出状态
    bash script.sh ❌ 不需要 ✅ 是 ❌ 不保持 脚本最后命令
    ./script.sh ✅ 需要 ✅ 是 ❌ 不保持 脚本最后命令
    source script.sh ❌ 不需要 ❌ 否 ✅ 保持 脚本最后命令
    . script.sh ❌ 不需要 ❌ 否 ✅ 保持 脚本最后命令

    #!/bin/bash
    # script_with_args.sh
    
    echo "脚本名称: $0"
    echo "参数个数: $#"
    echo "所有参数: $@"
    
    for i in $(seq 1 $#); do
        echo "参数 $i: ${!i}"
    done
    
    # 执行带参数的脚本
    bash script_with_args.sh arg1 arg2 "arg3 with spaces"
    
    ./script_with_args.sh apple banana cherry
    
    source script_with_args.sh 参数1 参数2
    

    #!/bin/bash
    # process_args.sh
    
    # 处理选项参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -f|--file)
                FILE="$2"
                shift 2
                ;;
            -h|--help)
                echo "用法: $0 [-v] [-f FILE]"
                exit 0
                ;;
            *)
                echo "未知参数: $1"
                exit 1
                ;;
        esac
    done
    
    echo "详细模式: ${VERBOSE:-false}"
    echo "文件: ${FILE:-未指定}"
    

    # 显示执行的每一行命令
    bash -x script.sh
    
    # 显示变量赋值
    bash -v script.sh
    
    # 组合调试
    bash -xv script.sh
    
    # 检查语法而不执行
    bash -n script.sh
    
    # 从指定行开始执行
    bash -x --debugger script.sh
    

    #!/bin/bash
    # debug_demo.sh
    
    # 开启调试
    set -x
    echo "这一行会被显示"
    name="Debug Test"
    echo "名字: $name"
    
    # 关闭调试
    set +x
    echo "这一行不会被显示"
    
    # 只调试部分代码
    (
        set -x
        echo "这部分代码会调试"
        date
        set +x
    )
    
    echo "调试结束"
    

    # 临时设置环境变量
    MY_VAR="value" bash script.sh
    
    # 设置多个环境变量
    DEBUG=true LOG_LEVEL=info bash script.sh
    
    # 清空环境变量执行
    env -i bash script.sh  # 空环境执行
    

    # 添加自定义路径到PATH
    PATH="/my/custom/bin:$PATH" ./script.sh
    
    # 使用完整路径避免PATH依赖
    /bin/bash /path/to/script.sh
    

    # 输出重定向到文件
    bash script.sh > output.txt
    bash script.sh >> output.txt  # 追加模式
    
    # 错误输出重定向
    bash script.sh 2> error.log
    bash script.sh > output.txt 2>&1  # 合并输出和错误
    bash script.sh &> all_output.txt  # 合并输出(bash 4.0+)
    
    # 输入重定向
    bash script.sh < input.txt
    echo "input data" | bash script.sh
    

    # 直接传递输入数据
    bash script.sh << EOF
    第一行输入
    第二行输入
    第三行输入
    EOF
    
    # 带变量替换的here document
    name="John"
    age=25
    bash script.sh << EOD
    姓名: $name
    年龄: $age
    时间: $(date)
    EOD
    

    # 后台执行
    bash long_running_script.sh &
    
    # 后台执行并忽略挂起信号
    nohup bash script.sh &
    
    # 后台执行并重定向输出
    nohup bash script.sh > output.log 2>&1 &
    
    # 使用screen/tmux保持会话
    screen -dm bash script.sh
    tmux new-session -d bash script.sh
    

    # 启动后台作业
    bash script.sh &
    jobs  # 查看后台作业
    
    # 将后台作业调到前台
    fg %1
    
    # 暂停当前作业
    Ctrl+Z
    bg %1  # 在后台继续运行
    
    # 杀死作业
    kill %1
    

    # 编辑crontab
    crontab -e
    
    # 添加定时任务示例
    # 每分钟执行
    * * * * * /path/to/script.sh
    
    # 每天凌晨2点执行
    0 2 * * * /path/to/script.sh
    
    # 每周一上午9点执行
    0 9 * * 1 /path/to/script.sh
    
    # 每月1号执行
    0 0 1 * * /path/to/script.sh
    

    # 10分钟后执行
    echo "/path/to/script.sh" | at now + 10 minutes
    
    # 明天上午9点执行
    at 09:00 tomorrow <<< "/path/to/script.sh"
    
    # 查看等待的at任务
    atq
    
    # 删除at任务
    atrm 任务编号
    

    # 只有前一个命令成功才执行
    bash script1.sh && bash script2.sh
    
    # 只有前一个命令失败才执行
    bash script1.sh || bash script2.sh
    
    # 复杂条件组合
    bash script1.sh && echo "成功" || echo "失败"
    

    # 脚本输出作为另一个脚本的输入
    bash generator.sh | bash processor.sh
    
    # 多个脚本管道连接
    bash script1.sh | bash script2.sh | bash script3.sh
    
    # 使用tee同时输出到屏幕和文件
    bash script.sh | tee output.log
    

    # 使用完整路径避免PATH劫持
    /bin/bash /path/to/script.sh
    
    # 使用sudo以特定用户执行
    sudo -u username bash script.sh
    sudo -u www-data bash script.sh
    
    # 在受限环境中执行
    bash --restricted script.sh  # 受限模式
    bash --norc script.sh        # 不读取rc文件
    

    # 设置适当的文件权限
    chmod 755 script.sh        # 所有者可读写执行,其他用户可读执行
    chmod 700 script.sh        # 只有所有者可读写执行
    
    # 设置setuid权限(谨慎使用)
    chmod u+s script.sh        # 以文件所有者身份执行
    
    # 使用acl进行精细控制
    setfacl -m u:username:rx script.sh
    

    #!/bin/bash
    # exec_demo.sh
    
    echo "准备执行exec..."
    exec bash -c 'echo "这是exec执行的命令"; sleep 2'
    echo "这行不会执行"  # 因为exec替换了当前进程
    

    #!/bin/bash
    # trap_demo.sh
    
    cleanup() {
        echo "收到信号,正在清理..."
        exit 1
    }
    
    # 设置信号处理
    trap cleanup SIGINT SIGTERM
    
    echo "脚本运行中,按Ctrl+C测试信号处理"
    sleep 10
    echo "正常结束"
    

    #!/bin/bash
    # coproc_demo.sh
    
    # 创建协程
    coproc MY_COPROC {
        while read line; do
            echo "处理: $line"
        done
    }
    
    # 向协程发送数据
    echo "数据1" >&${MY_COPROC[1]}
    echo "数据2" >&${MY_COPROC[1]}
    
    # 从协程读取数据
    read -u ${MY_COPROC[0]} result
    echo "结果: $result"
    

    #!/bin/bash
    # batch_executor.sh
    
    SCRIPT_DIR="/path/to/scripts"
    LOG_DIR="/path/to/logs"
    
    # 确保日志目录存在
    mkdir -p "$LOG_DIR"
    
    # 批量执行所有.sh脚本
    for script in "$SCRIPT_DIR"/*.sh; do
        if [[ -x "$script" ]]; then
            script_name=$(basename "$script")
            log_file="$LOG_DIR/${script_name}.log"
            
            echo "执行: $script_name"
            bash "$script" > "$log_file" 2>&1
            
            if [[ $? -eq 0 ]]; then
                echo "✓ $script_name 执行成功"
            else
                echo "✗ $script_name 执行失败"
            fi
        fi
    done
    

    #!/bin/bash
    # script_monitor.sh
    
    SCRIPT="$1"
    TIMEOUT=300  # 5分钟超时
    
    if [[ ! -f "$SCRIPT" ]]; then
        echo "错误: 脚本不存在: $SCRIPT"
        exit 1
    fi
    
    # 带超时执行
    timeout $TIMEOUT bash "$SCRIPT"
    
    case $? in
        0)
            echo "脚本执行成功"
            ;;
        124)
            echo "脚本执行超时(超过 ${TIMEOUT}秒)"
            ;;
        *)
            echo "脚本执行失败,退出码: $?"
            ;;
    esac
    

    使用场景 推荐执行方式 理由
    临时测试 bash script.sh 简单快捷,无需权限
    生产环境 ./script.sh 正式规范,权限明确
    配置加载 source config.sh 变量在当前shell生效
    调试排错 bash -x script.sh 显示执行过程
    定时任务 crontab 自动化调度
    后台服务 nohup script.sh & 持久化运行
    管道处理 `script1.sh script2.sh`
    安全执行 完整路径执行 避免路径劫持

    # 1. 生产环境使用完整路径
    /bin/bash /opt/scripts/myscript.sh
    
    # 2. 设置适当的执行权限
    chmod 750 /opt/scripts/myscript.sh
    
    # 3. 使用日志记录
    /bin/bash /opt/scripts/myscript.sh >> /var/log/myscript.log 2>&1
    
    # 4. 错误处理
    /bin/bash /opt/scripts/myscript.sh || echo "执行失败" | mail -s "脚本错误" admin@company.com
    
    # 5. 资源限制
    timeout 3600 /bin/bash /opt/scripts/myscript.sh
    

    这个完整的指南涵盖了Shell脚本执行的所有主要方法,从基础到高级技巧都有详细说明。根据具体需求选择合适的执行方式非常重要

    到此这篇关于执行shell脚本的各种方法小结的文章就介绍到这了,更多相关执行shell脚本内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

    您可能感兴趣的文章:

    • shell脚本中一些特殊符号
    • shell脚本中常见的一些特殊符号和作用详解
    • Shell脚本中$符号的几种用法小结
    • shell查找符号链接及其指向目标的方法介绍
    • 详解Shell 脚本中 “$” 符号的多种用法
    • shell脚本中$符号的命令使用汇总
    • 浅析shell脚本知识之符号篇
    • Shell脚本中$符号的嵌套使用方法小结

    站内搜索