把多个命令写入一个文件,让系统自动按顺序执行,就组成了Shell脚本。
顺序:如果没有指定顺序的话,那么就是 从上到下,从左到右
Shell脚本是批量命令的集合,让系统自动完成重复任务。类似Windows的.bat批处理文件,但更强大。
注意:只要是用bash脚本解析的脚步的第一行必须写:
#!/bin/bash
脚本文件名一般以.sh结尾
运行test脚本
bash test.sh
脚本写完需要为其增加一个执行权限
chmod +x test.sh
来看一个简单的脚本

- #!/bin/bash
脚本声明,指定用 bash 解释器运行这个脚本,之前讲过的Shebang 头 。
- cd /var/log
切换工作目录到 Linux 系统日志默认目录/var/log,后面操作messages日志文件就在这个文件夹里。
- cat /dev/null > messages
-
/dev/null是空黑洞,cat读取空内容
-
> 覆盖重定向 :用空白内容全覆盖messages,清空整个日志原有内容
- echo "log cleaned up." >> messages
-
是追加重定向(不覆盖原有内容)
-
在已经清空的messages文件末尾,写入一行记录:log cleaned up.
最终效果:日志全部清空,只留下这条【日志已清理】的备注记录。
整体脚本功能
进入系统日志目录 → 清空 messages 系统日志 → 在日志里留下一条清理标记,方便后续查看什么时候清过日志
变量
变量的命名规则
1、变量名称只能由字母、数字或下划线组成
2、不能以数字开头
3、严格区分大小写
4、不能使用Shell中保留的关键字 => test、if、for

赋值符=
=左右不能有空格
# 示例
name="Shell教程" # 字符串赋值
count=10 # 整型赋值
PI=3.1415926 # 浮点型赋值
is_valid=true # 布尔型赋值

$ 的作用:告诉系统后面不是普通文字,是变量名字,要拿它存的值
${name} 花括号用法
name=wang
echo ${name}123 # 输出 wang123
echo $name123 # 系统当成新变量name123,输出空
环境变量和普通变量
普通变量(局部变量)
定义方式:变量名=值(不加 export)
作用范围:只在当前 Shell 生效,子进程不能用特点:只在本进程内有效
环境变量(全局变量)
可以在创建它们的Shell及其派生出来的任意子进程Shell中使用
export:导出为环境(全局)变量,变量会传给后续新开的子 Shell 进程
大写变量,全局环境变量规范常用大写
① 系统全局性:
环境变量对所有进程有效;
任何程序(如编辑器、Shell 脚本等)都可以使用这些变量;
② 临时与永久:
在命令行中定义的环境变量只在当前会话中有效,一旦退出,变量就会消失;
有一些环境变量,比如
HOME(用户家目录)、
PATH(命令搜索路径)、
SHELL(Shell 类型)、
USER(用户名)、
PWD(当前工作目录)
等,这些变量在用户登录时由系统自动设置。
实操看一下环境变量和普通变量在子shell里的效果(临时)

echo $$:查看当前 Shell 的 PID(进程号)
我们bash打开一个子shall进程,
echo $$可以看到PID 改变,代表已经切换成子 Shell
可以看到环境变量被子进程继承,正常取值
普通变量没有传递给子shell,取值为空

永久设置环境变量
**永久设置,**如果希望变量在每次登录时都有效,需要将其添加到配置文件中
用户级别:~/.bash_profile 或 ~/.bashrc
系统级别:/etc/profile 或 /etc/bashrc
最后设置完了,要source一下
source ~/.bash_profile
source ~/.bashrc
source /etc/profile
source /etc/bashrc
我们写一个系统级别的试一下
vim /etc/bashrc


我们写一个系统级别的试一下
vim ~/.bash_profile


