3001 字
15 分钟
Shell第一章 入门筑基:从零开启脚本之路

很多刚接触Linux运维的同学,都会觉得Shell是一道门槛——看着黑框框里一行行命令很酷炫,自己写却总踩坑。其实Shell并没有那么难,它就是一门「把命令串起来」的脚本语言,是运维工程师提升效率、实现自动化的第一利器。

本章我们完全从零开始,不讲复杂原理,先带你搞懂Shell是什么,搭好学习环境,并深入掌握Shell脚本的编写规范、核心数据类型(字符串与数组)以及变量的正确定义方式。学完本章,你就能写出规范的Shell脚本,迈出自动化的第一步。


1.1 认知篇:Shell到底是什么?运维为什么必学?#

1.1.1 Shell是什么?#

我们常说的Linux,本质上分为两层:

  • 内核(Kernel):系统的核心,直接控制硬件(CPU调度、内存分配、磁盘读写),普通用户没法直接和内核对话。
  • Shell:包裹在内核外层的「命令解释器」,相当于用户和内核之间的翻译官。

你在终端里输入的每一行命令,都是先交给Shell解析,Shell翻译成内核听得懂的指令,再让内核去调用硬件执行,最后把结果返回给你。打个通俗的比方:内核是工厂里的机器,Shell是操作面板,你按面板上的按钮(输入命令),面板就会控制机器干活。

Linux里有很多种Shell,最主流的是 Bash(Bourne Again Shell),几乎所有Linux发行版(Ubuntu、CentOS、Debian等)都默认自带Bash,也是本教程全程使用的版本。

1.1.2 运维为什么一定要学Shell?#

很多同学会问:现在都有Ansible、Python、Go了,还有必要学Shell吗?答案是非常有必要,核心原因有三点:

  1. 原生通用,零依赖:任何一台Linux服务器开机就有Shell,不需要额外安装任何环境。当你接手一台完全陌生的内网服务器时,Python可能没装,但Shell一定在。
  2. 运维效率的绝对放大器:假设老板让你查出50台服务器上即将过期的SSL证书。手动登录排查可能要2小时;用Python写需要调用各种SSH库;而用Shell,一个for循环配合openssl命令,3分钟就能输出完美的统计报表。
  3. 所有运维工具的底层基础:Ansible的Playbook、Docker的Dockerfile、K8s的探针脚本,底层本质全都是Shell命令。学好Shell,你才能看懂高级工具的底层逻辑,遇到报错时迅速定位。

一句话总结:Shell是运维的「九阳神功」内功心法,上手快、用处广,是你从「手动搬砖」走向「自动化运维」的必经之路。


1.2 环境篇:Linux终端环境确认与Shell基础配置#

学习Shell不需要装复杂的软件,只要有一台Linux环境就行——无论是云服务器、虚拟机,还是WSL子系统,都完全适用。

1.2.1 确认你的Shell版本#

打开终端,输入以下命令,就能看到当前系统默认的Shell:

终端
echo $SHELL

正常会输出 /bin/bash,说明你用的就是Bash。

1.2.2 终端提示符的含义#

刚打开终端,你会看到一行前缀,这叫「命令提示符」,包含了关键信息:

  • 普通用户登录:结尾是 $ 符号
  • root管理员登录:结尾是 # 符号

举个例子:ubuntu@server:~$,分别代表「当前用户名@主机名:当前所在目录」,~ 代表用户的家目录。

[!TIP] 小白提示 本教程所有命令,默认以普通用户身份执行,涉及管理员权限的命令会标注 sudo。千万不要养成日常用 root 裸奔的坏习惯!

1.2.3 核心配置文件加载顺序#

Bash有几个极其重要的配置文件,了解它们的加载顺序,能帮你解决80%的“环境变量不生效”问题:

  1. /etc/profile:全局配置,所有用户登录时最先加载。
  2. ~/.bash_profile 或 ~/.profile:当前用户的环境变量配置。
  3. ~/.bashrc:当前用户的交互式配置(每次打开新终端窗口都会加载),这里最适合写你自己的 alias 别名。
  4. /etc/bashrc:全局交互式配置。

