Shell是用户与操作系统内核之间的接口程序,提供命令行交互和脚本编程能力。Linux默认Shell是Bash(Bourne Again Shell)。
| Shell | 路径 | 特点 |
|---|---|---|
| sh | /bin/sh | POSIX标准Shell,通常指向dash |
| Bash | /bin/bash | 最常用,Linux默认,功能丰富 |
| Zsh | /bin/zsh | 最强大,macOS默认,插件生态好 |
| Dash | /bin/dash | 轻量快速,Debian脚本默认 |
| Fish | /usr/bin/fish | 用户友好,自动补全,不POSIX兼容 |
$ bash --version | head -1
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
#!/bin/bash
# hello.sh - 第一个Shell脚本
echo "Hello, World!"
echo "当前用户: $(whoami)"
echo "当前目录: $(pwd)"
echo "系统时间: $(date)"
echo "内核版本: $(uname -r)"
echo "Shell版本: $BASH_VERSION"
# 方式1:作为可执行程序(需要执行权限和shebang)
chmod +x hello.sh
./hello.sh
# 方式2:通过bash解释器执行(不需要执行权限)
bash hello.sh
# 方式3:source在当前Shell执行(影响当前环境)
source hello.sh
. hello.sh # 等效写法
| 方式 | 子Shell | 需执行权限 | 影响当前Shell | 用途 |
|---|---|---|---|---|
| ./script | 是 | 是 | 否 | 常规执行 |
| bash script | 是 | 否 | 否 | 调试/无权限时 |
| source script | 否 | 否 | 是 | 加载函数/环境变量 |
#!/bin/bash # 使用bash执行
#!/bin/sh # 使用POSIX sh执行
#!/usr/bin/env bash # 更可移植,通过env查找bash
#!/usr/bin/env python3 # Python脚本
# 赋值(等号两边不能有空格!)
NAME="Linux"
VERSION=7
PATH_DIR="/var/log"
# 使用变量
echo $NAME # Linux
echo "$NAME version $VERSION" # Linux version 7
echo "${NAME}_VERSION" # Linux_VERSION(花括号消除歧义)
# 只读变量
readonly PI=3.14159
# PI=3 # 报错:readonly variable
# 删除变量
unset NAME
NAME="World"
# 双引号:变量展开,允许转义
echo "Hello, $NAME" # Hello, World
echo "Hello, \$NAME" # Hello, $NAME(转义$)
echo "Path: $PATH" # 变量展开
# 单引号:原样输出,不做任何展开
echo 'Hello, $NAME' # Hello, $NAME
echo 'Path: $PATH' # Path: $PATH
# 反引号/$():命令替换
echo "Today: $(date +%F)" # Today: 2024-01-15(推荐)
echo "Files: `ls | wc -l`" # 旧语法,不推荐
| 变量 | 含义 | 示例 |
|---|---|---|
| $0 | 脚本文件名 | ./script.sh |
| $1-$9 | 位置参数 | 第一个到第九个参数 |
| ${10} | 第10个参数 | 需要花括号 |
| $# | 参数个数 | 3 |
| $@ | 所有参数(独立字符串) | "a" "b" "c" |
| $* | 所有参数(单个字符串) | "a b c" |
| $? | 上一命令退出码 | 0(成功)/1(失败) |
| $$ | 当前脚本PID | 12345 |
| $! | 最近后台进程PID | 12346 |
# echo
echo "Hello" # 输出后换行
echo -n "Hello" # 不换行
echo -e "Line1\nLine2" # 解释转义字符
# printf(更灵活,推荐用于格式化输出)
printf "Name: %s\n" "Linux"
printf "Number: %d\n" 42
printf "Float: %.2f\n" 3.14159
printf "%-10s %5d\n" "Item" 100 # 左对齐10字符,右对齐5数字
# 基本读取
echo -n "请输入姓名: "
read NAME
echo "你好, $NAME!"
# 带提示的读取(一行写法)
read -p "请输入年龄: " AGE
# 密码输入(不回显)
read -s -p "密码: " PASSWORD
# 限制时间
read -t 10 -p "10秒内输入: " INPUT
# 读取多个值
read -p "姓名 年龄: " NAME AGE
# 标准输出重定向
command > file # 覆盖写入
command >> file # 追加写入
# 标准错误重定向
command 2> error.log # 错误到文件
command 2>> error.log # 错误追加
# 合并输出
command > all.log 2>&1 # 标准输出和错误都到文件
command &> all.log # 等效简写(Bash 4+)
# 丢弃输出
command > /dev/null 2>&1
# 输入重定向
command < input.txt
# Here Document
cat << EOF
这是多行文本
变量展开: $NAME
EOF
# Here String
grep "pattern" <<< "search in this string"
# 算术展开 $(( ))
echo $((1 + 2)) # 3
echo $((10 - 3)) # 7
echo $((4 * 5)) # 20
echo $((10 / 3)) # 3 (整数除法)
echo $((10 % 3)) # 1 (取余)
echo $((2 ** 10)) # 1024 (幂运算)
# let命令
let x=1+2; echo $x # 3
let x++; echo $x # 4 (自增)
let x+=5; echo $x # 9 (加赋值)
# expr命令(不推荐,速度慢)
expr 1 + 2 # 3
# bc浮点运算
echo "scale=2; 10/3" | bc # 3.33
echo "sqrt(2)" | bc -l # 1.41421356...
# 常用环境变量
echo $HOME # /root (家目录)
echo $USER # root (当前用户)
echo $PATH # 命令搜索路径
echo $PWD # 当前目录
echo $SHELL # /bin/bash
echo $HOSTNAME # 主机名
echo $LANG # 语言设置
echo $RANDOM # 随机数(0-32767)
# 设置环境变量
export MY_VAR="hello" # 当前会话
echo 'export MY_VAR="hello"' >> ~/.bashrc # 永久生效
source ~/.bashrc # 立即生效
# Bash调试选项
bash -n script.sh # 仅检查语法(不执行)
bash -x script.sh # 执行追踪(打印每条命令及其参数)
bash -v script.sh # 详细模式(打印读入的每一行)
# 脚本内启用/关闭调试
set -x # 开启追踪
# ... 需要调试的代码 ...
set +x # 关闭追踪
# 安全模式(推荐所有脚本使用)
set -euo pipefail
# -e: 命令失败时立即退出
# -u: 使用未定义变量时报错
# -o pipefail: 管道中任一命令失败则整个管道失败
# 错误捕获
trap 'echo "Error at line $LINENO"; exit 1' ERR
#!/bin/bash
# 描述: Shell脚本模板
# 作者: admin
# 日期: $(date +%Y-%m-%d)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="/tmp/$(basename "$0" .sh).log"
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $*" | tee -a "$LOG_FILE"; }
die() { log "FATAL: $*" >&2; exit 1; }
usage() {
echo "Usage: $(basename "$0") [OPTIONS]"
echo " -h 显示帮助"
echo " -v 详细输出"
echo " -f FILE 指定文件"
}
CONFIG_FILE=""
while getopts "hvf:" opt; do
case $opt in
h) usage; exit 0 ;;
v) set -x ;;
f) CONFIG_FILE="$OPTARG" ;;
*) usage; exit 1 ;;
esac
done
main() {
log "脚本开始执行"
# 在此添加业务逻辑
log "脚本执行完成"
}
main "$@"
#!/bin/bash
# sysinfo.sh
echo "===== 系统信息报告 ====="
echo "主机名: $(hostname)"
echo "内核: $(uname -r)"
echo "架构: $(uname -m)"
echo "CPU: $(nproc)核"
echo "内存: $(free -h | grep Mem | awk '{print $2}')"
echo "磁盘使用:"
df -h | grep -v tmpfs | grep -v udev
echo "IP: $(hostname -I | awk '{print $1}')"
echo "运行时间: $(uptime -p)"
echo "登录用户: $(who | wc -l)"✅ 理解Shell种类与特性
✅ 掌握脚本基本结构
✅ 学会变量、引号、重定向
✅ 掌握特殊变量与参数
✅ 学会脚本调试技巧
#!/bin/bash
# 最佳实践模板
set -euo pipefail
# 参数校验
if [[ $# -lt 1 ]]; then
echo "用法: $0 <必需参数> [可选参数]" >&2
exit 1
fi
# 清理
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
# 日志
log() { echo "[$(date +%T)] $*"; }
err() { log "ERROR: $*" >&2; exit 1; }
# 主逻辑
main() {
local input="$1"
log "处理: $input"
# ...
log "完成"
}
main "$@"
# 避免不必要的子Shell
# 慢: for f in $(ls); do ...
# 快: for f in *; do ...
# 使用内置命令而非外部命令
# 慢: expr 1 + 2
# 快: echo $((1 + 2))
# 慢: cat file | grep pattern
# 快: grep pattern file
# 使用 Bash 内置字符串操作
# 慢: echo "$var" | sed 's/old/new/'
# 快: echo "${var/old/new}"
# 慢: basename /path/to/file
# 快: echo "${path##*/}"
# 慢: dirname /path/to/file
# 快: echo "${path%/*}"
| 书名 | 作者 | 重点 |
|---|---|---|
| Linux命令行与Shell脚本编程大全 | Blum | Shell脚本全面覆盖 |
| UNIX/Linux系统管理技术手册 | Nemeth | 系统管理圣经 |
| Ansible: Up and Running | Lintner | Ansible实战 |
| 鸟哥的Linux私房菜 | 鸟哥 | 中文经典入门 |
| 认证 | 机构 | 级别 |
|---|---|---|
| LFCS | Linux Foundation | 基础系统管理 |
| LFCE | Linux Foundation | 高级系统工程师 |
| RHCSA | Red Hat | Red Hat管理员 |
| RHCE | Red Hat | Red Hat工程师 |
| CKA/CKAD | CNCF | Kubernetes管理员/开发者 |
# 文本处理速查
grep -E 'pattern' file # 扩展正则搜索
sed -i 's/old/new/g' file # 替换
awk '{print $1}' file # 提取列
sort | uniq -c | sort -rn # 频次统计
cut -d: -f1 file # 切列
tr 'A-Z' 'a-z' # 转小写
# 系统管理速查
systemctl status/start/stop/restart service
journalctl -u service -f # 跟踪日志
df -h / du -sh * # 磁盘使用
ps aux --sort=-%mem # 内存排序
ss -tlnp # 监听端口
iptables -L -n # 防火墙规则
crontab -e # 编辑定时任务
useradd -m -s /bin/bash user # 创建用户
# 网络诊断速查
ip addr / ip route # 网络配置
ping / traceroute # 连通测试
dig / nslookup # DNS查询
curl -I url # HTTP头检查
nc -zv host port # 端口测试
tcpdump -i eth0 port 80 # 抓包