快速掌握Shell编程规范与变量(执行脚本文件的四种方法,管道与重定向,自定义变量以及特殊变量详解),理论+实战

产生背景

  • 在一些复杂的Linux维护工作中,大量重复性的输入和交互操作不但费时费力,而且容易出错,而编写一个恰到好处的shell脚本程序,可以批量处理,自动化的完成一系列维护任务,大大减轻管理员的负担

一:Shell脚本编程规范

1.1:Shell脚本的概念

  • 将要执行的命令按顺序保存到一个文本文件
  • 给该文件可执行权限
  • 可结合各种shell控制语句以完成更复杂的操作

1.2:Shell脚本应用场景

  • 重复性操作
  • 批量事务处理
  • 自动化运维
  • 服务运行状态监控
  • 定时任务执行

1.3:Shell的作用

1.3.1:作用一

命令解释器,“翻译官”

  • 介于系统内核与用户之间,负责解释命令行
    在这里插入图片描述

1.3.2:作用二

用户的登录shell

  • 登录后默认使用的shell程序,一般为/bin/bash
  • 不同shell的内部指令,运行环境等会有所区别
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh

1.4:编写第一个shell脚本

1.4.1:编写脚本代码

  • 使用vim文本编辑器
  • 每行一条Linux命令,按执行顺序依次编写
  • 脚本后缀为.sh
  • 例如,将一下三条命令按顺序用shell脚本编写
[root@localhost ~]# vim first.sh
cd /boot
pwd
ls -lh vm*
[root@localhost ~]# sh first.sh
/boot
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64

1.4.2:赋予可执行权限

  • 使脚本具有可执行属性
[root@localhost ~]# chmod +x first.sh 

1.4.3:执行脚本文件(四种方法)

  • 方法一:脚本文件路径(绝对路径与相对路径)
[root@localhost ~]# ./first.sh                                    必须有X权限
例如
[root@localhost ~]# vim first.sh
cd /boot
pwd
ls -lh vml*
[root@localhost ~]# ./first.sh  
-bash: ./first.sh:                     权限不够        当权限不够时,这边按tab也是不会补全的
[root@localhost ~]# chmod +x first.sh 
[root@localhost ~]# ./first.sh 
/boot
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64
  • 方法二:sh脚本文件路径
[root@localhost ~]# sh first.sh
/boot
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64
  • 方法三:source脚本文件路径
[root@localhost ~]# source first.sh
/boot
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64
  • 方法四:.空格脚本文件路径
[root@localhost ~]# . first.sh 
/boot
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64

1.4.4:执行脚本文件(四种方法)的总结

方法一:./first 不切换路径 必须有X执行权限
方法二:sh 切换路径 不需要X执行权限
方法三:source 切换路径 不需要X执行权限
方法四:. 切换路径 不需要X执行权限

1.4.5:更完善的脚本构成

  • 脚本声明
  • 注释信息
  • 可执行语句
#!/bin/bash                
#This is my first shell-script		               脚本描述信息
cd /boot
echo "当前所在路径"                             输出友好提示信息
pwd
echo "以vml为开头的文件是"
ls -lh vml*
[root@localhost ~]# sh first.sh 
当前所在路径
/boot
以vml为开头的文件是
-rwxr-xr-x. 1 root root 6.4M 4  25 00:32 vmlinuz-0-rescue-21579b24d04b46568ae08bba51a7ebd5
-rwxr-xr-x. 1 root root 6.4M 11  9 2018 vmlinuz-3.10.0-957.el7.x86_64

1.5:管道与重定向

1.5.1:交互式硬件设备

  • 标准输入:从该设备接收用户输入的数据
  • 标准输出:通过该设备向用户输出数据
  • 标准错误:通过该设备报告执行出错信息
类型 设备文件 文件描述编号 默认设备
标准输入 /dev/stdin 0 键盘
标准输出 /dev/stdout 1 显示器
标准错误输出 /dev/stderr 2 显示器

1.5.2:重定向操作

