Linux Shell 完整教程:从入门到精通
目录
-
(图片来源网络,侵删)- 什么是 Shell?
- 为什么学习 Shell?
- 如何进入 Shell?
- 第一个 Shell 命令
- 基本文件和目录操作
- 查看帮助信息
-
- 文件权限管理
- 文本处理三剑客
- 管道与重定向
- 用户与权限管理
- 软件包管理
- 进程管理
-
- 什么是 Shell 脚本?
- 第一个 Shell 脚本
- 变量
- 条件判断
- 循环结构
- 函数
- 脚本调试
-
- 参数传递
- 数组
- 字符串操作
- 读取用户输入
- 调试与日志
- 实战案例:系统监控脚本
-
(图片来源网络,侵删)- 推荐书籍
- 在线资源
- 最佳实践
第一部分:Shell 基础入门
什么是 Shell?
Shell 是一个命令行解释器,它位于用户和 Linux 内核之间,用户输入命令,Shell 解释这些命令,并将其传递给内核执行,执行完成后,内核将结果返回给 Shell,Shell 再将结果展示给用户。
你可以把 Shell 想象成是一个“翻译官”,负责沟通“你”(用户)和“电脑”(内核)。
常见的 Shell 有:
- Bash (Bourne Again Shell):Linux 系统中最常用的 Shell,默认 Shell。
- Zsh (Z Shell):功能非常强大的 Shell,拥有丰富的插件和主题(如 Oh My Zsh)。
- Ksh (Korn Shell):功能也很强大,常用于商业 Unix 系统。
- Fish (Friendly Interactive Shell):以其友好的用户界面和自动补全功能著称。
本教程将以最普及的 Bash 为例进行讲解。

