SHELL脚本基础

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

前言

一、概述

二、SHELL与内核、硬件、应用之间的关系

​编辑    三、SHELL的类型

四、变量

五、SHELL脚本规范

六、语句

​编辑     七、文件四剑客

 八、测试

总结



前言

SHELL脚本是一种用来自动化执行操作系统命令和任务的脚本语言。它们被广泛用于Linux和其他类Unix操作系统中可以编写一系列命令和逻辑来完成特定的任务。

以下是SHELL脚本的一些基本特点

1. 解释性语言SHELL脚本不需要编译它们被解释器逐行解释和执行。

2. 命令行界面SHELL脚本通常在命令行界面中运行可以直接在终端中执行或者通过脚本文件执行。

3. 可编程性SHELL脚本支持变量、条件语句、循环和函数等基本的编程结构使得编写复杂的逻辑和控制流程成为可能。

4. 系统命令的调用SHELL脚本可以调用系统自带的命令、工具和程序利用其功能来完成各种任务。

5. 文件处理SHELL脚本可以读取、写入和处理文本文件进行文件和目录操作包括复制、移动、删除等。

6. 自定义脚本和函数SHELL脚本可以定义自己的函数和脚本方便代码的复用和模块化。

7. 条件和循环控制SHELL脚本支持条件判断和循环结构可以根据条件执行不同的操作并重复执行一系列命令。

8. 环境变量SHELL脚本可以设置和使用环境变量这些变量可以保存程序运行时的状态信息和配置参数。

SHELL脚本可以用于各种用途比如自动化任务、批量处理、系统管理和配置等。它们提供了一种简单而强大的方式来管理和控制计算机系统。


一、概述

脚本就是将手动一次性执行的命令进行规范且自动化。

方向

1、表达式

变量
        1、预定义变量
        2、位置变量
        3、自定义变量
    运算符
        1、数学运算
        2、数值比较
        3、字符串比较
        4、文件判断
        5、布尔运算符

2、语句

条件语句 if
 分支语句 case
 循环语句 for    while

3、函数

4、正则表达式
    标准正则
    扩展正则

5、文件操作四剑客
    find
    egrep
    sed
    awk

二、SHELL与内核、硬件、应用之间的关系

SHELLShell也是指这个软件是一种在操作系统中提供用户与操作系统内核进行交互的命令行解释器。它是用户与操作系统之间的接口负责解析和执行用户输入的命令并与内核和硬件进行通信来完成相应的操作。

具体而言SHELL与内核、硬件和应用程序之间的关系如下

1. 内核内核是操作系统的核心部分负责管理计算机的资源和处理底层任务如进程管理、内存管理、文件系统管理等。SHELL通过与内核进行交互向其发送用户输入的命令并将输出结果显示给用户。

2. 硬件硬件是指计算机的实际物理设备如处理器、内存、硬盘、网络接口等。SHELL通过与内核通信向硬件发送指令和请求以执行相应的操作。例如通过SHELL可以发送网络请求、读写文件或者与其他外设进行交互。

3. 应用程序应用程序是在操作系统上运行的软件。SHELL可以与应用程序进行交互启动和关闭应用程序传递命令行参数和输入数据给应用程序以及从应用程序获得输出结果。

在这个关系中SHELL充当了用户和操作系统之间的桥梁。它解释和执行用户输入的命令并与内核和硬件交互来实现所需的操作。通过SHELL用户可以操作计算机系统的各个方面包括文件管理、进程控制、系统配置等。


    三、SHELL的类型

类型
sh
 ash
bsh
csh
bash
 tcsh
 dsh
zsh

1、查看系统中支持的shell   命令cat /etc/shells

