Shell 脚本的介绍
常见快捷键
快捷键 | 描述 |
Ctrl + A | 将光标移至行首 |
Ctrl + E | 将光标移至行尾 |
Ctrl + C | 终止操作 |
Ctrl + D | 一般为结束输入 |
Ctrl + M | 回车 |
Ctrl + U | 删除光标至行首的所有内容 |
Ctrl + W | 删除光标前面的一个单词(空格分隔) |
Ctrl + S | 挂起,冻结终端 |
Ctrl + Q | 解除冻结终端 |
Alt + . | 使用前一个命令的最后一个词 |
方向键(上下键) | 历史记录 |
Tab键 | 补齐命令,选项、路径与文件名(补齐选项需要bash-completion软件包) |
安装新的解释器
[root@shell ~]# yum -y install ksh
[root@shell ~]# ksh
![]()
bash的优点
支持历史记录,快捷键,tab,管道,重定向,别名
标准的的脚本构成
1、声明解释器
#!/bin/bash
2、注释脚本功能,变量含义,每个步骤要解决的问题,等... ...
3、具体代码
例:
[root@shell]# cd /shell
[root@shell shell]# vim test.sh
#!/bin/bash
#这是一个测试脚本
echo abc
[root@shell shell]# ll test.sh
-rw-r--r--. 1 root root 47 Jul 16 15:27 test.sh
[root@shell shell]# chmod u+x test.sh //给用户执行权限,执行脚本
[root@shell shell]# ll test.sh
-rwxr--r--. 1 root root 47 Jul 16 15:27 test.sh
[root@shell shell]# /shell/test.sh
abc
或
[root@shell shell]# ./test.sh
abc
注:脚本执行方式:
1、赋予x执行权限,然后使用绝对或相对路径运行该文件
2、使用解释器直接执行脚本,即使没有x权限也可以,调用bash解释器来解释脚本(也可以用别的解释器),新开启解释器进程执行脚本,脚本执行完毕后,新开启的解释器自动退出
[root@shell /]# chmod u-x /shell/test.sh
[root@shell /]# ll /shell/test.sh
-rw-r--r--. 1 root root 47 Jul 16 15:27 /shell/test.sh
[root@shell /]# bash /shell/test.sh
abc
[root@shell /]# sh /shell/test.sh
abc
[root@shell /]# ksh /shell/test.sh
abc
3、使用source命令执行脚本,也可以没有x权限,(用当前默认释器来解释脚本),不开启新解释器,使用当前解释器执行脚本
[root@shell /]# source /shell/test.sh
abc
source可以简写为 .
[root@server opt]# . test2.sh //也可以执行
注:脚本执行方式,调用解释器执行和source执行的区别
[root@shell ~]# vim /shell/test2.sh
#!/bin/bash
mkdir abc
cd abc
[root@server opt]# source test2.sh
[root@server abc]# //使用source命令执行,使用当前解释器来执行命令,命令执行完会停留在当前状态
[root@server abc]# cd ..
[root@server opt]# ls
abc test2.sh
[root@server opt]# rm -rf abc
[root@server opt]# bash test2.sh
[root@server opt]# ls
abc test2.sh //调用新的解释器执行,是在当前解释器上又新开了一个解释器,新的解释器执行完命令后会自动结束进程,而默认解释器的状态是在/opt下,所以执行结果显示会在/opt,其实脚本已经被新的解释器所执行,使用ls查看可以看见新的解释器的执行效果
编写一键部署yum脚本(test3.sh)
[root@server ~]# mkdir /etc/yum.repos.d/repo
[root@server ~]# cd /etc/yum.repos.d/
[root@server yum.repos.d]# mv *.repo repo //将所有yum源放入repo中,以免影响下面脚本
[root@server yum.repos.d]# ls
repo
[root@server ~]# cd /opt
[root@server opt]# vim test3.sh
#!/bin/bash
echo "[base]
name=ceshi
baseurl=file:///mnt/
enable=1
gpgcheck=0" > /etc/yum.repos.d/ceshi.repo
mount /dev/cdrom /mnt
[root@server opt]# bash test3.sh
[root@server opt]# cd /etc/yum.repos.d/
[root@server yum.repos.d]# ls
ceshi.repo repo
[root@server yum.repos.d]# yum repolist
编写一键部署vsftpd脚本(test4.sh)
[root@server ~]# cd /opt
[root@server opt]# vim test4.sh
#!/bin/bash
yum -y install vsftpd &> /dev/null
systemctl start vsftpd
systemctl enable vsftpd
[root@server opt]# bash test4.sh
[root@server ~]# systemctl stop firewalld //脚本写完关闭防火墙测试服务
#############################################################################
Shell脚本中的变量
常量:固定不变的内容(以上脚本所运用的都是变量)
变量:存储可能会发生变化的内容,增加脚本的灵活性
变量类型
— 自定义变量
— 环境变量
— 位置变量
— 预定义变量
自定义变量
— 变量名称必须使用字母,数字,下划线,不能以数字开头,不能使用特殊符号
[root@server ~]# a=10
[root@server ~]# echo $a
10
[root@server ~]# a=100
[root@server ~]# a=abc
[root@server ~]# echo $a
abc //若赋予变量多个值,最后只输出最后一次赋值的结果,后面的值将会覆盖前面的
[root@server ~]# unset a //取消自定义变量的定义
[root@server ~]# echo $a //因为取消变量a的定义,所以输出结果为空
[root@server ~]# a=10
[root@server ~]# echo ${a}RMB //用{}将变量括起来,就不会将变量与常量混淆
10RMB
######################################################################
环境变量:系统定义好的变量
[root@server ~]# env //显示所有的环境变量
[root@server ~]# env | grep SHE //可以结合管道进行查询
SHELL=/bin/bash
GNOME_SHELL_SESSION_MODE=classic
[root@server ~]# set //查看所有变量
[root@server ~]# abcd=88888888
[root@server ~]# set | grep abcd
abcd=88888888
— 常见环境变量
[root@server ~]# echo $USER
root
[root@server ~]# echo $UID
0
[root@server ~]# echo $HOME
/root
[root@server ~]# echo $SHELL
/bin/bash
— 不常见环境变量
[root@server ~]# echo $PS1 //一级提示符
[\u@\h \W]\$
[root@server ~]# echo $PS2 //二级提示符
> //换行,在未输完命令的后面加 \
[root@server ~]# echo $PATH //命令程序存放路径
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin //当执行某个命令时,Linux 会依照 PATH 中包含的目录依次搜寻该命令的可执行文件,一旦找到,即正常执行;反之,则提示无法找到该命令。路径用:分开
[root@server opt]# vim test1.sh
#!/bin/bash
echo abc
[root@server opt]# chmod u+x /opt/test1.sh
[root@server opt]# ./test1.sh
abc
[root@server opt]# test1.sh
bash: test1.sh: command not found...
将test1.sh放入环境变量PATH中任意一路径中,以后执行此脚本就不需要加路径,就可以直接执行
[root@server opt]# cp test1.sh /usr/local/sbin/
[root@server opt]# test1.sh
abc
注:若随便修改环境变量PATH,将导致无法找到系统命令
[root@server opt]# PATH= //将环境变量定义为空,系统将找不到命令
bash: sed: No such file or directory
[root@server opt]# ls
bash: ls: No such file or directory
bash: sed: No such file or directory
[root@server opt]# touch abc
bash: touch: No such file or directory
bash: sed: No such file or directory
########################################################################
位置变量($1 $2 $3 .. ..)
预定义变量($0 $$ $? $# $* $!)
[root@server ~]# cd /opt
[root@server opt]# vim test5.sh
#!/bin/bash
echo $1 //脚本后跟的第一个参数
echo $2 //脚本后跟的第二个参数
echo $3 //脚本后跟的第三个参数
echo $$ //显示当前程序运行时的进程号(进程号为随机的)
echo $# //显示所有位置变量的个数,下面有三个参数,所以为3
echo $* //显示所有的位置变量,下面参数为a,b,c,所以输出结果为a b c
echo $? //显示上一条命令的状态返回值,0是正常;非0是异常
echo $0 //显示执行脚本的名称
echo $! //显示最后一条放在后台的程序的进程号,无后台进程,所以为空
[root@server opt]# bash test5.sh a b c //输出结果对应上面脚本的变量
a
b
c
10667
3
a b c
0
test5.sh
(空)
[root@server ~]# sleep 1000 & //将sleep 1000放到后台执行
[1] 10955 //进程号为10955
[root@server ~]# echo $! //查看后台进程的进程号
10955
利用位置变量编写创建账户配置密码的脚本(test6.sh)
[root@server ~]# cd /opt
[root@server opt]# vim test6.sh
#!/bin/bash
useradd $1
echo $2 | passwd --stdin $1
[root@server opt]# bash test6.sh dc 123456
Changing password for user dc.
passwd: all authentication tokens updated successfully.
#######################################################################
变量的扩展应用
"" :界定范围
'' :界定范围,可以屏蔽特殊符号
`` (反撇号):获取命令的结果,而不是命令本身
$()与``(反撇号)效果一致
[root@server ~]# cd /mnt
[root@server mnt]# touch a b //创建2个文件
[root@server mnt]# ll
-rw-r--r--. 1 root root 0 Jul 16 07:53 a
-rw-r--r--. 1 root root 0 Jul 16 07:53 b
[root@server mnt]# touch "a b" //创建1个文件
[root@server mnt]# ll
-rw-r--r--. 1 root root 0 Jul 16 07:53 a
-rw-r--r--. 1 root root 0 Jul 16 07:53 a b
-rw-r--r--. 1 root root 0 Jul 16 07:53 b
[root@server mnt]# touch 'c d' //创建1个文件
[root@server mnt]# ll
-rw-r--r--. 1 root root 0 Jul 16 07:53 c d
[root@server ~]# a=10
[root@server ~]# echo $a
10
[root@server ~]# echo "$a" //显示变量的值(内容)
10
[root@server ~]# echo '$a' //显示$a,$是特殊符号,功能被屏蔽
$a
[root@server ~]# d=date //定义变量d,内容是date
[root@server ~]# echo $d
date
[root@server ~]# d=`date` //定义变量d,内容是date命令执行的结果
[root@server ~]# echo $d
Fri Jul 16 07:58:20 PDT 2021
[root@server ~]# d=$(date)
[root@server ~]# echo $d
Fri Jul 16 07:58:20 PDT 2021
使用read命令从键盘读取变量值
read的基本用法:执行后会等待并接收用户输入,并赋值给变量;可以结合选项[-p]给出提示
优化创建账户配置密码的脚本(test6.sh)
[root@server ~]# cd /opt
[root@server opt]# vim test6.sh
#!/bin/bash
read -p "请输入用户名:" u
useradd $u
read -p "请输入密码:" p
echo $p | passwd --stdin $u
[root@server opt]# bash test6.sh
请输入用户名:zhangsan
请输入密码:123456
Changing password for user zhangsan.
passwd: all authentication tokens updated successfully.
stty终端显示控制
stty -echo:关闭回显功能
stty echo:恢复回显功能
优化创建账户配置密码的脚本,使得输入密码是关闭回显功能(test6.sh)
[root@server opt]# vim test6.sh
#!/bin/bash
read -p "请输入用户名:" u
useradd $u
stty -echo
read -p "请输入密码:" p
stty echo
echo $p | passwd --stdin $u
[root@server opt]# bash test6.sh
请输入用户名:lisi
请输入密码:Changing password for user lisi.
passwd: all authentication tokens updated successfully.
局部变量
定义的变量a只能在当前解释器中使用,新开一个解释器后,变量a是未定义的,所以为空
[root@server ~]# a=10
[root@server ~]# echo $a
10
[root@server ~]# bash //开启新解释器(进入子进程)
[root@server ~]# echo $a //测试,无值,因为a是局部变量
(空)
全局变量——系统将自己定义好的变量(环境变量)发布为全局变量
[root@server ~]# echo $USER
root
[root@server ~]# bash
[root@server ~]# echo $USER
root
局部变量发布为全局变量
export可以将局部变量发布为全局变量
export 变量 ——已经定义了变量
export 变量=值 ——未定义变量
export -n 变量 ——取消发布全局变量,变为局部变量
[root@server ~]# a=10
[root@server ~]# export a //a已经被定义过,对已有变量的变量,发布全局变量
[root@server ~]# echo $a
10
[root@server ~]# bash //开启新解释器(进入子进程)
[root@server ~]# echo $a //测试,有值,因为a已经成为全局变量
10
[root@server ~]# exit //退出新解释器
[root@server ~]# export b=20 //b未被定义过,创建新变量,并发布成全局变量
[root@server ~]# echo $b
20
[root@server ~]# bash //测试,有值,因为b已经成为全局变量
[root@server ~]# echo $b
20
[root@server ~]# export -n b //撤销全局变量b,恢复为局部变量
[root@server ~]# bash
[root@server ~]# echo $b //测试,无值,因为已经撤销全局变量
(空)
注:撤销全局变量必须与发布全局变量在同一个解释器内
##########################################################################
shell中的运算
expr命令——调用变量,没有改变变量本身
既有运算的能力,也有显示输出的能力(注:数字,运算符之间都必须有空格)
[root@server ~]# expr 1 + 1
2
[root@server ~]# expr 2 - 1
1
[root@server ~]# expr 2 '*' 2 // * 为特殊字符,指全部,需要屏蔽特殊含义
4
[root@server ~]# expr 2 \* 2
4
[ro ot@server ~]# expr 4 / 2 //取商(整数)
2
[root@server ~]# expr 10 % 3 //求模,取余数
1
注:
\ :转义符号,屏蔽之后的一个字符的特殊含义
'' :可以屏蔽单引号之间所有字符的特殊含义
[root@server ~]# a=10
[root@server ~]# echo $a
10
[root@server ~]# expr $a + 5
15
[root@server ~]# expr $a + $a
20
$[]与$(())——调用变量,没有改变变量本身
乘法操作*无需转义,数字与运算符之间无需空格,引用变量可省略$符号;不会显示结果,可结合echo命令输出
[root@server ~]# echo $[1+1]
2
[root@server ~]# echo $[2-1]
1
[root@server ~]# echo $[2*2] //无需使用转义字符
4
[root@server ~]# echo $[4/2]
2
[root@server ~]# echo $[5%2]
1
[root@server ~]# a=10
[root@server ~]# echo $[a+10]
20
[root@server ~]# echo $[a*a]
100
let命令
可以改变变量本身的值,不显示结果
非主流用法:
[root@server ~]# a=10
[root@server ~]# let a=a+1
[root@server ~]# echo $a
11
[root@server ~]# let a=a*2
[root@server ~]# echo $a
22
主流用法:(建议使用)
[root@server ~]# a=10
[root@server ~]# let a++ //a++(a=a+1)
[root@server ~]# echo $a
11
[root@server ~]# let a-- //a--(a=a-1)
[root@server ~]# echo $a
10
[root@server ~]# let a+=5 //a+=5(a=a+5)
[root@server ~]# echo $a
15
[root@server ~]# let a-=5 //a-=5(a=a-5)
[root@server ~]# echo $a
10
[root@server ~]# let a*=5 //a*=5(a=a*5)
[root@server ~]# echo $a
50
[root@server ~]# let a/=5 //a/=5(a=a/5)
[root@server ~]# echo $a
10
[root@server ~]# let a%=3 //a%=3(a=a%3)
[root@server ~]# echo $a
1
注:以上三种运算方法,只能整数运算,不支持小数运算
bc命令
bc为交互式命令,可以运算小数
[root@server ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1.1+1.1
2.2
1.1*1.1 //只显示小数点后1位
1.2
10/3 //商只取整数
3
scale=4 //scale定义小数点后显示的位数
10/3
3.3333
quit //退出
注:bc命令为交互式命令不能直接写入脚本
[root@server ~]# echo "1.1+1.1" | bc //使用bc进行非交互式计算,并且可以计算小数
2.2
[root@server ~]# echo "10/3" | bc //不定义小数点后面的长度,默认取整数
3
[root@server ~]# echo "scale=4;10/3" | bc //scale定义小数点后面的长度,;代表前后命令的区分
3.3333
注:若要使用bc写脚本时,必须使用echo结合管道的方式