目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Shell

为什么要学习shell编程

  • Linux/Unix系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。
  • 减少重复性工作,提升运维人员的工作效率。
  • Shell脚本是企业中Linux自动化运维必备不可替代的工具。

学好shell编程所需Linux基础

  • 熟练掌握vim。
  • 对Linux系统常用命令的掌握程度就直接决定运维人员Shell脚本编程的掌握高度。
  • 正则表达式及三剑客(grep、sed、awk)。

如何才能学好shell编程

  • 变量基础、条件表达式、if判断、for循环、While循环、case语句、循环控制命令
  • 初学者,一定要从简单做起,最小化代码学习,复杂的程序都是由许多小的功能模块组合而成的。
  • 多模仿、多练习、多思考。
  • 锻炼编程思维:将需求理解透彻,然后把大的需求进行分解,逐步形成小的程序或模块。

什么是shell

  shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,用户输入一条命令,Shell就解释执行一条。这种从键盘输入命令,就可以立即得到回应的对话方式,被称之为交互的方式。

  shell存在于操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出到屏幕返回给用户,当我们输入系统用户名和密码,登录到Linux后的所有操作都是由Shell解释并执行的。

  针对命令解释器shell在操作系统中所处的位置给了基本图解。

常用操作系统的默认shell

操作系统默认使用的shell
Linuxbash(Bourne Again shell)
Solaris、FreeBSDsh(Bourne shell)
AIXksh(Korn Shell)

  通过以下两种方法可查看CentOS linux系统默认的shell

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

# 方法二
[root@localhost ~]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

shell脚本的创建与执行

[root@localhost software]# cat test.sh
#!/bin/bash
echo "This is a test!"

  一个规范的shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容,这一行内容在Linux bash变成中一般为:

#!/bin/bash

  “#!”的作用:在执行bash脚本的时候,内容会根据 #! 后的解释器来确定该用哪个程序解释这个脚本中的内容。

  执行方式

[root@localhost software]# bash test.sh
This is a test!

变量

  变量是暂时存储数据的空间及其引用,所存储的数据存在于内容空间中,通过正确地引用内存空间中变量的名字就可以取出变量对应的数据。

  变量分为:普通变量(局部变量)、环境变量(全局变量)

普通变量

  普通变量也称为局部变量,只能在创建他们的shell函数或shell脚本中使用。

# 定义变量
[root@localhost software]# dog="My name is lion"
[root@localhost software]# echo $dog
My name is lion

# 取消变量
[root@localhost software]# unset dog
[root@localhost software]# echo $dog

  局部变量定义及赋值的规则:

  • 变量内容有空格且希望解析内容中的变量,使用双引号
    [root@localhost ~]# a="My name is $USER"
    [root@localhost ~]# echo $a
    My name is root
    
  • 希望原样输出变量的内容时使用单引号
    [root@localhost ~]# a='My name is $USER'
    [root@localhost ~]# echo $a
    My name is $USER
    
  • 要使用反引号将赋值的命令括起来,或者用$()
    [root@localhost ~]# a="today is `date`"
    [root@localhost ~]# echo $a
    today is Sat Jun 5 10:57:40 CST 2021
    

环境变量

  环境变量也可称为全局变量,可以在创建他们的shell及其派生出来的任意子进程shell中使用,环境变量又可分为自定义环境变量和bash内置环境变量。

# bash内置环境变量
[root@localhost software]# echo $USER
root
[root@localhost software]# echo $SHELL
/bin/bash
[root@localhost software]# echo $HOME
/root

# 自定义环境变量
[root@localhost software]# export test=1
[root@localhost software]# echo $test
1

# 环境变量永久生效(优先级)
/etc/bashrc > 
~/.bashrc > 
~/.bash_profile >
/etc/profile

export TMOUT=30000

显示当前环境变量名称及对应值

[root@localhost ~]# env

位置特殊参数变量

位置变量作用说明
$0获取当前执行shell脚本的文件名,如果执行脚本带路径,那么就包括脚本路径
$n获取当前执行的shell脚本的第n个参数值,n=1..9,如果n大于9,则用大括号括起来,例如${10},接的参数以空格隔开
$*获取当前shell脚本所有传参的参数
$#参数的个数
[root@localhost script]# cat test.sh
echo $0
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15}
echo $*
echo $#

[root@localhost script]# bash test.sh {a..z}
test.sh
a b c d e f g h i a0 a1 a2 a3 a4 a5
a b c d e f g h i j k l m n o
a b c d e f g h i j k l m n o p q r s t u v w x y z
26

# 关于$#的用法
[root@localhost script]# cat network.sh
if [ "$#" -eq 0 ]
then
        echo "Usage: ${0} {start|stop|restart}"
fi
echo $1

进程特殊状态变量

进程变量作用说明
$?获取执行上一个指令的执行状态返回值,0为成功,非零为失败
$$获取当前执行的shell脚本的进程号(PID),
# $? 的用法
[root@localhost script]# ls
network.sh  test.sh
[root@localhost script]# echo $?
0
[root@localhost script]# l
-bash: l: command not found
[root@localhost script]# echo $?
127

# $$ 的用法
[root@localhost script]# echo $$
14615

字符串处理

# 计算字符串长度
[root@localhost ~]# var1="I love you,Do you love me"
[root@localhost ~]# echo ${#var1}
25
[root@localhost ~]# expr length "$var1"
25