[!IMPORTANT] 核心原则 个人日常使用的变量和别名,闭眼写进 ~/.bashrc 即可。修改后记得执行 source ~/.bashrc 让它立刻生效。


1.3 基础语法篇:编写规范、变量与数据类型#

1.3.1 脚本编写规范与执行方式#

Shell脚本的本质,就是把你平时一行行敲的命令,按顺序写进一个文本文件里。

我们来写一个输出「Hello World」的脚本:

helloworld.sh
#!/bin/bash
# 这是一个单行注释
echo "Hello World!"
:<<!
这是一个多行注释
这里面的内容不会被执行
!

脚本结构解析:

  1. 第一行 #!/bin/bash:这叫「Shebang」。它的作用是告诉系统:请用 /bin/bash 这个解释器来运行以下代码。必须顶格写,前面绝对不能有空格。
  2. 注释:# 用于单行注释,:<<! 和 ! 用于多行注释。

执行脚本: 通常我们需要先赋予脚本执行权限,然后再运行:

终端
chmod +x helloworld.sh
./helloworld.sh

[!CAUTION] 常见报错解析 如果执行时提示 bad interpreter: No such file or directory,通常是因为第一行的 #!/bin/bash 写错了(比如多加了空格或斜杠写成了 #!/bin/bash/),或者在Windows下编写带有 CRLF 换行符(需使用 dos2unix 转换)。

1.3.2 变量的定义与作用域#

在Shell中,变量可以分为局部变量、常量和全局(环境)变量。在Bash环境中,变量的默认类型都是字符串类型,无法直接进行数值运算。

1. 局部变量#

只在当前的脚本文件中有效的变量。

var_demo.sh
#!/bin/bash
# 定义变量(等号两边绝对不能有空格!)
name="运维小白"
age = 20 # ❌ 错误写法:会报错 command not found
age=20 # ✅ 正确写法
# 规范引用变量:务必加上花括号界定边界
echo "我的名字是${name},今年${age}岁"

变量命名规则:

  1. 只能由字母、数字和下划线组成,不能以数字开头。
  2. 等号两侧不能有空格。
  3. 变量的值如果有空格,必须使用双引号括起来。
  4. 不能使用Shell的关键字作为变量名。

2. 常量(只读变量)#

定义之后就不能再被修改的变量。

readonly_demo.sh
#!/bin/bash
my_url="https://www.google.com"
readonly my_url
my_url="https://www.baidu.com" # ❌ 运行时会报错:This variable is read only.

3. 全局变量(环境变量)#

使用 export 命令可以将局部变量提升为全局变量,这样在当前脚本中调用的其他子脚本也能访问到该变量。

demo1.sh
#!/bin/bash
var_env="张三"
export var_env
sh demo2.sh # 在demo2.sh中可以直接使用 ${var_env}

[!TIP] 删除变量 如果需要删除一个变量(常量除外),可以使用 unset 变量名 命令。

1.3.3 特殊内置变量#

Shell 提供了一系列预定义的特殊变量,用于获取脚本运行时的状态和参数:

  • $0:当前脚本的名称。
  • $1, $2, …:传入脚本的第1个、第2个参数。当参数超过9个时,必须用花括号括起来,如 ${10}。
  • $#:传入脚本的参数总个数。
  • $?:最后执行的命令的退出状态(0代表成功,非0代表失败)。
  • $!:最后创建的后台进程的进程ID。
special_vars.sh
#!/bin/bash
echo "当前脚本名称: $0"
echo "第一个参数: $1"
echo "参数总数: $#"
# 挂起一个后台进程
sleep 10 &
echo "后台进程ID: $!"
echo "上一条命令状态码: $?"

1.4 数据类型核心:字符串与数组#

Shell编程中最核心的数据承载形式就是字符串和数组。

1.4.1 字符串的定义与操作#

字符串有三种定义方式,它们的解析规则完全不同:

1. 单引号(强引用)#

任何内容都会原样输出,在单引号中拼接变量是无效的。单引号内部不能再出现单独的单引号(转义也不行)。

Terminal window
name="张三"
echo '你好,${name}' # 输出:你好,${name}

2. 双引号(弱引用)#

双引号内部的变量会被解析。如果字符串中包含空格或变量,最推荐使用双引号。