类型 操作符 用途
重定向输入 < 从指定的文件读取数据,而不是从键盘输入
重定向输出 > 将输出结果保存到指定的文件(覆盖原有内容)
重定向输出 >> 将输出结果追加到指定的文件
标准错误输出 2> 将错误信息保存到指定的文件(覆盖原有内容)
标准错误输出 2>> 将错误信息追加到指定的文件中
混合输出 &> 将标准输出,标准错误的内容保存到同一个文件中
例如
[root@localhost ~]# cd /link
-bash: cd: /link: 没有那个文件或目录                    提示错误
[root@localhost ~]# cd /link 2> /~/error.txt        将错误信息输入到新的error.txt
[root@localhost ~]# cd /~
[root@localhost ~]# cat error.txt                        查看文本内容
-bash: cd: /link: 没有那个文件或目录
[root@localhost ~]# 

1.5.3:管道操作符号“|”

将左侧的命令输出结果,作为右侧命令的处理对象(前后有关系时使用)

[root@localhost ~]# grep "bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
kevin:x:1000:1000:kevin:/home/kevin:/bin/bash
[root@localhost ~]# grep "bash$" /etc/passwd | awk -F: '{print $1,$7}'         此间的-F:也可以用空格和Tab代替,查看第1,7列的数据
root /bin/bash
kevin /bin/bash
[root@localhost ~]# df -Th
文件系统                类型      容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root xfs        50G  5.1G   45G   11% /
devtmpfs                devtmpfs  1.4G     0  1.4G    0% /dev
tmpfs                   tmpfs     1.4G     0  1.4G    0% /dev/shm
tmpfs                   tmpfs     1.4G   10M  1.4G    1% /run
tmpfs                   tmpfs     1.4G     0  1.4G    0% /sys/fs/cgroup
/dev/sda1               xfs      1014M  179M  836M   18% /boot
/dev/mapper/centos-home xfs       246G   39M  246G    1% /home
tmpfs                   tmpfs     283M   12K  283M    1% /run/user/42
tmpfs                   tmpfs     283M     0  283M    0% /run/user/0
[root@localhost ~]# df -Th | awk '{print $1,$6}'                查看第1.2.6列的数据
文件系统 已用%
/dev/mapper/centos-root 11%
devtmpfs 0%
tmpfs 0%
tmpfs 1%
tmpfs 0%
/dev/sda1 18%
/dev/mapper/centos-home 1%
tmpfs 1%
tmpfs 0%
  • awk :大部分情况,按列读取

    大部分情况下
    grep:过滤关键字
    sed: 按行读取
    awk:按列读取数据
    $1,$2:位置变量

二:shell脚本变量详解

2.1:shell变量的作用,类型

变量的作用

  • 为灵活管理Linux系统提供特定参数,有两层意思

    ​ 变量名:使用固定的名称,由系统预设或用户定义

​ 变量值:能够根据用户设置,系统环境的变化而变化

变量的类型

  • 自定义变量:由用户自己定义,修改和使用

  • 环境变量:由系统维护,用于设置工作环境

  • 位置变量:通过命令行给脚本程序传递参数

  • 预定义变量:bash中内置的一类变量,不能直接修改

2.2:自定义变量

2.2.1:定义一个新的变量与查看变量的值

  • 变量名以字母或下划线开头,区分大小写,建议全大写

变量名=变量值 =表示将右边的值赋予左边,并不是等于

  • 查看变量的值

echo $变量名

例如
[root@localhost ~]# name=python
[root@localhost ~]# echo $name
python
[root@localhost ~]# name1=text
[root@localhost ~]# echo $name $name1
python text

2.2.2:赋值时使用引号

  • 双引号:允许通过$符号引用其他变量值
  • 单引号:禁止引用其他变量值,$视为普通字符
  • 反撇号:命令替换,提取命令执行后的输出结果
