5.1.1 Shell环境与执行方式
Shell环境概述#
Shell 是用户与内核交互的命令解释器,常见实现包括 Bash、Zsh、Dash。不同 Shell 在语法与内建命令上存在差异,运维脚本通常以 Bash 为主。
常见 Shell 类型与识别#
- 查看当前登录 Shell(用户默认):
echo $SHELL - 查看当前运行中的 Shell:
ps -p $$ - 常见路径:
/bin/bash、/bin/sh、/bin/zsh /bin/sh可能指向dash或bash,需注意兼容性
命令示例与说明:
echo $SHELL # 输出用户默认登录Shell
ps -p $$ -o comm= # 输出当前进程对应的Shell名称
ls -l /bin/sh # 查看 /bin/sh 实际指向
预期效果:
- echo $SHELL 输出如 /bin/bash
- ls -l /bin/sh 输出如 -> dash 或 -> bash
Shell 启动方式#
- 登录 Shell:读取
/etc/profile、~/.bash_profile、~/.bash_login或~/.profile - 非登录交互 Shell:读取
~/.bashrc - 非交互 Shell(脚本):默认不读取上述文件,可用
source或.显式加载
示例:验证不同启动方式加载配置
# 1) 在 ~/.bashrc 中加入标记
echo 'echo "Loaded .bashrc"' >> ~/.bashrc
# 2) 开一个新的非登录交互shell
bash
# 预期输出:Loaded .bashrc
# 3) 退出后执行非交互脚本
cat > /tmp/test.sh <<'EOF'
#!/bin/bash
echo "RUN SCRIPT"
EOF
bash /tmp/test.sh
# 预期输出:RUN SCRIPT(不会显示 Loaded .bashrc)
脚本执行方式#
- 显式调用解释器:
bash script.sh,不依赖执行权限 - 直接执行:
./script.sh,需可执行权限与正确的 shebang - source 执行:
source script.sh或. script.sh,在当前 Shell 中执行并保留变量
示例:三种方式对变量影响
cat > /tmp/envdemo.sh <<'EOF'
#!/bin/bash
export FOO="from_script"
BAR="local_only"
echo "FOO=$FOO BAR=$BAR"
EOF
# 1) 显式调用
bash /tmp/envdemo.sh
echo "FOO=$FOO BAR=$BAR" # 预期:FOO= BAR=
# 2) 直接执行
chmod +x /tmp/envdemo.sh
/tmp/envdemo.sh
echo "FOO=$FOO BAR=$BAR" # 预期:FOO= BAR=
# 3) source 执行
source /tmp/envdemo.sh
echo "FOO=$FOO BAR=$BAR" # 预期:FOO=from_script BAR=local_only
Shebang 与执行环境#
- Shebang 位于脚本首行:
#!/bin/bash - 指定解释器路径,决定脚本语法与内建命令
- 推荐使用:
#!/usr/bin/env bash以适配多路径环境
示例:不同 shebang 的可移植性
cat > /tmp/hello.sh <<'EOF'
#!/usr/bin/env bash
echo "Hello from $(command -v bash)"
EOF
chmod +x /tmp/hello.sh
/tmp/hello.sh
命令解释:
- command -v bash:输出 bash 的实际路径
- #!/usr/bin/env bash:通过环境变量查找 bash,适配不同系统路径
执行环境与变量作用域#
- 子进程执行脚本时,变量需
export才能传递 source执行不会开启子进程,可直接影响当前环境- 脚本中设置的
PATH只在当前进程有效
示例:export 的作用
cat > /tmp/varscope.sh <<'EOF'
#!/bin/bash
echo "IN SCRIPT: FOO=$FOO"
EOF
FOO="local"
bash /tmp/varscope.sh # 预期:IN SCRIPT: FOO=
export FOO="exported"
bash /tmp/varscope.sh # 预期:IN SCRIPT: FOO=exported
执行权限与安全注意#
- 赋予权限:
chmod +x script.sh - 控制可写权限,避免脚本被篡改
- 避免在脚本中硬编码敏感信息,必要时使用环境变量或外部配置
权限与安全示例:
# 仅所有者可读写执行
chmod 700 /usr/local/bin/backup.sh
ls -l /usr/local/bin/backup.sh
预期效果:
- 权限显示为 -rwx------,减少被非授权用户修改的风险
安装与依赖检查(Bash)#
多数发行版默认安装 Bash,可通过包管理器确认:
# Debian/Ubuntu
dpkg -l | grep -E '^ii bash'
# CentOS/RHEL
rpm -qa | grep '^bash-'
排错与常见问题#
1) 报错:/bin/bash^M: bad interpreter
- 原因:脚本为 Windows 换行
- 解决:
sed -i 's/\r$//' /path/script.sh
2) 报错:permission denied
- 原因:未赋执行权限
- 解决:
chmod +x /path/script.sh
3) 报错:command not found
- 原因:PATH 不包含命令路径或使用了 sh 运行 bash 特性
- 解决:
which yourcmd
export PATH=$PATH:/usr/local/bin
bash /path/script.sh
实战建议#
- 统一使用 Bash 并在脚本首行声明
- 明确脚本执行方式,避免环境差异导致的兼容问题
- 脚本顶部视需要启用严格模式:
set -euo pipefail
示例:严格模式模板
cat > /tmp/template.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
echo "脚本启动..."
EOF
chmod +x /tmp/template.sh
练习#
1) 编写脚本 envcheck.sh 输出当前 Shell、/bin/sh 指向,并展示 $PATH 的前 3 项。
2) 使用 source 运行脚本,观察变量在当前 Shell 中是否保留。
3) 故意将脚本改为 CRLF 行尾并修复。