一、Shell编程概述
1.Shell脚本的概念
将要执行的命令按顺序保存到一个文本文件,给该文件可执行权限,可结合各种shell控制语句以完成更复杂的操作。
2.Shell脚本的应用场景
重复性操作
交互性任务
批量事务处理
服务运行状态监控
定时任务执行
…
3.Shell的作用-(命令解释器)
介于系统内核与用户之间,负责解释命令行
4.Linux系统中支持的shell
[root@localhost1 ~]#cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh
bash(bin/nash)是大多linux版本默认的shell
二、Shell编程规范
1.编写Shell脚本规范步骤
-
创建脚本文件:首先创建一个.sh 为后缀的文件
-
脚本申明解释器 :开头 #!/bin/bash 表示此行以下的代码语句是通过 /bin/bash 程序来解释的#!/bin/bash为默认解释器,还有其它类型的解释器,如# !/usr/bin/python,#! /usr/bin/expect
-
注释信息:# 开头的语句为注释信息,可以在代码编写前简介此脚本(如时间、作者、作用等信息)
-
可执行语句:开发者使用shell编写的脚本,能够实现某个特定的任务
//编写 first.sh 脚本文件
[root@localhost1 ~]#vim first.sh
#!/bin/bash
#这是我的第一个脚本文件,用于输出 hello world
echo "hello world"
2.Shell脚本执行方法
(1)以绝对路径执行(需要赋予脚本文件执行权限)
[root@localhost1 ~]#chmod a+x first.sh
[root@localhost1 ~]#/root/first.sh
hello world
(2)指定shell解释器运行脚本(不需要赋予脚本文件执行权限)
[root@localhost1 ~]#bash first.sh
hello world
[root@localhost1 ~]#sh first.sh
hello world
(3)source 脚本文件 或 . 脚本文件 (会使用当前shell环境运行)
[root@localhost1 ~]#source first.sh
hello world
[root@localhost1 ~]#. first.sh
hello world
3.脚本错误种类
命令错误:命令出错不会影响接下来的命令继续
语法错误:会影响接下来的命令继续
逻辑错误:逻辑有问题需要重新编写
检查代码正确性
[root@localhost1 ~]# bash -n 脚本名称 //检查语法错误
[root@localhost1 ~]# bash - -x 脚本名称 //检查逻辑错误
4.管道符与重定向的使用
标准输入与标准输出
由于Shell脚本“批量处理”的特殊性,其大部分操作过程位于后台,不需要用户进行干预,因此要学会提取、过滤执行信息变得十分重要,所以我们需要重定向和管道。
(1)管道符 “ | ”
作用:将管道符号“|"左侧的命令输出的结果,作为右侧命令的输入(处理对象)
同一行命令中可以使用多个管道符
//过滤80端口的信息
[root@localhost1 ~]#ss -nltp | grep 80
LISTEN 0 128 [::]:80 [::]:* users:(("httpd",pid=4308,fd=4),("httpd",pid=4307,fd=4),("httpd",pid=4306,fd=4),("httpd",pid=4305,fd=4),("httpd",pid=4304,fd=4),("httpd",pid=4303,fd=4))
//统计系统进程数(需要-1)
[root@localhost1 ~]#ps aux |wc -l
240
//统计/etc/下以.conf结尾的文件数量
[root@localhost1 ~]#find /etc/ -name *.conf -type f |wc -l
392
(2)重定向
//将123abc重定向输出到zspasswd.txt文件中
[root@localhost1 ~]#echo "123abc" > zspasswd.txt
//将zspasswd.txt中的内容重定向输入到前一个命令的标准输入中(首先关闭selinux,可以更改密码)
[root@localhost1 ~]#setenforce 0
[root@localhost1 ~]#passwd --stdin zhangsan < zspasswd.txt
更改用户 zhangsan 的密码 。
passwd:所有的身份验证令牌已经成功更新。
//将1234567890 重定向追加到zspasswd.txt文件中
[root@localhost1 ~]#echo 1234567890 >> zspasswd.txt
[root@localhost1 ~]#cat zspasswd.txt
123abc
1234567890
//将标准错误输出重定向覆盖到zspasswd.txt文件中
[root@localhost1 ~]#ausdbcabuewu 2> zspasswd.txt --输入乱码,使系统显示标准错误输出,在重定向覆盖此文件
[root@localhost1 ~]#cat zspasswd.txt
bash: ausdbcabuewu: 未找到命令...
三、Shell变量
1.变量的作用
变量是用来临时保存数据的,并且该数据时可以变化的,任何一个语言都离不开变量,如果某个内容需要多次使用并且会重复出现,这样就可以使用变量了,如果需要修改直接修改变量就可以了。
2.变量命名要求
- 区分大小写
- 只能以字母或下划线“_”开头
- 命名只能使用字母、数字和下划线“_”组成
3.常用命名格式
- 驼峰:FirstName
- 小驼峰:firstName
- 下划线:first_name
4.Shell变量的类型
- 自定义变量:由用户自己定义,修改和使用
- 特殊变量:环境变量、只读变量、位置变量、预定义变量
5.自定义变量的方法
(1)直接赋值
[root@localhost ~]# 变量名=变量值
注: 如果定义变量值中间有空格需要用单、双引号引起来;
两边不可以有空格
[root@localhost1 ~]#a=123
[root@localhost1 ~]#echo $a
123
[root@localhost1 ~]#A=456
[root@localhost1 ~]#echo $A
456
[root@localhost1 ~]#test='hello world'
[root@localhost1 ~]#echo $test
hello world
赋值时使用引号的效果
[root@localhost ~]# 变量名=“xxxx” // 双引号——允许通过$符号引用其他变量值
变量名=‘xxxx’ //单引号——禁止引用其他变量, $ 原样显示
变量名=xxxx
//反撇号——命令替换,提取命令执行后的输出结果命令
和$(命令)作用相同
//双引号效果
[root@localhost1 ~]#A=456
[root@localhost1 ~]#AA="$A"
[root@localhost1 ~]#echo $AA
456
//单引号效果
[root@localhost1 ~]#B='$b'
[root@localhost1 ~]#echo $B
$b
//反撇号效果
[root@localhost1 ~]#ls=`ls`
[root@localhost1 ~]#echo $ls
anaconda-ks.cfg initial-setup-ks.cfg 公共 模板 视频 图片 文档 下载 音乐 桌面
(2)键盘输入为变量赋值
[root@localhost ~]# read 变量名 // read 变量名(没有提升信息)继续输入变量值即可赋值
-p “显示提示信息” // 可追加输出需要显示的提示信息
//为 MyName 赋值(无提示信息)
[root@localhost1 ~]#read MyName
hhh
[root@localhost1 ~]#echo $MyName
hhh
//为 YourName 赋值(有提示信息)
[root@localhost1 ~]#read -p "请输入你的名字:" YourName
请输入你的名字:xxx
[root@localhost1 ~]#echo $YourName
xxx
6.删除变量
unset 变量名
[root@localhost1 ~]#A=123
[root@localhost1 ~]#echo $A
123
//删除变量
[root@localhost1 ~]#unset A
[root@localhost1 ~]#echo $A
7.自定义变量作用范围
默认情况下,新定义的变量只在当前的Shell环境中有效,因此称为局部变量。当进入子程序或新的子Shell环境时局部变量将无法再使用。
可以通过内部命令export将指定的变量导出为全局变量,使用户定义的变量在所有的子Shell环境中能够继续使用。
[root@localhost1 ~]# export 变量名
8.自定义变量永久启用
在/etc/profile(全局配置文件)中添加 export 变量名
9.变量的算术运算
整数变量的算术运算(Shell 默认只支持整数运算)
使用整数变量的算术运算赋值
- 变量=$((数值或变量1 运算符 数值或变量2))
- 变量=$[数值或变量1 运算符 数值或变量1]
- 变量=$(expr 数值或变量1 运算符 数值或变量2)
- let 变量=数值或变量1运算符数值或变量2 (数值与运算符之间不需要空格)
[root@localhost1 ~]#AB=$(($a + $b))
[root@localhost1 ~]#echo $AB
30
[root@localhost1 ~]#AB=$[100 / $b]
[root@localhost1 ~]#echo $AB
5
[root@localhost1 ~]#AB=$(expr $a \* 2)
[root@localhost1 ~]#echo $AB
20
[root@localhost1 ~]#let AB=99%$b
[root@localhost1 ~]#echo $AB
19
10.环境变量
[root@localhost1 ~]#env //使用 env 命令可以查看到当前工作环境下的环境变量
[root@localhost1 ~]#env
XDG_SESSION_ID=6
HOSTNAME=localhost1
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.116.1 53256 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/2
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share:/var/lib/flatpak/exports/share:/usr/local/share:/usr/share
SSH_CONNECTION=192.168.116.1 53256 192.168.116.10 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
DISPLAY=localhost:1
11.只读变量
定义只读变量无法手动修改和删除,但由于自定义变量是临时的,重启后便不存在了。
[root@localhost1 ~]# readonly 变量=变量值 //自定义只读变量
[root@localhost1 ~]# readonly -p //查看所有只读变量
//自定义只读变量
[root@localhost1 ~]#readonly x=123123
//查看所有只读变量
[root@localhost1 ~]#readonly -p
declare -r BASHOPTS="checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath"
declare -ir BASHPID
declare -r BASH_COMPLETION_COMPAT_DIR="/etc/bash_completion.d"
declare -ar BASH_REMATCH='()'
declare -ar BASH_VERSINFO='([0]="4" [1]="2" [2]="46" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")'
declare -ir EUID="0"
declare -ir PPID="4550"
declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
declare -ir UID="0"
declare -r x="123123"
12.位置变量
Shell脚本执行命令操作时会带有很多变量$n,文件中执行的第一变量为$1,n数值依次递增,用于代表某个位置的变量。
前9个位置变量可以用$1、$2、… 、$9 表示 ,第10个及以后的位置变量 $ 后跟的数值必须加{},如 ${28} 代表第28个位置变量
//编写脚本用于输出位置$1~$10变量
[root@localhost1 ~]#vim locate.sh
#!/bin/bash
echo -n $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}
[root@localhost1 ~]#source locate.sh 1 3 5 7 9 11 13 15 17 19
1 3 5 7 9 11 13 15 17 19