后加载的.bash_profile里name=456覆盖了前面/etc/bashrc的name=123
系统写死加载流程,永远是:
- 先读:
/etc/profile→ 连锁加载/etc/bashrc(系统全局文件,执行NAME=123,此时NAME=123) - 后读:
~/.bash_profile→ 内部自动调用~/.bashrc
所以:用户目录NAME=456 永远后执行 → 覆盖系统的123,最终NAME=456
环境变量的顺序
|------|-----------------------------|---------|-------------------------------------------|------------------------------------------------------|
| 执行顺序 | 配置文件路径 | 生效范围 | 核心作用 | 内部自动执行的动作 |
| 1 | /etc/profile | 全系统所有用户 | 系统级全局登录配置,所有用户登录必执行,设置全系统通用环境变量、登录初始化命令 | /etc/profile.d/ 目录下所有 .sh 脚本,按文件名顺序挨个执行 |
| 2 | ~/.bash_profile (当前用户家目录) | 当前用户 | 单个用户的个人登录配置,仅当前用户登录时执行,设置用户专属环境变量、登录初始化命令 | 系统默认自带代码:如果 ~/.bashrc 文件存在,自动执行 source ~/.bashrc |
| 3 | ~/.bashrc (当前用户家目录) | 当前用户 | 单个用户的个人非登录配置,设置用户专属的 Shell 属性、别名、函数 | 系统默认自带代码:自动执行 source /etc/bashrc |
| 4 | /etc/bashrc | 全系统所有用户 | 系统级全局非登录配置,设置全系统统一的 Shell 默认属性、全局变量、函数 | 无 |
我们在系统级别的环境变量里添加了一个永久的环境变量时,/etc/bashrc里添加了echo "你好,天才",切换到别的用户会看到两次输出

就是因为我们环境变量的执行顺序,再上表中,第一次执行时,里面的配置规则,让我们执行了一次我们输入的内容,第四次执行时,执行了我们输入内容的本身,所以看到两次
非登录式 Shell 不会执行 /etc/profile、~/.bash_profile,也就是表中的最后两个,

显示环境变量
echo $HOME # 用户的家目录
echo $UID # 当前用户的UID,相当于id --u
echo $PWD # 当前工作目录的绝对路径名
echo $SHELL # 当前SHELL
echo $USER # 当前用户
printf "$HOME" # printf是一个格式化打印输出工具
显示默认环境变量
env
set可以显示系统环境变量和局部变量
set

取消环境变量unset
unset 只能删当前 shell 内存里的变量,不能直接删掉配置文件里的代码
unset name #清空内存变量
source /etc/bashrc #重新加载系统配置,NAME变回123
echo $name

新开登录 shell,又会先 123 再被 456 覆盖
设置shell的登陆提示
1,在/etc/motd里增加提示的字符串


2,是在/etc/profile.d/下面增加如下脚本
echo "bibilabu"


单引号与双引号的区别

把命令执行结果赋值给变量
变量=命令
变量=$(命令)
Shell中特殊且重要的内置变量
|---------|-----------------------------------------------------|
| 变量 | 含义 |
| 0 | 当前脚本的文件名。 |
| n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 1,第二个参数是 2。 |
| # | 传递给脚本或函数的参数个数。 |
| * | 传递给脚本或函数的所有参数,参数是一个整体,每一个变量参数之间以空格隔开。 |
| @ | 传递给脚本或函数的所有参数。参数是独立的,也是全部输出 |
| ? | 上个命令的退出状态或函数的返回值 |
| $$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
看一下**$n(n≥1)**的效果

bash 脚本 文件后面跟着的数字/文字 = 按顺序赋值给$1 $2 $3 $4...

想要做数值加法:echo $(( $1+$2 )),执行后输出13
$?
输出0表示上条命令执行成功

\*和@
$*是把所有参数当做一个整体,参数之间空格隔开
$@虽然也可以接收所有参数,但是其每个参数保存时依然是独立的


for 变量 in 一堆内容
do
每次循环把【一堆内容里的一项】放进变量,执行命令
done
i = 容器,轮流装每一个参数,随便叫什么都行,这是自定义的一个临时变量
for i in "$*"
把所有参数打包成【1 个完整字符串】,只循环 1 次
for i in "$@"
保留原有参数分界,每个参数独立,原样分开循环
Shell运算符
+ 加
- 减
* 乘
/ 除
% 求余数

++ 与 -- 运算符
++就是在变量本身+1,--就是在变量本身-1

单纯使用时,放在前面或者后面没有区别
echo 变量名++ 或者 变量名--
echo ++变量名 或者 --变量名
参与运算+-*/=%,++--放前面还是后面就有了区别
x=10
let y=++x 先加1再运算

x=10
let y=x++ 先运算再+1

