shell脚本

把多个命令写入一个文件,让系统自动按顺序执行,就组成了Shell脚本。

顺序:如果没有指定顺序的话,那么就是 从上到下,从左到右

Shell脚本是批量命令的集合,让系统自动完成重复任务。类似Windows的.bat批处理文件,但更强大。

注意:只要是用bash脚本解析的脚步的第一行必须写:

复制代码
#!/bin/bash

脚本文件名一般以.sh结尾

运行test脚本

复制代码
bash test.sh

脚本写完需要为其增加一个执行权限

复制代码
chmod +x test.sh

来看一个简单的脚本

  1. #!/bin/bash

脚本声明,指定用 bash 解释器运行这个脚本,之前讲过的Shebang 头

  1. cd /var/log

切换工作目录到 Linux 系统日志默认目录/var/log,后面操作messages日志文件就在这个文件夹里。

  1. cat /dev/null > messages
  • /dev/null是空黑洞,cat读取空内容

  • > 覆盖重定向 :用空白内容全覆盖messages,清空整个日志原有内容

  1. 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_profilename=456覆盖了前面/etc/bashrcname=123

系统写死加载流程,永远是:

  1. 先读:/etc/profile → 连锁加载/etc/bashrc(系统全局文件,执行NAME=123,此时NAME=123
  2. 后读:~/.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
相关推荐
天一生水water1 小时前
agent教程S01-Agent 最小循环教程整理
java·服务器·网络·agent
花果山~~程序猿1 小时前
ubuntu20.4下载python3.12
linux
网络与设备以及操作系统学习使用者1 小时前
多路由设备静态路由配置详解
运维·网络·学习·华为·智能路由器
RD_daoyi1 小时前
Google SEO第四周:深度站内优化——让网站快速收录、稳定排名的硬核技术
大数据·服务器·人工智能·搜索引擎
daad7772 小时前
sitl_5760_io记录
linux·运维·服务器
XIAOHEZIcode2 小时前
进程、会话与终端——一次真实的 Linux Session 解剖
linux·后端·命令行
Albert Edison2 小时前
【Docker】镜像仓库(Registry)
运维·docker·容器
小则又沐风a2 小时前
今日算法----一篇文章学会背包问题
运维·服务器·算法
好好风格2 小时前
Scrapling:现代 Web 抓取,正在从“写选择器”走向“自适应”
linux·后端