Shell 基础知识
- Shell:用户与系统内核之间的命令解释器。
- 查看当前 Shell :
echo $SHELL或echo $0 - 脚本第一行 :
#!/bin/bash(指定解释器) - 执行脚本 :
bash script.sh(新子进程)./script.sh(需chmod +x)source script.sh/. script.sh(当前 Shell 执行,可修改环境变量)
- 脚本调试 :
- 语法检查:
bash -n script.sh - 跟踪执行:
bash -x script.sh - 安全选项:
set -euo pipefail(遇错即停、未定义变量报错、管道命令失败也报错)
- 语法检查:
文件与目录操作
| 命令 | 说明 |
|---|---|
ls -lh |
详细信息,人类可读的大小 |
cd - |
回到上一次目录 |
pwd |
打印当前完整路径 |
mkdir -p a/b/c |
递归创建目录 |
touch file |
新建空文件,或更新文件时间戳 |
cp -r src dst |
递归复制 |
mv old new |
移动/重命名 |
rm -rf dir |
危险 强制递归删除 |
find . -name "*.log" -mtime +7 -exec rm {} \; |
查找并删除7天前的日志 |
ln -s target linkname |
创建软链接 |
stat file |
查看文件详细属性 |
查看文件内容
bash
head -n 20 file # 前20行
tail -n 20 file # 后20行
tail -f /var/log/syslog # 实时跟踪
less file # 分页浏览,/搜索,q退出
wc -l file # 统计行数
权限管理
bash
chmod 755 file # rwxr-xr-x
chmod u+x script.sh # 属主增加执行权限
chown user:group file
chgrp group file
数字计算:r=4, w=2, x=1
例:rwxr-x--- = 750
压缩与归档
bash
tar -czvf archive.tar.gz dir/ # 打包为 tar.gz
tar -xzvf archive.tar.gz # 解压 tar.gz
tar -cjvf archive.tar.bz2 dir/ # 打包为 tar.bz2
tar -xjvf archive.tar.bz2
zip -r file.zip dir/ # 压缩为 zip
unzip file.zip
gzip file # 生成 file.gz
gunzip file.gz
网络与传输
bash
curl -O http://example.com/file # 下载并保存
curl -I http://example.com # 显示响应头
wget http://example.com/file
ping -c 4 google.com
netstat -tulnp | grep :80 # 查看端口占用
ss -tulnp # 更现代的 netstat
进程与任务
bash
ps aux | grep nginx
top # 实时监控,按 q 退出
htop # 需安装,更好看
kill -9 PID # 强制终止
pkill -f pattern # 按名称模式终止
& # 命令后加 & 后台运行
jobs # 列出当前 Shell 后台任务
fg %1 # 将后台任务 1 拉到前台
bg %1 # 让暂停的任务在后台继续
nohup long_cmd & # 关闭终端后仍运行,输出默认到 nohup.out
变量与环境变量
bash
name="Linux" # 赋值等号两边不加空格
echo "Hello, $name" # 双引号解析变量
echo 'Hello, $name' # 单引号原样输出
echo "PATH is ${PATH}" # 用大括号界定变量边界
# 环境变量
export MY_VAR="value" # 使子进程可见
echo $HOME $USER $PWD $? # $? 上条命令退出码(0 成功)
# 只读变量
readonly PI=3.14
# 命令结果赋值
now=$(date) # 推荐使用 $()
files_count=$(ls | wc -l)
特殊变量