[root@localhost ~]# name=python
[root@localhost ~]# echo $name
python
[root@localhost ~]# name1=text
[root@localhost ~]# echo $name $name1
python text
[root@localhost ~]# echo "$name"         
python
[root@localhost ~]# echo "${name}6.6"               双引号:允许通过$符号引用其他变量值
python6.6
[root@localhost ~]# echo '$name'                  单引号禁止引用其他变量值,$视为普通字符
$name
[root@localhost ~]# num=`ps aux | wc -l`           反撇号中识别命令,对命令结果进行解析
[root@localhost ~]# echo $num
197
[root@localhost ~]# txt=$(ps aux | wc -l)
[root@localhost ~]# echo $txt
197

2.2.3:从键盘输入内容为变量赋值

[root@localhost ~]# read -p "请输入一个整数:" sum
请输入一个整数:120
[root@localhost ~]# echo $sum
120
[root@localhost ~]# vim text.sh
#!/bin/bash
#This is my first shell-script
read -p "请输入一个整数:" sum
echo "你输入的值是:$sum"
[root@localhost ~]# sh text.sh 
请输入一个整数:120
你输入的值是:120

2.2.4:设置变量的作用范围

格式一:export 变量名... 
格式二:export 变量名=变量值...
[root@localhost ~]# num=`ps aux | wc -l`
[root@localhost ~]# echo $num
197
[root@localhost ~]# bash                 改变环境
[root@localhost ~]# echo $num
                                                               显示不出
[root@localhost ~]# exit               退出变量范围
exit
[root@localhost ~]# export num                 使用export设置变量
[root@localhost ~]# bash                   变量范围
[root@localhost ~]# echo $num              生效
197

2.2.5:整数变量的运算和常用运算符

  • 整数变量的运算

expr 变量1 运算符 变量2 [运算符 变量3]…

  • 常用运算符
加法运算:+
减法运算:-
乘法运算:\*               \表示转义
除法运算:/
求模(取余)运算:%
[root@localhost ~]# expr 1 + 2
3
[root@localhost ~]# expr 1 \* 3
3
[root@localhost ~]# expr 6 / 2
3
[root@localhost ~]# expr 32 % 15
2
[root@localhost ~]# expr 32 % 5
2
[root@localhost ~]# sum=`expr 3+3`	错误格式,求和变量运算,  中间是要加空格
[root@localhost ~]# echo $sum
3+3
[root@localhost ~]# sum=`expr 3 + 3`	正确格式,求和变量运算
[root@localhost ~]# echo $sum
6

2.3:特殊的shell变量

2.3.1:环境变量和常见的环境变量

环境变量

  • 由系统提前创建,用来设置用户的工作环境
  • 配置文件:/etc/profile,~/.bash_profile

常见的环境变量

  • PWD,PATH
  • USER,SHELL,HOME

2.3.2:只读变量

  • 用于变量值不允许被修改的情况
[root@localhost ~]# name=cloud
[root@localhost ~]# readonly name        //设置为只读变量
[root@localhost ~]# echo $name
cloud
[root@localhost ~]# name=yun
-bash: name: readonly variable           //只读变量不可以被重新赋值
[root@localhost~]#
[root@localhost ~]# unset name       //只读变量不可以被删除
-bash: unset: name: cannot unset: readonly variable

2.3.3:位置变量

表示为$n,n为1-9之间的数字

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-treJyQop-1594824598108)(C:\Users\kevin\AppData\Roaming\Typora\typora-user-images\image-20200715223429991.png)]

[root@localhost ~]# vim kfc.sh 
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "总和为:$sum"

[root@localhost ~]# ./kfc.sh 20 30
总和为:50
[root@localhost ~]# vim kfc.sh 
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "总和为:$sum"
echo "执行的脚本是$0"

[root@localhost ~]# ./kfc.sh 22 33
总和为:55
执行的脚本是./kfc.sh
[root@localhost ~]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "总和为:$sum"
echo "执行的脚本是:$0"
echo "执行的脚本个数是:$#"		'$#:命令行中位置变量的个数'
~     
[root@localhost ~]# ./kfc.sh 13 30
总和为:43
执行的脚本是:./kfc.sh
执行的脚本个数是:2