为什么学习 Shell?
- 自动化:将重复性的手动操作写成脚本,一键执行,极大提高效率。
- 系统管理:绝大多数 Linux 服务器管理都通过命令行完成,Shell 是核心工具。
- 深度控制:相比于图形界面,Shell 提供了对系统更底层、更精细的控制。
- 提升效率:熟练使用 Shell 命令和脚本,可以让你在 Linux 环境下如鱼得水。
如何进入 Shell?
打开你的 Linux 终端(Terminal),你看到的那个 或 开头的提示符,就表示你已经进入了 Shell。
- 表示普通用户。
- 表示超级用户。
第一个 Shell 命令
echo "Hello, World!"
echo是一个命令,用于在终端输出文本。"Hello, World!"是要输出的内容。
按下回车,你会看到终端打印出 Hello, World!。
基本文件和目录操作
| 命令 | 全称 | 作用 | 示例 |
|---|---|---|---|
ls |
list | 列出当前目录下的文件和文件夹 | ls -l (以列表形式显示详细信息) |
cd |
change directory | 切换目录 | cd /home (切换到 /home 目录) |
pwd |
print working directory | 显示当前所在目录的完整路径 | pwd |
mkdir |
make directory | 创建新目录 | mkdir my_folder |
touch |
- | 创建一个空文件或更新文件时间戳 | touch file.txt |
cp |
copy | 复制文件或目录 | cp file.txt file_backup.txt |
mv |
move | 移动文件/目录 或 重命名文件/目录 | mv file.txt new_name.txt (重命名) |
rm |
remove | 删除文件或目录 | rm file.txt (删除文件) rm -r my_folder (递归删除目录) |
man |
manual | 查看命令的帮助手册 | man ls |
小技巧:使用 Tab 键可以自动补全命令和文件名,这是提高效率的神器!
查看帮助信息
当你遇到一个不熟悉的命令时,最好的方法是查看它的帮助信息。
man <command>:最详细的帮助手册,使用q键退出。<command> --help:显示该命令的常用选项和简要说明。
ls --help
第二部分:Shell 高级操作
文件权限管理
Linux 是一个多用户系统,文件权限至关重要,每个文件都有所有者、所属组和其他用户三种身份,每种身份都有读、写、执行三种权限。
r(read): 读权限,数值为 4。w(write): 写权限,数值为 2。x(execute): 执行权限,数值为 1。
使用 ls -l 查看文件时,会显示类似 -rw-r--r-- 的信息。
- 第一个字符 表示这是一个文件,
d表示目录。 - 接下来的 9 个字符分为三组,分别代表所有者、所属组、其他用户的权限。
修改权限:chmod (change mode)
使用数字法修改权限:
# 给 file.txt 的所有者添加读写执行权限,所属组和其他用户添加读和执行权限 # 所有者: rwx = 4+2+1 = 7 # 所属组: r-x = 4+1 = 5 # 其他用户: r-x = 4+1 = 5 chmod 755 file.txt
修改所有者:chown (change owner)
# 将 file.txt 的所有者改为 user1,所属组改为 group1 sudo chown user1:group1 file.txt
文本处理三剑客
这是 Linux/Unix 系统中处理文本的三个核心工具,威力无穷。
-
grep: 全局搜索正则表达式并打印行。- 作用:在文件中搜索匹配特定模式的行。
- 示例:
grep "error" /var/log/syslog(在系统日志中搜索包含 "error" 的行)。
-
sed: 流编辑器。- 作用:对输入的文本流进行编辑(查找、替换、删除、插入等)。
- 示例:
sed 's/old_text/new_text/g' file.txt(将 file.txt 中的所有 "old_text" 替换为 "new_text")。
-
awk: 报告生成器。- 作用:对文本按行或按字段进行复杂的处理和格式化输出。
- 示例:
awk '{print $1, $3}' file.txt(打印 file.txt 的每一行的第 1 列和第 3 列)。
管道与重定向
这是 Shell 的精髓,允许你将命令连接起来,构建强大的工作流。
-
重定向
>:标准输出重定向,将命令的输出结果写入文件(覆盖)。echo "Hello" > output.txt
>>:标准输出追加重定向,将命令的输出结果追加到文件末尾。echo "World" >> output.txt
<:标准输入重定向,让命令从文件中读取输入,而不是从键盘。sort < names.txt
-
管道
- 将前一个命令的标准输出作为后一个命令的标准输入。
- 示例:
ps aux | grep "nginx"(先列出所有进程,然后从中过滤出包含 "nginx" 的行)。 - 示例:
cat file.txt | sort | uniq(查看文件内容,排序,然后去除重复行)。
用户与权限管理
sudo <command>:以超级用户权限执行命令,首次使用时需要输入当前用户的密码。su - <username>:切换到指定用户,并加载其环境配置。su -切换到 root 用户。useradd <username>:创建一个新用户。passwd <username>:修改用户密码。userdel -r <username>:删除一个用户及其主目录。
软件包管理
不同发行版使用不同的包管理器。
- Debian/Ubuntu:
apt(Advanced Package Tool)sudo apt update(更新软件包列表)sudo apt install <package_name>(安装软件包)sudo apt remove <package_name>(卸载软件包)
- CentOS/RHEL/Fedora:
yum或dnfsudo yum install <package_name>sudo dnf install <package_name>
进程管理
ps aux:列出当前正在运行的进程。a(all),u(user-oriented),x(include processes not attached to a terminal)。top或htop:动态地显示系统中运行的进程,并按 CPU/内存使用率排序。htop是top的增强版,更直观。kill <pid>:终止指定进程 ID 的进程。pkill <process_name>:根据进程名终止进程。jobs:列出当前 shell 会话中后台运行的作业。bg <job_id>:将一个暂停的作业放到后台运行。fg <job_id>:将一个后台作业放到前台运行。
第三部分:Shell 脚本编程核心
什么是 Shell 脚本?
Shell 脚本就是一个包含一系列 Shell 命令的文本文件,通过将命令写入文件,我们可以让它们按顺序自动执行,实现复杂的逻辑和自动化任务。
第一个 Shell 脚本
-
创建一个文件
hello.sh:touch hello.sh
-
用编辑器(如
vim,nano)打开文件,并写入以下内容:#!/bin/bash echo "Hello from a Shell Script!" echo "The current date is: $(date)"
-
第一行
#!/bin/bash是一个 shebang,它告诉系统这个脚本应该使用哪个解释器来执行(这里是 Bash)。 -
给脚本添加可执行权限:
chmod +x hello.sh
-
执行脚本:
# 方法一:使用 bash 解释器执行 bash hello.sh # 方法二:直接执行(需要可执行权限) ./hello.sh
变量
- 定义变量:
变量名=变量值(注意 两边不能有空格)name="Alice" version=1.0
- 使用变量:在变量名前加
echo "Hello, $name" echo "Version: $version"
- 只读变量:使用
readonly命令。readonly PI=3.14159 # PI=3.14 # 这会报错
- 删除变量:使用
unset命令。unset version
条件判断
Shell 中的条件判断主要使用 if 语句和 test 命令(或 [ ])。
test命令和[ ]是等价的。[ ]是test命令的别名,使用更广泛。- 注意:
[和]两边必须有空格!
常用判断条件:
| 判断类型 | 语法 | 示例 |
|---|---|---|
| 数值比较 | [ $a -eq $b ] |
a 等于 b |
[ $a -ne $b ] |
a 不等于 b | |
[ $a -gt $b ] |
a 大于 b | |
[ $a -lt $b ] |
a 小于 b | |
| 字符串比较 | [ "$str1" = "$str2" ] |
str1 等于 str2 |
[ "$str1" != "$str2" ] |
str1 不等于 str2 | |
[ -z "$str" ] |
str 的长度为 0 | |
[ -n "$str" ] |
str 的长度不为 0 | |
| 文件判断 | [ -f "file" ] |
file 是一个普通文件 |
[ -d "dir" ] |
dir 是一个目录 | |
[ -r "file" ] |
file 可读 | |
[ -w "file" ] |
file 可写 | |
[ -x "file" ] |
file 可执行 |
if-elif-else 结构示例:
#!/bin/bash
age=25
if [ $age -lt 18 ]; then
echo "You are a minor."
elif [ $age -lt 60 ]; then
echo "You are an adult."
else
echo "You are a senior."
fi
循环结构
for 循环:
#!/bin/bash
# 遍历列表
for i in 1 2 3 4 5
do
echo "Number: $i"
done
# 遍历命令的输出
for file in $(ls *.txt)
do
echo "Processing file: $file"
done
while 循环:
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "Count is: $count"
count=$((count + 1)) # ((count++)) 在某些 shell 中也支持
done
函数
#!/bin/bash
# 定义函数
greet() {
local name=$1 # 使用 local 定义局部变量
echo "Hello, $name! Welcome to the function."
}
# 调用函数
greet "Alice"
greet "Bob"
脚本调试
当脚本出错时,调试非常重要。
-
bash -x your_script.sh:执行脚本并打印出每一行命令及其输出,非常有助于理解执行流程。 -
在脚本中添加
set -x和set +x来开启和关闭调试模式。#!/bin/bash echo "This line will be printed normally." set -x # 开启调试 echo "This line and all following will be traced." set +x # 关闭调试 echo "This line will be printed normally again."
第四部分:Shell 脚本实战与进阶
参数传递
脚本可以接受从命令行传入的参数。
| 参数 | 含义 |
|---|---|
$0 |
脚本名称 |
$1 |
第一个参数 |
$2 |
第二个参数 |
| ... | ... |
| 参数的个数 | |
| 所有参数,作为一个列表 | |
| 所有参数,作为一个字符串 |
示例 params.sh:
#!/bin/bash echo "Script Name: $0" echo "First Param: $1" echo "Second Param: $2" echo "Total Params: $#" echo "All Params as a list: $@" echo "All Params as a string: $*"
执行:./params.sh arg1 arg2 arg3
数组
#!/bin/bash
# 定义数组
fruits=("apple" "banana" "cherry")
# 访问元素
echo "First fruit: ${fruits[0]}"
echo "Second fruit: ${fruits[1]}"
# 遍历数组
echo "All fruits:"
for fruit in "${fruits[@]}"; do
echo "- $fruit"
done
# 获取数组长度
echo "Number of fruits: ${#fruits[@]}"
字符串操作
#!/bin/bash
str="Hello, World!"
# 获取长度
echo "Length: ${#str}"
# 子串提取
echo "Substring (0-5): ${str:0:5}" # 提取从索引0开始的5个字符
# 查找子串
echo "Index of 'World': ${str#*World}" # 这个命令会返回从 World 开始到结尾的字符串
# 更准确的查找方法:
if [[ "$str" == *"World"* ]]; then
echo "'World' is found in the string."
fi
读取用户输入
使用 read 命令。
#!/bin/bash echo "Please enter your name:" read name echo "Hello, $name!" # -p 选项可以直接提示信息 read -p "Enter your age: " age echo "You are $age years old."
调试与日志
一个健壮的脚本应该有良好的日志记录功能。
#!/bin/bash
LOG_FILE="my_script.log"
# 定义一个日志函数
log() {
local message=$1
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $message" | tee -a $LOG_FILE
}
log "Script started."
log "Processing some data..."
log "Script finished."
tee -a 命令可以将内容同时输出到屏幕和追加到文件。
实战案例:系统监控脚本
创建一个 monitor.sh 脚本,用于监控 CPU 和内存使用率。
#!/bin/bash
# 监控脚本
# 获取CPU使用率
cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}')
# 获取内存使用率
mem_usage=$(free | grep Mem | awk '{print ($3/$2) * 100.0}')
# 定义阈值
CPU_THRESHOLD=80
MEM_THRESHOLD=80
echo "---------------------------------"
echo "System Resource Monitor"
echo "---------------------------------"
printf "CPU Usage: %.2f%%\n" $cpu_usage
printf "Memory Usage: %.2f%%\n" $mem_usage
echo "---------------------------------"
# 判断是否超过阈值
if (( $(echo "$cpu_usage > $CPU_THRESHOLD" | bc -l) )); then
echo "WARNING: CPU usage is high!"
fi
if (( $(echo "$mem_usage > $MEM_THRESHOLD" | bc -l) )); then
echo "WARNING: Memory usage is high!"
fi
注意:上面的脚本使用了 bc 命令来进行浮点数比较,如果你的系统没有安装,需要先安装 bc。
第五部分:学习资源与最佳实践
推荐书籍
- 《鸟哥的 Linux 私房菜》:Linux 入门圣经,Shell 部分讲解非常透彻。
- 《Linux 命令行与 Shell 脚本编程大全》:非常全面和深入,适合系统学习和作为参考手册。
在线资源
- ShellCheck:一个在线的 Shell 脚本静态分析工具,可以帮你发现脚本中的常见错误和潜在问题,强烈推荐!
- explainshell.com:可以输入一个复杂的命令行,它会为你解释每个部分的作用。
- man pages:所有命令最权威的文档。
最佳实践
- 添加注释:为你的脚本添加清晰的注释,解释代码的意图和逻辑。
- 使用有意义的变量名:
user_count比uc更易于理解。 - 处理错误:使用
set -e让脚本在遇到错误时立即退出,防止错误累积,或者使用if语句检查命令的返回值 。 - 使用
#!/bin/bash:明确指定解释器,而不是使用#!/bin/sh,因为sh可能指向一个功能较少的 shell。 - 引用你的变量:在变量名外加上双引号 ,特别是当变量可能包含空格时,可以防止意外的分割。
- 模块化:将复杂的功能拆分成小的函数,提高代码的可读性和复用性。
- 先测试,再运行:在生产环境执行脚本前,先在测试环境中充分验证。
学习 Shell 是一个循序渐进的过程,从掌握最基本的命令开始,然后逐步学习管道、重定向等高级技巧,最后再深入到脚本编程,多动手实践,多写脚本,多看别人的优秀代码,你的 Shell 技巧一定会越来越精湛。
祝你学习愉快!