[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh

2、查看系统中当前使用的shell  命令 echo $SHELL

[root@localhost ~]# echo $SHELL
/bin/bash

四、变量

1、什么是变量

变量名是由变量名和变量值组成的举个简单的例子比如喝水用的杯子我可以使用这个杯子装水喝也可以用这个杯子装可乐、雪碧、牛奶等。在这里杯子属于变量名没有变化杯子里的液体属于变量值发生了变化类似下图a的值

[root@localhost ~]# a=1
[root@localhost ~]# echo $a
1
[root@localhost ~]# a=2
[root@localhost ~]# echo $a
2
[root@localhost ~]# a=3
[root@localhost ~]# echo $a
3

2、变量名的声明规范、方法

声明规范
    
    不能是数字或数字开头
    以_或字母开头
    变量名中不能包含特殊字符
声明方法
    
驼峰式 userName
    双驼峰UserName
    shell写法 user_name
                   username
                        USERNAME
[root@localhost ~]# _a=1
[root@localhost ~]# Name=1
[root@localhost ~]# NumberInt=1
[root@localhost ~]# User_Name=1
[root@localhost ~]# NAME=1

3、在Linux系统中可用env查看所有的变量

自定义变量varName=varValue等号两边不能有空格
    数字 var1=1
    字符串shell中可以不使用引号当包含有空格时需要使用引号
    引号的用法
        1不会引用变量值 单引号 '
        2)会应用变量值双引号 "
        3引用命令结果反撇号 `
            $(命令)应用场景较多

[root@localhost ~]# name=hy
####单引号' '单引号内的内容会被视为字面字符串不会对其中的变量或命令进行解析即不会引用它们的值。如
[root@localhost ~]# echo 'my name is $name'
my name is $name
####双引号" "双引号内的内容会被解析并引用其中的变量和命令结果。如
[root@localhost ~]# echo "my name is $name"
my name is hy
####反撇号``和$这两个用法是等效的用于引用命令的结果。如
[root@localhost ~]# echo `my name is $name`
bash: my: 未找到命令...
[root@localhost ~]#files_count=`ls | wc -l`
[root@localhost ~]# mkdir test
[root@localhost ~]# cd test
[root@localhost test]# echo "当前文件夹中的文件数量为${files_count}"
当前文件夹中的文件数量为0

4、 位置变量
    脚本后参数所在的位置$1... $9

5、预定义变量

 $0脚本本身的名称
 $#脚本后参数的个数
$*脚本运行时参数的内容整体输出
$@脚本运行时参数的内容逐个输出
$?脚本运行完毕后的返回值默认情况0成功、非0失败
###写一个测试脚本
#!/bin/bash
#This is test
echo "第一个参数$1"
echo "第一个参数$2"
echo "第一个参数$3"
echo "脚本名称 $0"
echo "执行的参数 $@"
echo "执行数量 $#"

6、作用域
  1  默认变量只在当前shell下生效

打开子标签这里a=666是没有生效的
    2若要在当前及其子shell下生效需要声明为全局变量export

7、shell中的字符串

赋值 str1=foodfornoting.gpg

string
1获得字符串的长度
    语法    ${#StringName}
    案例    echo ${#str1}
    输出结果17
2字符串取子串
    语法    ${#StringName:position:lenght}
    案例    echo ${str1:0:3}
    输出结果foo
    注意lenght没有定义时一直取到字符串的结尾

3字符串的截取
    a从左至右截取最后一个匹配字符串string之后的所有字符串
    语法    ${StringName##*string}
    案例    echo ${str1##*fo}
    输出结果rnoting.gpg

   b从左至右截取第一个匹配字符串string之后的所有字符串
    语法    ${StringName#*string}
    案例    echo ${str1#*fo}
    输出结果odfornoting.gpg
    c从右至左截取最后一个匹配字符串string之后的所有字符串
    语法    ${StringName%%string*}    
    案例    echo ${str1%%o*}
    输出结果f
    d从右至左截取第一个匹配字符串string之后的所有字符串
    语法 ${StringName%string*}
    案例 echo ${str%o*}
    输出结果foodforn
    4字符串的拼接
    语法    StringName3=${StingName1}${StringName2}
    案例    str1=Hello
        str2=,Jack!
        str3=${str1}${str2}
        echo ${str3}
    输出结果: Hello,Jack!
    5字符串替换
    语法    ${StringName/OldString/NewString}
    案例    str1=foodfornoting.gpg
        echo ${str1/oo/kk}
    输出结果fkkdfornoting.gpg

[root@localhost ~]# str1=foodfornoting.gpg
[root@localhost ~]# echo $str1
foodfornoting.gpg
[root@localhost ~]# echo ${#str1}
17
[root@localhost ~]# echo ${str1:0:3}
foo
[root@localhost ~]# echo ${str1##*fo}
rnoting.gpg
[root@localhost ~]# echo ${str1#*fo}
odfornoting.gpg
[root@localhost ~]# echo ${str1%%o*}
f
[root@localhost ~]# echo ${str1%o*}
foodforn
[root@localhost ~]# str1=Hello
[root@localhost ~]# str2=,Jack!
[root@localhost ~]# str3=${str1}${str2}
[root@localhost ~]# echo ${str3}
Hello,Jack!
[root@localhost ~]# str1=foodfornoting.gpg
[root@localhost ~]# echo ${str1/oo/kk}
fkkdfornoting.gpg

8、数学运算

 + - * / %    当* 作为乘号时需要加转义符\
    
运算方法
        expr
            expr $a + $b
        $((a+b))
            echo $((a+b))
        $[a+b]
            echo $[a+b]
    注意
        shell不支持浮点数的显示
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# expr $a+$b
1+2
[root@localhost ~]# expr $a + $b
3
[root@localhost ~]# echo $((a+b))
3
[root@localhost ~]# echo $[a+b]
3
[root@localhost ~]# expr $[ a / b ]
0
[root@localhost ~]# expr $[ a - b ]
-1
[root@localhost ~]# expr $[ a * b ]
2
[root@localhost ~]# expr $[ a / b ]
0
 

9、比较运算

条件测试
[ $a -ne $b ] &&  echo OK条件 && 输出结果     条件为真输出
 [ $a -ne $b ] ||  echo OK条件 || 输出结果        条件为假输出
[root@localhost ~]# a=1
[root@localhost ~]# b=2
[root@localhost ~]# [ $a -ne $b ] && echo OK
OK
[root@localhost ~]# [ $a -eq $b ] || echo OK 
OK
##1不等于2是真的所以&&输出
##1等于2是假的所以||输出

数值比较

 -eq 等于  -ne 不等于  -lt 小于  -le 小于等于 -gt 大于  -ge 大于等于

[root@localhost test]# a=10
[root@localhost test]# b=20
[root@localhost test]# [ $a -eq $b ]
[root@localhost test]# echo $?
1
[root@localhost test]# [ $a -ne $b ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ $a -lt $b ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ $a -le $b ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ $a -gt $b ]
[root@localhost test]# echo $?
1
[root@localhost test]# [ $a -ge $b ]
[root@localhost test]# echo $?
1
#####0为成功、非0为失败
字符串比较
= 字符串一致
 !=字符串不一致
 -z字符串为空
 !     -z 字符串不为空
[root@localhost test]# str1=hello,word
[root@localhost test]# str2=hell,john
[root@localhost test]# [ $str1 = $str2 ]
[root@localhost test]# echo $?
1
[root@localhost test]# [ $str1 != $str2 ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -z $str1 ]
[root@localhost test]# echo $?
1
[root@localhost test]# [ ! -z $str1 ]
[root@localhost test]# echo $?
0

文件比较

-e 文件或目录是否存在 -f 是否为文件 -d 是否为目录  -r 判断文件是否可读 -w 判断文件是否可写

-x

判断文件是否可执行

[root@localhost test]# touch 1.txt
[root@localhost test]# [ -e 1.txt ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -f 1.txt ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -d 1.txt ]
[root@localhost test]# echo $?
1
[root@localhost test]# ll 1.txt 
-rw-r--r-- 1 root root 0 8月  18 11:45 1.txt
[root@localhost test]# [ -r 1.txt ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -w 1.txt ]
[root@localhost test]# echo $?
0
[root@localhost test]# [ -x 1.txt ]
[root@localhost test]# echo $?
1

10、逻辑运算符

逻辑运算符
&&

         -a
            并且有假则假全真为真
                [ -r 111 -a -w 111 -a -x 111 ]
                [ -r 111 ] && [ -w 111 ] &&  [ -x 111 ]

          [ -x /root/file1 -a  -d /root/file1 ]
         [ -x /root/file1 ]  && [ -d /root/file1 ]

 ||-o
            或者有真则真全假为假
 !取反
            有真则假有假则真

五、SHELL脚本规范

shell脚本规范
 第一行#!/bin/bash
第二行 #脚本的说明
 第三行脚本正文
脚本运行规则
 没有x权限        bash  脚本所在路径/脚本文件
        source 脚本所在路径/脚本文件
        .      脚本所在路径/脚本文件
        脚本存在cd  时会切换到目标目录
有x权限       ./脚本文件
        脚本绝对路径/脚本文件

shell脚本运行追踪bash -x 脚本所在路径/脚本文件

$[$RANDOM%100]返回100内随机数
seq 1 10返回1到10 的连续数字
{1..10}返回1到10 的连续数字
seq 1.1 10.1返回1.1 2.1 3.1.... 10.1
read -p "提示语" 变量名读取键盘输入并赋值给变量名

六、语句

条件语句
单分支if        if [ ];then
fi
双分支if
        if [ ];then
else
fi
多分支if   if [ ];then
elif [ ];then
else
fi
#!/bin/bash
#hy
#if单分支用来进行简单的测试
read -p "你好请问你的名字是" c
echo " 很荣幸认识你,$c" 
b=yes                                                     #定义变量   
read -p "尊敬的$c,你好~请问你需要查看磁盘情况吗yes/no  " a      #这里是一个交互的询问 a是一个变量
if [ "$a" = "$b" ];then                                   #当输入的是yes就会查看磁盘信息
 df
else                                                      #其他情况
 exit 0                                                   #退出
fi

#!/bin/bash
#hy
#test2
##定义变量
b=1
c=2
d=3
read -p "你需要查看什么信息磁盘(1)、剩余内存(2、ip(3)" a
if [ "$a" = "$b" ];then        #如果输入1就查看磁盘
   df
 elif [ "$a" = "$c" ];then     #如果输入的是2就查看剩余内存
   free
 elif [ "$a" = "$d" ];then     #如果输入的是3就查看ip地址
   ip a
 else
   exit 0                      #其他情况直接退出
fi

 

循环语句

for

for 条件i in 值|((i=1;i<=10;i++))

do
    语句
done

 while i=1
while 条件
do
    语句
    let  i++
done
#!/bin/bash
#hy
#for循环
for i in {1..10};do
touch $i.txt #创建1~10.txt
done


 

#!/bin/bash
#hy
#for循环
#for i in {1..10};do
#touch $i.txt
#done
###下面我使用这个脚本去删除我之前创建的1~10.txt
i=1
while [ "$i" -lt "11" ] #当$i小于11时执行
do
    rm -r $i.txt        #删除$i.txt   
    echo "已删除$i.txt"
    i=$(($i+1))         #每次$i递增1,并继续循环
done

#!/bin/bash
#hy
#case开关测试
b=$"`date`"
c=$"`ip a`"
read -p "您好查询时间请按1查询ip请按2查询天气请按3听笑话请按4;退出请按5"                 a
case $a in
   1)echo "北京时间$b"
   ;;
   2)echo "ip地址$c"
   ;;
   3)echo "当前气温30摄氏度注意防晒。"
   ;;
   4)echo " 笑话 "
   ;;
   5)echo " 谢谢使用祝您生活愉快~再见~"
esac


     七、文件四剑客

1、find

Find命令适用于查找文件、目录

find ./ -type f 查找当前目录下的文件

find ./ -type f -mtime +30查找当前目录下30天前创建的文件

find ./ -type f -mtime -1查找当前目录下今天创建的文件

find ./ -type f -mtime -1|xargs rm -rf {} /;查找当前目录下今天创建的文件,并删除

find ./ -type d 查找当前目录下的目录

find ./ -type d -mtime +30查找当前目录下30天前创建的目录

find ./ -type d -mtime -1查找当前目录下今天创建的目录

find ./ -type d -mtime -1|xargs rm -rf {} /;查找当前目录下今天创建的目录,并删除

find ./ -name “*.txt” -type d -mtime -1 |xargs rm -rf {} /; 查找当前目录下所今天创建有.txt结尾的目录并删除

find ./ -name “*.txt” -type d -mtime -1 -exec cp -r {} /tmp\; 查找当前目录下所今天创建有.txt结尾的目录并拷贝到/tmp下

##-exec是将前面执行的结果调用更建议使用。因为|xargs有些命令执行不了例如chmod修改权限等。

2、grep

Grep用于查找文件的内容

^表示是以什么开头grep “^root” /etc/passwd 查找/etc/passwd中以root开头的内容

$表示以什么结尾grep “bash$” /etc/passwd 查找/etc/passwd中以bash结尾的内容

过滤注释grep -v “#”

过滤空行grep -v “^$”

拓展如何使用egrep来匹配ip?

创建一个带有ip的文件ip.txt

下面用egrep命令来筛选出真确的IP格式

egrep [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ip.txt

解释[0-9]表示0到9的随机数字{1,3}表示3次$表示结束

也可以使用 egrep '([0-9]{1,3}\.){3}[0-9]{1,3}$' ip.txt

解释[0-9]表示0到9的随机数字{1,3}表示3次表示将其视为一个整体。{3}执行3次

3、awk

AWK命令是用于查询文件的列

如果我想要打印一个用户的名字和对应的SHELL

awk的常用格式 awk ‘{print $1}’ /etc/passwd 打印/etc/passwd的第一列但是他只有一列所以会全部打出

awk -F: {print $1,$NF} /etc/passwd -F:去除掉打印/etc/passwd的第一列和最后一列

awk -F: {print $1,:$NF} /etc/passwd -F:去除打印第一列和最后一列并在两者间添加

如何把本机的IP以 “- - -”  的形式打印出来

1.ip -a查看IP信息

2.这里运用了大量的管道符来进行处理不断的过滤前一条命令的处理结果

ip a |grep "192.168.115.129"|awk -Finet '{print $2}'|awk -F/24 '{print $1}'|awk -F. '{print $1"-"$2"-"$3"-"$4}'

3.那如何把主机名修改为此ip呢

直接用``号调用命令的执行结果

hostnamectl set-hostname `ip a |grep "192.168.115.129"|awk -Finet '{print $2}'|awk -F/24 '{print $1}'|awk -F. '{print $1"-"$2"-"$3"-"$4}'`

 

4、sed

sed命令用于替换文件的内容

sed基本使用格式sed -i s/ 原来的/要替换的/替换行数 /文件名

sed -i 2s/192/8888/ ip.txt 仅修改第二行的192

 

sed -i s/192/8888/g ip.txt 把所有的192换成8888

 

把www.test.com换成www//test//com

sed -i 's/www.test.com/www\/\/test\/\/com/g' ip.txt

 

其中/\/\表示转意

 八、测试

这里我写了一个检测系统状态的脚本

#/bin/bash
#qzh
#用于监控系统的性能
cpu_use=$(top -bn1|grep "%Cpu(s)"|awk '{print $2+$4} '|awk '{print}'|awk -F. '{print $1}')
free_use=$(free |grep "Mem"|awk '{print ($3/$2) * 100}'|awk -F. '{print $1}')
df_use=$(df |awk 'NR==6 {print $5}'|awk -F% '{print $1}')
#定义阈值
Cpu=80
Free=80
df=80
####
y="yes"
read -p " 是否检测系统当前状况?yes/no " h
if [ "$h" = "$y" ];then
      echo " 当前cpu使用率" $cpu_use%
      echo " 当前磁盘使用率" $df_use%
      echo " 当前内存使用情况" $free_use%
  else 
      echo " 再见~ "   
      exit 0
fi
###
if [ "$cpu_use" -gt "$Cpu"  ];then
      echo " 警告 当前CPU使用率过高请注意 "
fi
if [ "$free_use" -gt "$Free" ];then
      echo " 警告当前内存使用过高请注意 "
fi
if [ "$df_use" -gt "$df" ];then
      echo " 警告当前磁盘使用率过高请注意 "
fi 
while true
do 
cpu_use=$(top -bn1|grep "%Cpu(s)"|awk '{print $2+$4} '|awk '{print}'|awk -F. '{print $1}')
free_use=$(free |grep "Mem"|awk '{print ($3/$2) * 100}'|awk -F. '{print $1}')
df_use=$(df |awk 'NR==6 {print $5}'|awk -F% '{print $1}')
clear
 echo " 当前cpu使用率" $cpu_use%
      echo " 当前磁盘使用率" $df_use%
      echo " 当前内存使用情况" $free_use%
if [ "$cpu_use" -gt "$Cpu"  ];then
      echo " 警告 当前CPU使用率过高请注意 "
fi
if [ "$free_use" -gt "$Free" ];then
      echo " 警告当前内存使用过高请注意 "
fi
if [ "$df_use" -gt "$df" ];then
      echo " 警告当前磁盘使用率过高请注意 "

sleep 5
fi
done

运行后是这个界面

 

可以配合命令touch ~/4.txt && dd if=/dev/zero of=~/4.txt bs=1000M count=100来检测

 

 


 

总结

这里我表达的并不全面还有很多东西没有列举出来主要是四剑客要多多练习共同进步加油每一个你

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: shell