# 获取字符索引位置
[root@localhost ~]# var1="quickstart is a app"
[root@localhost ~]# expr index "$var1" start
6
[root@localhost ~]# expr index "$var1" uniq
1
[root@localhost ~]# var1="qkuickstart is a app"
[root@localhost ~]# expr index "$var1" cnk
2

# 获取子串长度
[root@localhost ~]# expr match "$var1" .*app
19
[root@localhost ~]# expr match "$var1" quickstart
10

# 抽取字符串中的子串  expr索引是从1开始计算, postion索引是从0开始计算
[root@localhost ~]# var1="kafka hadoop yarn mapreduce"
[root@localhost ~]# echo ${var1:10}
op yarn mapreduce
[root@localhost ~]# echo ${var1:5:10}
hadoop ya
[root@localhost ~]# echo ${var1: -5}
educe
[root@localhost ~]# echo ${var1: -5:2}
ed
[root@localhost ~]# expr substr "$var1" 5 10
a hadoop y

变量替换

[root@localhost ~]# var1="I love you,Do you love me"
[root@localhost ~]# echo $var1
I love you,Do you love me

# 从头开始匹配,最短删除
[root@localhost ~]# v1=${var1#*ov}
[root@localhost ~]# echo $v1
e you,Do you love me
# 从头开始匹配,最长删除
[root@localhost ~]# v2=${var1##*ov}
[root@localhost ~]# echo $v2
e me

# 从尾部开始删除,最短匹配
[root@localhost ~]# v3=${var1%ov*}
[root@localhost ~]# echo $v3
I love you,Do you l
# 从尾部开始删除,最长匹配
[root@localhost ~]# v4=${var1%%ov*}
[root@localhost ~]# echo $v4
I l

# 替换变量内的旧字符串为新字符串,只替换一次
[root@localhost ~]# echo $PATH
/application/mysql/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# v5=${PATH/bin/BIN}
[root@localhost ~]# echo $v5
/application/mysql/BIN:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

# 替换变量内的旧字符串为新字符串,替换全部
[root@localhost ~]# echo $PATH
/application/mysql/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# v6=${PATH//bin/BIN}
[root@localhost ~]# echo $v6
/application/mysql/BIN:/usr/local/sBIN:/usr/local/BIN:/usr/sBIN:/usr/BIN:/root/BIN

综合练习脚本

[root@localhost software]# cat example.sh
#!/bin/bash

string="Bigdata process framework is Hadoop,Hadoop is an open source project"

function print_tips
{
        echo "********************************"
        echo "(1)打印string长度"
        echo "(2)删除字符串中所有的Hadoop"
        echo "(3)替换第一个Hadoop为Mapreduce"
        echo "(4)替换全部Hadoop为Mapreduce"
        echo "********************************"
}
function len_of_string
{
        echo "${#string}"
}
function del_hadoop
{
        echo "${string//Hadoop/}"
}
function rep_hadoop_mapreduce_first
{
        echo "${string/Hadoop/Mapreduce}"
}
function rep_hadoop_mapreduce_all
{
        echo "${string//Hadoop/Mapreduce}"
}

while true
do
        echo "[string=$string]"
        echo
        print_tips
        read -p "Pls input your choice(1|2|3|4|q|Q):"  choice

        case $choice in
                1)
                        len_of_string
                        ;;
                2)
                        del_hadoop
                        ;;
                3)
                        rep_hadoop_mapreduce_first
                        ;;
                4)
                        rep_hadoop_mapreduce_all
                        ;;
                q|Q)
                        exit
                        ;;
                *)
                        echo "Error,input only in (1|2|3|4|q|Q)"
        esac
done

命令替换

``和$()两者是等价的

$(())主要用来进行整数运算,包括加减乘除

# 获取系统所有用户并输出
[root@localhost ~]# cat user.sh
#!/bin/bash
#
index=1
for user in `cat /etc/passwd | cut -d ":" -f 1`
do
        echo "This is $index user: $user"
        index=$(($index + 1))
done


# 根据系统时间计算今年或明年
[root@localhost ~]# echo "This is $(($(date +%Y) + 1)) year"
This is 2022 year

# 根据系统时间获取今年还剩多少星期,已经过了多少星期
[root@localhost ~]# echo "This year have passed $(date +%j) days"
This year have passed 135 days
[root@localhost ~]# echo "This year have passed $(($(date +%j)/7)) weeks"
This year have passed 19 weeks

[root@localhost ~]# echo "There is $((365 -$(date +%j))) days before new year"
There is 230 days before new year
[root@localhost ~]# echo "There is $(((365 -$(date +%j))/7)) weeks before new year"
There is 32 weeks before new year

# 判断nginx 进程是否存在,若不存在则自动拉起该进程
[root@localhost ~]# cat nginx.sh
#!/bin/bash
#

nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)
if [$nginx_process_num -eq 0];then
        systemctl start nginx
fi

expr

[root@localhost ~]# num1=17
[root@localhost ~]# num2=5
[root@localhost ~]# num3=`expr $num1 + $num2`
[root@localhost ~]# echo $num3
22

[root@localhost ~]# expr $num1 \* $num2
85

[root@localhost ~]# num3=$(($num1*$num2))
[root@localhost ~]# echo $num3
85

作者:Soulboy