shell概述
Shell 既是一种命令语言,又是一种程序设计语言。 Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。 Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
概念
- 将要执行的命令按顺序保存到一个文件
- 给该文件可执行权限
- 可结合各种shell控制语句完成更复杂的操作
应用场景
- 重复性操作
- 交互性任务
- 批量事物处理
- 服务运行状态监控
- 定时任务执行
如果有人爆破我的机器就可以查看
[root@localhost ~]# vim /var/log/secure
Aug 17 02:14:23 localhost polkitd[727]: Loading rules from directory /etc/polkit-1/rules.d
Aug 17 02:14:23 localhost polkitd[727]: Loading rules from directory /usr/share/polkit-1/rules.d
Aug 17 02:14:24 localhost polkitd[727]: Finished loading, compiling and executing 8 rules
Aug 17 02:14:24 localhost polkitd[727]: Acquired the name org.freedesktop.PolicyKit1 on the system bus
Aug 17 02:14:27 localhost sshd[1100]: Server listening on 0.0.0.0 port 22.
shell的作用
-
Shell就是命令行工具的胶水,没有任何语言能像Shell一样方便地将一大堆命令行工具组合起来。原则上来说,Shell做什么都可以,但显然它最适合的是自动化,因为只需要将你原来手动敲的命令都复制到一个文件里面就行了。
-
Shell跟标准的编程语言区别很大,它基本上是一个面向字符串的编程语言,组合用好awk/sed/grep,偶尔配合eval,有时候会发挥奇效,但也有可能原地爆炸。可以跟Python之类的其他语言配合起来,比如某个复杂的功能使用一个Python脚本来实现,然后在shell中调用这个脚本实现较复杂的功能;或者反过来,在Python脚本中调用外部的Shell脚本来提高自动化的效率,也是可以的。
- 用户输入指令以后交给shell处理
- shell收到指令以后将命令转换成二进制而言交给内核处理
- 内核收到指令后调用相关的内核交给系统硬件进行处理
Shcll(壳程序)是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个"命令解释器""角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。
Linux中内置的shell
[root@localhost ~]# vim /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
常用的shell
bash //基于GNU的框架下发展出的shell
csh //语法类似于c语言的shell
tcsh //整合了 csh 提供更多的功能
sh //已经被bash所替换
nologin //奇怪的shell 这个shell可以让用户无法登陆主机
bash (/bin/bash) 是目前大多数Linux版本采用的默认shell
要查看用户使用哪一个shell可以查看(/etc/passwd)
[root@localhost ~]# vim /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
shell脚本的作用
脚本(script)就是包含一系列命令的一个文本文件。Shell 读取这个文件,依次执行里面的所有命令,就好像这些命令直接输入到[命令行]一样。所有能够在命令行完成的任务,都能够用脚本完成。
脚本的好处是可以重复使用,也可以指定在特定场合自动调用,比如系统启动或关闭时自动执行脚本。
- 自动化运维
- 批量化重复操作可以编写脚本结合计划任务自动周期性运行
- 减轻管理员工作量
- 提高处理文本文件的速度
- 避免配置出错
扩充了解:
shell + Python
shell 可针对Linux系统做自动化运维和状态监控
Python 可针对通过ARI接口对 应用程序 做数据的收集 统计和分析
编程语言(解释性语言)
强类型
命令:int string
代表语言:C C++ JAVA CO
弱类型
代表语言:shell Python(外置)
shell脚本的构成
-
脚本申明(申明解释器) :第一行开头 “#!/bin/bash”,表示此行以下的代码语句是通过/bin/bash程序来执行。还有其他类型的解释器,比如 #/usr/bin/python、#!/usr/bin/expect 。
-
注释信息: 以“#”开头的语句表示为注释信息,被注释的语句在脚本运行时不会被执行。
-
可执行语句: 如echo命令,用于输出“ ”之间的字符串
Shell 脚本代码 申明解释器 #!/bin/bash 或省略
Python 代码 必须申明解释器 #!/usr/bin/python 或 #!+ python执行文件的其他路径
[root@localhost ~]# vim demol.sh
#!/bin/bash
#desc: this is a simple shell script <2022823>
echo "hello world"
要执行脚本就要加上权限
[root@localhost data]# chmod +x demol.sh
[root@localhost data]# ll
总用量 4
-rwxr-xr-x. 1 root root 98 8月 23 23:21 demol.sh
执行脚本 ./
[root@localhost data]# ./demol.sh
hello world
*[root@localhost data]# vim demol.sh [root@localhost data]# ls demol.sh *
尾部是.sh的文件都是shell脚本
写脚本
- 将要执行的命令按顺序一一列出,保存到一个文本文件,最后自动执行。
- 执行脚本需要x权限,也可以使用绝对路径来执行。
- 可结合各种Shell控制语句以完成更复杂的操作。
[root@localhost data]# vim demol.sh
#!/bin/bash
#desc:this si a simple shell script <2022823>
cd /boot //切换目录
echo "当前所在目录为:" //输出字符串内容
pwd //显示当前所在目录的路径
echo"其中以vml开头的文件有:" //输出字符串内容
ls -lh vml* //输出以vml开头的文件
~
添加权限
[root@localhost data]# vim demol.sh
[root@localhost data]# rm -rf demlo.sh
[root@localhost data]# ll
总用量 4
-rw-r--r--. 1 root root 98 8月 23 23:21 demol.sh
[root@localhost data]# chmod +x demol.sh
[root@localhost data]# ll
总用量 4
-rwxr-xr-x. 1 root root 98 8月 23 23:21 demol.sh
执行命令
执行命令可以用两种方式去执行
绝对路径:/data/demol.sh 相对路径:./demol.sh
[root@localhost data]# pwd
/data
[root@localhost data]# /data/demol.sh //绝对路径执行
当前所在目录为:
/boot
-rwxr-xr-x. 1 root root 5.7M 8月 17 02:12 vmlinuz-0-rescue-a0b3252dfe4f4ab4b25084b31120b5e4
-rwxr-xr-x. 1 root root 5.7M 8月 23 2017 vmlinuz-3.10.0-693.el7.x86_64
/data/demol.sh:行8: /root: 是一个目录
[root@localhost data]# /root/data/demol.sh
-bash: /root/data/demol.sh: 没有那个文件或目录
[root@localhost data]# ./demol.sh //相对路径执行
当前所在目录为:
/boot
-rwxr-xr-x. 1 root root 5.7M 8月 17 02:12 vmlinuz-0-rescue-a0b3252dfe4f4ab4b25084b31120b5e4
-rwxr-xr-x. 1 root root 5.7M 8月 23 2017 vmlinuz-3.10.0-693.el7.x86_64
./demol.sh:行8: /root: 是一个目录
如果没有执行权限是无法执行脚本的
[root@localhost data]# chmod -x demol.sh
[root@localhost data]# ./demol.sh
-bash: ./demol.sh: 权限不够
[root@localhost data]# ll
总用量 4
-rw-r--r--. 1 root root 176 8月 23 23:36 demol.sh
创建shell脚本
#!/bin/bash 申明解释器
#xxxxx 坐脚本的注释信息
xxxxxx 运行代码
运行脚本
1.会在脚本的子shell环境中执行脚本的代码
使用绝对路径或者相对路径指定脚本的路径运行,要求脚本必须要有执行权限 X
指定shell程序来执行解释运行脚本
bash 脚本文件
sh
2.会在当前的shell环境中执行脚本里的代码操作,也就是脚本中的代码或者命令会影响当前shell
source 脚本文件环境
重定向与管道操作
管道操作
将管道符号*|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道。
Ps aux |wc -l
[root@localhost ~]# ps aux |wc -l //统计进程数量\
154
ss -ntap | grep 22 //查看22端口是否开启
echo "abc123"|passwd --stdin lisi //非交互式设置用户密码
如果管道符号右边是一定需要执行对象的命令,管道符号后面要有 xaegs 命令来传递执行参数
交互式硬件设备
标准输入:从该设备接收用户输入的数据
标准输出:通过该设备向用户输出数据
标准错误:通过该设备报告执行出错信息
| 类型 | 设备文件 | 文件描述编号 | 默认设备 |
|---|---|---|---|
| 标准输入 | /dev/stbin | 0 | 键盘 |
| 标准输出 | /dev/stdout | 1 | 显示器 |
| 标准错误输出 | /dev/stdrr | 2 | 显示器 |
输入重定向
| 符号 | 作用 |
|---|---|
| 命令 < 文件 | 从指定的文件读取文件,而不是从键盘输入 |
| 命令 << 分界符 | 从标准输入中读入,直到遇见分界符才停止 |
| 命令 < 文件1 > 文件2 | 将文件1 作为命令的标准输入并将标准输出到文件2 |
输出重定向
| 符号 | 作用 |
|---|---|
| 命令 > 文件 | 将标准输出结果保存到指定的文件中(覆盖原有内容) |
| 命令 >> 文件 | 将标准输出结果追加到指定的文件尾部 |
| 命令 2> 文件 | 将错误输出信息保存到指定文件中(覆盖原有内容) |
| 命令 2>> 文件 | 将错误输出信息追加到指定文件尾部 |
| 命令 > 文件 2>&1 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
| 命令 2> 文件 1>&2 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
| 命令 &> 文件 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
| 命令 >& 文件 | 混合输出,将标准输出与错误输出保存到文同一个文件中 |
&表示混合,&> 和 >& 都表示将标准输出和错误输出重定向到同一个文件。
shell变量的作用
变量的作用
- 用来存放系统和用户需要使用的特定参数(值)
- 变量名:使用固定的名称,由系统预设或用户定义
- 变量值:能够根据用户设置、系统环境的变化而变化
变量的类型
- 自定义变量:由用户自己定义、修改和使用
- 特殊变量:环境变量,只读变量,位置变量,预定义变量
定义一个新的变量
- 变量名以字母或者下划线开头,区分大小写,建议全大写
格式 : 变量名=变量值
$引用变量名输出变量值
[root@localhost ~]# a=1
[root@localhost ~]# A=2
[root@localhost ~]# echo $a
1
[root@localhost ~]# echo $A
2
[root@localhost ~]# abc123=123
[root@localhost ~]# 123=12 //必须用字母或者下划线开头
bash: 123=12: 未找到命令...
变量的值会取它最后一个赋予的值
=号代表赋值
[root@localhost ~]# a=1
[root@localhost ~]# a=2
[root@localhost ~]# a=3
[root@localhost ~]# echo $a
3
[root@localhost ~]# name=wl
[root@localhost ~]# class=10
[root@localhost ~]# echo $name $class //同时输出
wl 10
[root@localhost ~]# echo $name$class //合并输出
wl10
[root@localhost ~]# echo $name10
系统会把name10当做一个变量名,没有定义所以输出什么都没有
[root@localhost ~]# echo $name"10" //可以用""号单独扩出来
wl10
[root@localhost ~]# echo ${name}10 //使用{}括号括起来也是可以实现
wl10
想在变量后面加上空格那么一定要加""号来实现
否则无法实现
[root@localhost ~]# name=wangwu
[root@localhost ~]# echo $name
wangwu
[root@localhost ~]# name=wang wu
bash: wu: 未找到命令...
[root@localhost ~]# name="wang wu"
[root@localhost ~]# echo $name
wang wu
如果在没有$符号的情况下'' "" 两个符号是没有区别的
如果有$符号的情况下'' "" 两个符号是有去别的
''只会把$符号当做一个普通的符号去使用
""会应用后面的字符串当做一个量变,应用变量的值
[root@localhost ~]# a='$name'
[root@localhost ~]# echo $a
$name
[root@localhost ~]# a="$name"
[root@localhost ~]# echo $a
wang wu
想给read有提示信息有两种方式
[root@localhost ~]# vim 1.sh
#!/bin/bash //申明解释器
read -p "提示信息" ab
echo "ab变量的值为:"
echo $ab
[root@localhost ~]# sh 1.sh
提示信息123
ab变量的值为:
123
[root@localhost ~]# vim 1.sh
#!/bin/bash
echo -n "请输入变量值"
read ab
echo "ab变量的值为:"
echo $ab
[root@localhost ~]# sh 1.sh
请输入变量值123132
ab变量的值为:
123132
赋值时使用引号
- 双引号:允许通过$符号引用其他变量值
- 单引号:禁止引用其他变量值,$视为普通字符
- 反撇号:命令替换,提取命令执行后的输出结果
整数变量的运算
格式
expr 变量1 运算符 变量2 [运算符 变量3
常用的运算符
| 加法运算 | + |
|---|---|
| 减法运算 | - |
| 乘法运算 | \ * |
| 除法运算 | / |
| 求模(取余)运算 | % |
[root@localhost ~]# expr 5 / 2
2
[root@localhost ~]# expr 5 % 5
0
[root@localhost ~]# echo $((2+5))
7
[root@localhost ~]# echo $((5-1))
4
[root@localhost ~]# echo $[ 5+2]
7
[root@localhost ~]# echo $[5/5]
1
[root@localhost ~]# echo $[5%2]
1
[root@localhost ~]# let i=5\*2
[root@localhost ~]# echo $i
10
[root@localhost ~]# let i++
[root@localhost ~]# echo $i
11
[root@localhost ~]# let i--
[root@localhost ~]# echo $i
10
[root@localhost ~]# let i+=2
[root@localhost ~]# echo $i
12
[root@localhost ~]# let i-=2
[root@localhost ~]# echo $i
10
[root@localhost ~]# echo "1.1+1.2" | bc
2.3
想指定输出多少为小数
[root@localhost ~]# echo "scale=2;5.1/2.1" | bc
2.42
[root@localhost ~]# echo "scale=3;5.1/2.1" | bc
2.428
混合运算
[root@localhost ~]# echo "scale=2;3/(5.8+1.5)*5" | bc
2.05
awk运算
[root@localhost ~]# awk 'BEGIN{print 4.1+1.1}'
5.2
总结运算方法:
常用的运算表达式:
i=$(expr 12 \ * 5 )
i=$((1 * 5 ))
i=$[12 *1]
let i=1*5
i++ 相当于 i=i+1]
i-- 相当于 i=i-1]
i+=2 相当于 i=i+2]
四种整数运算
expr 数值或者变量 运算符 数值或者变量
$(( 数值 运算符 数值 ))
$[数值 运算符 数值]
let变量=<数值>运算符<数值>
两种浮点运算
echo "浮点运算表达式" | bc
awk 'BEGIN {print 浮点运算表达式}'
变量
环境变量
环境变量由系统提前创建,用于设置用户的工作环境
常用的环境变量
[root@localhost ~]# env
HOSTNAME=localhost.localdomain //获取当前主机的主机名
SHELL=/bin/bash //可以查看当前的shell环境
HISTSIZE=1000 //当前的历史条目数
USER=root //当前的用户名
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin //想要系统能识别命令就要放到这些路径中
PWD=/root //变量 也能活得当前所在的目录
LANG=zh_CN.UTF-8 //当前使用的语言以及字符集
| 命令 | 作用 |
|---|---|
| echo$PATH | 查看当前搜索路径 |
| PATH="$PATH:/root" | 将/root目录添加到搜索路径 |
| export PATH="$PATH:/root" | 输出为全局环境变量 |
环境变量的全局配置文件为/etc/profile
在此文件中定义的变量作用于所有用户
每个用户还有自己的独立配置文件
(~/.bash_profile)可以用来长期变更或者设置某个环境变量
[root@localhost ~]# vim /root/.bash_profile
export HISTSIZE=200
修改root用户的历史命令记录条数
echo $HISTSIZE
aource /root/.bash_profile
读取并执行文件中的设置
echo $H工STSIZE
readonly命令设置只读变量
product-beTet
readonly product //设置为只读变最
echo $product
product-accp //只读变量不可以被电新赋值
unset product //只读变量不可以被删除,unset命令用于删除变量
位置变量
当执行命令行操作时,第一个字段表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量。 1-{10}
#!/bin/bash
read -p "请输入第一个参数:" num1
read -p "请输入第二个参数:" num2
sum=$[num1 + num2]
echo "sum的值为 $sum"
[root@localhost ~]# sh 2.3.sh
请输入第一个参数:20
请输入第二个参数:50
sum的值为 70
#!/bin/bash
echo "第一个位置变量的值为:$1 "
echo "第二个位置变量的值为:$2 "
echo "第三个位置变量的值为:$3 "
echo "第四个位置变量的值为:$4 "
echo "第五个位置变量的值为:$5 "
echo "第六个位置变量的值为:$6 "
echo "第七个位置变量的值为:$7 "
echo "第八个位置变量的值为:$8 "
echo "第九个位置变量的值为:$9 "
echo "第十个位置变量的值为:${10} "
echo "第十一个位置变量的值为:${11} "
echo "第十二位置变量的值为:${12} "
[root@localhost ~]# sh 2.1.sh 10 20 30 40 50 60 70 80 90 100 110 120
第一个位置变量的值为:10
第二个位置变量的值为:20
第三个位置变量的值为:30
第四个位置变量的值为:40
第五个位置变量的值为:50
第六个位置变量的值为:60
第七个位置变量的值为:70
第八个位置变量的值为:80
第九个位置变量的值为:90
第十个位置变量的值为:100
第十一个位置变量的值为:110
第十二位置变量的值为:120
预定义变量
$*``$@ 代表命令或脚本要出的参数
"$*":把所有参数看成以空格分隔的一个字符串整体(单字符串)返回,代表"2 $3".....
"$@":把各个参数加上双引号分割成N份参数列表,每个参数作为一个人字符串返回,代表"2" "$3"....
#!/bin/bash
echo "未加双引号时....."
echo $*
echo $@
~
[root@localhost ~]# sh 3.1.sh 10 20 30
未加双引号时.....
10 20 30
10 20 30
#!/bin/bash
echo "未加双引号时....."
echo " $*"
echo "$@"
echo "加双引号时....."
echo '$* 为'
for i in "$*"
do
echo $i
done
echo '$@ 为'
for j in "$@"
do
echo $j
done
[root@localhost ~]# sh 3.1.sh 10 20 30 40 50 60
未加双引号时.....
10 20 30 40 50 60
10 20 30 40 50 60
加双引号时.....
$* 为
10 20 30 40 50 60
$@ 为
10
20
30
40
50
60
$0:表示当前执行的脚本或命令的名称
$#:表示命令或脚本要处理的参数个数
#?:表示前一条命令或脚本执行后的返回状态码
返回值为0表示执行正确
返回值非0值为表示执行初夏异常
也常被用于shell脚本中retutn退出函数并返回的退出值
列子:
[root@localhost ~]# echo $? //返回值为0表示执行正确
0
[root@localhost ~]# ls a111
ls: 无法访问a111: 没有那个文件或目录
[root@localhost ~]# echo $? //返回值非0表示执行错误
2
总结
$0 脚本本身
$# 脚本后面根的所有参数个数
$* $@ 脚本后面跟的所有参数
"$*" 会把脚本后面跟的所有参数当做一个整体看待
"$@" 会把脚本后面跟的所有参数看作多个以空格分隔的个体
$? 返回上一条Linux命令或者脚本执行的结果,0位执行正常,非0值为执行异常
[root@localhost ~]# date
2022年 08月 28日 星期日 18:58:56 CST
[root@localhost ~]# date --help
[root@localhost ~]# date
2022年 08月 28日 星期日 19:04:49 CST
[root@localhost ~]# date +"%y/%m/%d"
22/08/28
给定的格式FORMAT 控制着输出,解释序列如下:
%% 一个文字的 %
%a 当前locale 的星期名缩写(例如: 日,代表星期日)
%A 当前locale 的星期名全称 (如:星期日)
%b 当前locale 的月名缩写 (如:一,代表一月)
%B 当前locale 的月名全称 (如:一月)
%c 当前locale 的日期和时间 (如:2005年3月3日 星期四 23:05:25)
%C 世纪;比如 %Y,通常为省略当前年份的后两位数字(例如:20)
%d 按月计的日期(例如:01)
%D 按月计的日期;等于%m/%d/%y
%e 按月计的日期,添加空格,等于%_d
%F 完整日期格式,等价于 %Y-%m-%d
%g ISO-8601 格式年份的最后两位 (参见%G)
%G ISO-8601 格式年份 (参见%V),一般只和 %V 结合使用
%h 等于%b
%H 小时(00-23)
%I 小时(00-12)
%j 按年计的日期(001-366)
%k hour, space padded ( 0..23); same as %_H
%l hour, space padded ( 1..12); same as %_I
%m month (01..12)
%M minute (00..59)
%n 换行
%N 纳秒(000000000-999999999)
%p 当前locale 下的"上午"或者"下午",未知时输出为空
%P 与%p 类似,但是输出小写字母
%r 当前locale 下的 12 小时时钟时间 (如:11:11:04 下午)
%R 24 小时时间的时和分,等价于 %H:%M
%s 自UTC 时间 1970-01-01 00:00:00 以来所经过的秒数
%S 秒(00-60)
%t 输出制表符 Tab
%T 时间,等于%H:%M:%S
%u 星期,1 代表星期一
%U 一年中的第几周,以周日为每星期第一天(00-53)
%V ISO-8601 格式规范下的一年中第几周,以周一为每星期第一天(01-53)
%w 一星期中的第几日(0-6),0 代表周一
%W 一年中的第几周,以周一为每星期第一天(00-53)
%x 当前locale 下的日期描述 (如:12/31/99)
%X 当前locale 下的时间描述 (如:23:13:48)
%y 年份最后两位数位 (00-99)
%Y 年份
%z +hhmm 数字时区(例如,-0400)
%:z +hh:mm 数字时区(例如,-04:00)
%::z +hh:mm:ss 数字时区(例如,-04:00:00)
%:::z 数字时区带有必要的精度 (例如,-04,+05:30)
%Z 按字母表排序的时区缩写 (例如,EDT)
[root@localhost ~]# date +"%y%m%d"
220828
前一天
[root@localhost ~]# date -d "-1 day" +"%y%m%d"
220827
后一天
[root@localhost ~]# date -d "+1 day" +"%y%m%d"
220829
下个月一号
[root@localhost ~]# date -d "next-month" +"%y%m01"
220901
上个月一号
[root@localhost ~]# date -d "last- month" +"%Y%m01"
20220701
[root@localhost ~]# date -d "-1 month" +"%Y%m01"
20220701
一个星期后的日期
[root@localhost ~]# date -d "+1 week" +"%Y%m%d"
20220904
两个星期以后的日期
[root@localhost ~]# date -d "+2 week" +"%Y%m%d"
20220911