Terminal window
name="张三"
echo "你好,${name}" # 输出:你好,张三

3. 获取长度与字符串拼接#

可以通过 ${#变量名} 获取字符串的长度,拼接字符串直接将变量写在一起即可。

string_demo.sh
#!/bin/bash
str="Hello"
echo "字符串长度为:${#str}" # 输出:5
# 双引号拼接
name="World"
greeting="hello, ${name} !"
echo ${greeting}
# 字符串截取语法:${变量名:起始索引:截取长度}(索引从0开始)
text="Linux Shell"
echo ${text:0:5} # 输出:Linux

1.4.2 数组的定义与增删改查#

Bash支持一维数组(不支持多维数组),数组元素的索引从0开始。

1. 定义数组#

可以使用空格分隔元素,或者明确指定索引:

Terminal window
# 方式一:空格分隔
arr1=(item1 item2 item3)
# 方式二:自定义索引
arr2=([0]=item1 [2]=item3)

2. 读取与获取长度#

获取数组元素时,推荐使用 @ 或 * 来获取全部元素:

array_demo.sh
#!/bin/bash
arr=(apple banana orange)
# 获取特定元素
echo "第一个元素:${arr[0]}"
# 获取所有元素
echo "所有元素:${arr[@]}"
# 获取数组长度
echo "数组长度:${#arr[@]}"
# 获取特定元素的字符串长度
echo "banana的长度:${#arr[1]}"

3. 删除数组元素#

使用 unset 可以删除数组的指定元素或整个数组:

Terminal window
unset arr[1] # 删除索引为1的元素 (banana)
unset arr # 删除整个数组

1.5 常用内置命令与交互#

Shell自带了一些强大的内置命令(Built-in commands),它们由Bash自身提供,执行效率极高。

1.5.1 alias 设置别名#

当某些命令过长且经常使用时,可以通过 alias 设置简短的别名。

终端
# 设置别名
alias pg='ps -aux | grep'
# 使用别名
pg nginx
# 查看当前环境下的所有别名
alias
# 删除指定别名
unalias pg

[!NOTE] 永久生效 在终端直接执行的 alias 只在当前窗口有效。如果想永久生效,请将其写入 ~/.bashrc 文件中。

1.5.2 read 交互式读取#

read 命令用于从标准输入(键盘)读取数据并赋值给变量,是编写交互式脚本的核心。

常用参数:

  • -p:指定提示信息。
  • -t:指定等待输入的超时时间(秒),超时后自动跳过。
  • -s:静默输入(输入内容不回显,常用于输入密码)。
read_demo.sh
#!/bin/bash
# 读取多个变量
read -p "请输入姓名和年龄(空格分隔):" name age
echo "你输入的名字是 ${name},年龄是 ${age}"
# 密码静默输入与超时限制
read -t 10 -s -p "请输入数据库密码(10秒内):" db_pass
echo -e "\n密码已接收!"

(注:如果 read 后面不加任何变量名,输入的内容会默认存入系统内置的 $REPLY 变量中。)


1.6 本章小结#

  1. 核心认知:Shell是操作系统的命令解释器,是自动化运维必不可少的基础技能。
  2. 编写规范:脚本首行必须声明 #!/bin/bash,执行前赋予 chmod +x 权限。
  3. 变量铁律:等号两边无空格;引用变量加 {};单引号原样输出,双引号解析变量;默认类型皆为字符串。
  4. 特殊变量:牢记 $0(脚本名)、$1(参数)、$?(状态码)和 $#(参数个数)的含义。
  5. 数据类型:掌握字符串的截取与拼接,熟练使用 arr=(a b c) 和 ${arr[@]} 操作一维数组。
  6. 交互能力:利用 alias 简化日常命令,通过 read -p 实现脚本与用户的输入交互。

掌握了以上基础,你就已经具备了Shell数据处理的核心能力,下一章我们将深入学习流程控制(分支判断与循环)以及函数封装!

Shell第一章 入门筑基:从零开启脚本之路
https://www.6ixblog.site/posts/linux-shell-1/
作者
Licwic
发布于
2025-05-01
许可协议
CC BY-NC-SA 4.0