[root@localhost ~]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "总和为:$sum"
echo "执行的脚本是:$0"
echo "执行的脚本个数是:$#"
echo "详细内容是:$*"

[root@localhost ~]# ./kfc.sh 13 30 
总和为:43
执行的脚本是:./kfc.sh
执行的脚本个数是:2
详细内容是:13 30
[root@localhost ~]# ./kfc.sh 13 30 22 22 22
总和为:43
执行的脚本是:./kfc.sh
执行的脚本个数是:5
详细内容是:13 30 22 22 22

[root@localhost ~]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 + $2`
echo "是否执行成功:$?"
echo "总和为:$sum"		
echo "执行的脚本是:$0"
echo "执行的脚本个数是:$#"
echo "详细内容是:$*"

[root@localhost ~]# ./kfc.sh 13 30 
是否执行成功:0	'0:表示执行成功,非0值:表示执行失败'
总和为:43
执行的脚本是:./kfc.sh
执行的脚本个数是:2
详细内容是:13 30

[root@localhost ~]# !vim
#!/bin/bash
#This is my first shell-script
sum=0
sum=`expr $1 / $2`	'改变成除法'
echo "是否执行成功:$?"	'此变量要放在第一行,输出上一行命令执行后返回的状态'
echo "总和为:$sum"
echo "执行的脚本是:$0"
echo "执行的脚本个数是:$#"
echo "详细内容是:$*"

[root@localhost ~]# ./kfc.sh 10 0
expr: division by zero	
是否执行成功:2	'显示失败'
总和为:
执行的脚本是:./kfc.sh
执行的脚本个数是:2
详细内容是:10 0

2.3.4:预定义变量

  • $#:命令行中位置变量的个数
  • $*:所有位置变量的内容
  • $?:上一条命令执行后返回的状态,当返回状态值为0时表示正常,非0值表示执行异常或出错
  • $0:当前执行的进程/程序名

分析脚本

[root@localhost opt]# vim text.sh
#!/bin/bash
TARFILE=beifen-`date +%s`.tgz  '设置变量名称,+%s表示从1970至今经过的秒数,所以文件名不会出现重复的情况,就不会有被覆盖的风险'
tar zcvf $TARFILE $* &> /dev/null	'tar工具压缩输出到 /dev/null'
echo "已执行$0个脚本"	'当前执行的进程名'
echo "共完成$#个对象的备份"	'位置变量的个数'
echo "具体内容包括:$*"	'所有位置变量的内容'
~    
[root@localhost opt]# ./text.sh /etc/passwd /etc/shadow
已执行./text.sh个脚本
共完成2个对象的备份
具体内容包括:/etc/passwd /etc/shadow
'/dev/null:黑洞,数据到这里就消失了,无法找回'

[root@localhost ~]# date
2020 07 15 星期三 22:45:11 CST
[root@localhost ~]# date +%s
1594824318
[root@localhost ~]# date +%F
2020-07-15
[root@localhost ~]# date +%Y%m%d
20200715

[root@localhost ~]# date "+现在的时间是:%Y-%m-%d %H-%M-%S"
现在的时间是:2020-07-15 22-47-11
[root@localhost ~]# date "+三年前的时间是:%Y-%m-%d %H-%M-%S" -d "-3 year"
三年前的时间是:2017-07-15 22-48-08
[root@localhost ~]# date "+三个月后的时间是:%Y-%m-%d %H-%M-%S" -d "+3 month"
三个月后的时间是:2020-10-15 22-48-50

[root@localhost opt]# 
%Y表示年
%m表示月
%d表示日
%H表示小时
%M表示分钟
%S表示秒
%s表示从 1970  1  1  00:00:00 UTC 到目前为止的秒数,相当于time函数
%w表示一周中的第几天。

猜你喜欢

转载自blog.csdn.net/m0_47219942/article/details/107372324