【Linux从入门到精通】第21篇:Shell脚本开篇——什么是Shell?写第一个Hello World

目录

一、引言:Shell是什么?

[1.1 你每天都在用Shell,只是没意识到](#1.1 你每天都在用Shell,只是没意识到)

[1.2 Shell在系统中的位置](#1.2 Shell在系统中的位置)

[1.3 Shell的多样性](#1.3 Shell的多样性)

[1.4 什么是Shell脚本?](#1.4 什么是Shell脚本?)

[二、第一个脚本:Hello World](#二、第一个脚本:Hello World)

[2.1 创建并编写脚本](#2.1 创建并编写脚本)

[2.2 赋予执行权限](#2.2 赋予执行权限)

[2.3 执行脚本](#2.3 执行脚本)

三、三种执行方式的本质区别

四、变量:脚本的"记忆细胞"

[4.1 定义变量:一条严格的语法](#4.1 定义变量:一条严格的语法)

[4.2 引用变量的多种写法](#4.2 引用变量的多种写法)

[4.3 环境变量 vs 局部变量](#4.3 环境变量 vs 局部变量)

[4.4 只读变量与删除变量](#4.4 只读变量与删除变量)

[4.5 命令替换:把命令结果存进变量](#4.5 命令替换:把命令结果存进变量)

五、本篇小结

动手练习

六、下篇预告


一、引言:Shell是什么?

1.1 你每天都在用Shell,只是没意识到

每当你通过SSH登录Linux,看到这个提示符:

bash

复制代码
root@server:~$ _

你就在Shell 里面了。你输入lscdtop,回车后看到结果------这个"接收你输入的命令、传给系统执行、把结果展示给你"的程序,就是Shell。

1.2 Shell在系统中的位置

如果把Linux想象成一家公司:

角色 对应组件 职责
董事长 内核(Kernel) 掌控所有硬件资源,但不直接和基层员工说话
总经理秘书 Shell 把员工的诉求翻译成董事长听得懂的语言,把董事长的批复传达给员工
员工 想做事,但无法直接指挥硬件,必须通过秘书

从技术架构看:

text

复制代码
用户 → 终端模拟器 → Shell → 系统调用 → 内核 → 硬件
  • 终端(Terminal):你看到那个黑框框窗口(如GNOME Terminal、iTerm2)

  • Shell:在终端里运行的程序(如Bash、Zsh、Fish),负责解释你输入的命令

  • 内核:真正干活的人

1.3 Shell的多样性

Linux上有多种Shell可供选择:

bash

复制代码
cat /etc/shells   # 查看系统支持哪些Shell
echo $SHELL       # 查看当前使用的Shell

常见的Shell:

Shell 全称 特点
sh Bourne Shell Unix原始Shell,功能最简
bash Bourne Again Shell Linux默认Shell,功能强大
zsh Z Shell 兼容bash,更强的交互体验
dash Debian Almquist Shell 极简,启动快,Ubuntu的/bin/sh指向它

本文及整个专栏的脚本均使用bash------它是Linux发行版的事实标准,语法兼容性最广。

1.4 什么是Shell脚本?

当你把多条命令按顺序写进一个文件,加上一些逻辑控制(如果...就...),这个文件就是Shell脚本

bash

复制代码
#!/bin/bash
# 这是我写的第一个Shell脚本
echo "Hello, Shell!"
date
whoami

这三行命令如果每次都要手动逐一输入,很烦。写成脚本后,一句./hello.sh全搞定。这就是Shell脚本的第一层意义:把重复操作变成一键执行

二、第一个脚本:Hello World

2.1 创建并编写脚本

bash

复制代码
# 创建脚本文件
vim hello.sh

写入以下内容:

bash

复制代码
#!/bin/bash
# 我的第一个Shell脚本
echo "Hello World!"
echo "今天是:$(date)"
echo "当前用户:$(whoami)"

逐行解释

  • #!/bin/bashShebang(也叫Hashbang),告诉系统"用/bin/bash这个解释器来执行本文件"

  • # 我的第一个...:注释(以#开头的行不执行)

  • echo:输出文本到屏幕

  • $(date):命令替换------先执行date命令,把输出结果嵌入到这里

2.2 赋予执行权限

bash

复制代码
ls -l hello.sh   # 默认没有执行权限(-rw-r--r--)
chmod +x hello.sh
ls -l hello.sh   # 多了一个x(-rwxr-xr-x)

2.3 执行脚本

bash

复制代码
./hello.sh

输出:

text

复制代码
Hello World!
今天是:Sun Apr 26 15:30:00 CST 2026
当前用户:zhangsan

为什么是./hello.sh而不是直接hello.sh

Linux只在PATH环境变量指定的目录中查找可执行文件(如/usr/bin/usr/local/bin)。当前目录一般不在PATH中(出于安全考虑),所以需要加上./明确告诉系统:"就在当前目录找"。

三、三种执行方式的本质区别

执行Shell脚本有三种方式,它们看似一样,实则不同:

bash

复制代码
# 方式一:直接执行(需要x权限)
./hello.sh

# 方式二:用bash命令执行(不需要x权限)
bash hello.sh

# 方式三:source执行(在当前Shell中执行)
source hello.sh
. hello.sh     # . 是 source 的简写
对比维度 ./hello.sh bash hello.sh source hello.sh
需要x权限
启动方式 启动子Shell 启动子Shell 当前Shell中执行
对当前环境的影响 不改变当前Shell 不改变当前Shell 会改变当前Shell
Shebang生效 忽略(用bash)

什么时候必须用source?

当你修改了~/.bashrc配置后,希望立即生效:

bash

复制代码
source ~/.bashrc   # 在当前Shell中加载配置,立即生效

如果写成bash ~/.bashrc,会在子Shell中执行,子Shell退出后一切环境变量都丢了,等于白干。

四、变量:脚本的"记忆细胞"

脚本不只是顺序执行命令,还需要记住数据传递信息。这靠的就是变量。

4.1 定义变量:一条严格的语法

bash

复制代码
#!/bin/bash
# 定义变量(注意:= 两边不能有空格!)
name="zhangsan"
age=25
pi=3.14
current_time=$(date)

# 引用变量(用$符号)
echo "姓名:$name"
echo "年龄:$age"
echo "Pi的值:$pi"
echo "当前时间:$current_time"

最容易犯的错误

bash

复制代码
name = "zhangsan"   # 错误!Shell会把name当成命令执行
name ="zhangsan"    # 错误!
name= "zhangsan"    # 错误!
name="zhangsan"     # 正确

为什么=两边不能有空格?

Shell把空格视为命令和参数的分隔符。name = "zhangsan"被解析为"执行name命令,参数是=zhangsan"------而系统里根本没有name这个命令。

4.2 引用变量的多种写法

bash

复制代码
name="world"

echo $name       # world
echo ${name}     # world(花括号明确变量边界)
echo "${name}"   # world(双引号内解析变量)
echo '${name}'   # ${name}(单引号原样输出,不解析)

花括号{}的必要场景

bash

复制代码
prefix="super"
echo "$prefixman"     # 空值(Shell找的是prefixman变量)
echo "${prefix}man"   # superman(明确边界)

推荐习惯 :始终用${变量名}的写法,避免边界不明确导致的bug。

4.3 环境变量 vs 局部变量

bash

复制代码
# 局部变量:只在当前脚本中有效
my_var="hello"

# 环境变量:当前Shell及所有子进程都能访问
export MY_GLOBAL="visible everywhere"

典型的环境变量

  • $HOME:当前用户家目录

  • $PATH:命令搜索路径

  • $USER:当前用户名

  • $PWD:当前工作目录

  • $RANDOM:生成一个随机数

  • $?:上一条命令的退出状态码

bash

复制代码
echo "我的家目录:$HOME"
echo "命令搜索路径:$PATH"
echo "当前用户:$USER"
echo "随机数:$RANDOM"

4.4 只读变量与删除变量

bash

复制代码
#!/bin/bash
readonly author="zhangsan"
author="lisi"   # 报错!author是只读变量

temp="delete me"
unset temp      # 删除变量
echo $temp      # 空值

4.5 命令替换:把命令结果存进变量

两种等价写法:

bash

复制代码
# 语法一:$(命令) —— 推荐
current_dir=$(pwd)
files_count=$(ls | wc -l)

# 语法二:`命令` —— 老式写法,不推荐(嵌套时易读性差)
current_dir=`pwd`

推荐使用$(),因为嵌套时更清晰:

bash

复制代码
# 统计某个目录下的文件数量
count=$(ls $(pwd) | wc -l)
# 如果换成反引号:count=`ls \`pwd\` | wc -l` —— 可读性差

五、本篇小结

Shell的本质:介于用户和内核之间的命令解释器,bash是Linux的事实标准。

Shebang#!/bin/bash告诉系统用哪个解释器执行脚本。写脚本第一行带上它是好习惯。

三种执行方式

  • ./script:标准执行,需要x权限,启动子Shell

  • bash script:不需要x权限,启动子Shell,忽略Shebang

  • source script:在当前Shell执行,会改变当前环境

变量三要点

  1. 定义:变量名=值,等号两边绝不能有空格

  2. 引用:$变量名${变量名}

  3. 命令替换:$(命令)获取命令输出

动手练习

bash

复制代码
#!/bin/bash
# 练习脚本:创建一个系统信息报告

# 1. 定义变量
report_time=$(date "+%Y-%m-%d %H:%M:%S")
host_name=$(hostname)
current_user=$(whoami)
kernel_ver=$(uname -r)
cpu_count=$(nproc)

# 2. 输出报告
echo "========== 系统信息报告 =========="
echo "报告时间:${report_time}"
echo "主机名:${host_name}"
echo "当前用户:${current_user}"
echo "内核版本:${kernel_ver}"
echo "CPU核心数:${cpu_count}"
echo "=================================="

将上述内容保存为system_info.sh,赋予执行权限,运行查看结果。

六、下篇预告

掌握了变量的基本使用,下一篇我们将深入学习Shell变量与数据类型,包括:

  • 如何获取字符串长度、截取子串

  • 环境变量的配置文件(~/.bashrc~/.bash_profile

  • 位置参数变量(把命令行参数传给脚本)

这些是构建复杂脚本逻辑的基础素材。


延伸思考 :执行echo $SHELL看你的当前Shell,再执行cat /etc/shells看系统装了哪些Shell。你有没有想过,脚本第一行的#!/bin/bash如果改成#!/usr/bin/python3会怎样?试试看------这正体现了Shebang的通用性:任何解释型语言都可以用这种方式写"可执行脚本"。

相关推荐
Lumos_7772 小时前
Linux -- 系统调用
linux·运维·算法
LSL666_2 小时前
4 Docker 镜像安装与容器启动
运维·docker·容器
坚持就完事了2 小时前
Linux中的cp命令
linux·运维·服务器
切糕师学AI2 小时前
使用 gdisk 快速判断硬盘分区表类型:是 GPT 还是 MBR?
linux·硬盘分区表·gdisk
2301_800976932 小时前
Linux的基本命令
linux·运维·服务器
原来是猿3 小时前
线程安全的单例模式
linux·服务器·开发语言·单例模式·策略模式
许愿OvO3 小时前
MySQL 8.3.0 运维与集群架构实战
运维·mysql·架构
凌云拓界3 小时前
青创赛终评手记:最后的成功
运维·科技·职场和发展·架构·创业创新
zjeweler3 小时前
宝藏网站推荐:云服务器特惠与网安学习资源的一站式聚合平台
运维·服务器·学习