| 变量 | 含义 |
|---|---|
$0 |
脚本名 |
$1, $2... |
第1、第2...个参数 |
$# |
参数个数 |
$@ |
所有参数(每个为独立字符串) |
$* |
所有参数(合并成一个字符串) |
$? |
上一条命令的退出码 |
$$ |
当前 Shell 的 PID |
$! |
最后一个后台命令的 PID |
字符串操作
bash
str="Hello World"
echo ${#str} # 长度:11
echo ${str:0:5} # 截取:Hello
echo ${str/World/Buddy} # 替换第一个匹配:Hello Buddy
echo ${str//o/O} # 全局替换:HellO WOrld
# 默认值处理(变量不存在或为空时使用默认值)
echo ${UNSET_VAR:-"default"}
条件判断与测试
常用测试标志
- 文件测试 :
-f存在且为普通文件,-d目录,-e存在,-x可执行,-s非空 - 字符串测试 :
=相等,!=不等,-z空为真,-n非空为真 - 数字测试 :
-eq(等于),-ne,-gt,-lt,-ge,-le
推荐使用 [[ ]] (Bash 扩展) ,支持 &&、|| 和正则匹配,且变量无需加引号防空格拆分。

bash
if [[ $name == "Alice" ]]; then
echo "Welcome, Alice"
elif [[ -f /etc/config ]]; then
echo "Config found"
else
echo "Nothing matched"
fi
# 一行写法
[[ -d /tmp ]] && echo "tmp exists"

case 多分支
bash
case "$1" in
start)
echo "Starting...";;
stop)
echo "Stopping...";;
restart|reload)
echo "Restarting...";;
*)
echo "Usage: $0 {start|stop|restart}";;
esac
循环结构
bash
# for 循环
for fruit in apple banana cherry; do
echo "I like $fruit"
done
# C 风格 for
for (( i=0; i<5; i++ )); do
echo "Number: $i"
done
# 遍历文件
for logfile in /var/log/*.log; do
gzip "$logfile"
done
# while 循环
count=1
while [[ $count -le 5 ]]; do
echo "Count: $count"
((count++)) # 自增
done
# 按行读取文件
while IFS= read -r line; do
echo "$line"
done < "file.txt"
循环控制 :break 跳出整个循环,continue 跳过本次循环余下部分。
函数
bash
# 定义
say_hello() {
local name=$1 # 局部变量
echo "Hello, $name"
return 0 # 返回值 0-255,仅表示状态
}
# 调用
say_hello "Linux"
# 获取函数输出
msg=$(say_hello "World")
echo "$msg"
# 函数内可使用 $1..$n 获取参数
重定向与管道
| 操作 | 说明 |
|---|---|
cmd > file |
标准输出覆盖写入 |
cmd >> file |
标准输出追加写入 |
cmd < file |
从文件读取输入 |
cmd 2> err.log |
标准错误覆盖写入 |
cmd &> all.log |
标准输出和错误都写入同一文件 |
cmd > /dev/null 2>&1 |
丢弃所有输出 |
| `cmd1 | cmd2` |
| `cmd | tee file` |
Here Document(多行文本输入):
bash
cat <<EOF > output.txt
Line 1
Line 2
EOF
文本处理三剑客
grep:搜索文本
bash
grep "pattern" file
grep -i "pattern" file # 忽略大小写
grep -r "pattern" /dir/ # 递归搜索
grep -v "pattern" file # 反向匹配
grep -c "pattern" file # 计数
grep -E "regex" file # 扩展正则
sed:流编辑器,常用于替换
bash
sed 's/old/new/g' file # 全局替换(仅输出,不改文件)
sed -i 's/old/new/g' file # 直接修改文件
sed '/pattern/d' file # 删除匹配行
sed -n '5,10p' file # 打印第5到10行
awk:强大的文本分析工具
bash
awk '{print $1, $3}' file # 打印第1和第3列(默认空格分隔)
awk -F: '{print $1}' /etc/passwd # 指定分隔符为冒号
awk '$3 > 1000' /etc/passwd # 按条件过滤
实用操作
- 历史命令 :
history,!!执行上一条,!$上条最后一个参数,!n执行第 n 条。 - 花括号扩展 :
echo file{1,2,3}.txt展开为file1.txt file2.txt file3.txt - 快速备份 :
cp file.txt{,.bak}变成cp file.txt file.txt.bak - 子 shell :
(cd /tmp && ls)目录切换不影响当前 Shell - 算术运算 :
echo $((5 + 3 * 2)),或let a=5+3 - 读取用户输入 :
read -p "Your name: " username - 别名 :
alias ll='ls -lh',永久写入~/.bashrc或~/.bash_aliases
常见错误解决方法
- 变量始终加双引号 :
"$var",防止包含空格时出现意外。 - 脚本头部加保护 :
set -euo pipefail或set -eu。 - **使用
[[ ]]而非 **[ ]进行测试(写 Bash 脚本时)。 - 命令替换用
$()而非反引号,嵌套更清晰。 - 函数内变量用
local声明,避免污染全局变量。 - 删除操作前务必确认 :先用
echo测试命令,或rm前加-i。 - 检查命令退出码 :
if command; then echo ok; fi。 - 避免将变量放在
cd等命令前不加引号,防止路径包含空格出错。