---. 1 root root 51 1月 19 13:58 echo_test.sh
[root@centOS7 shell01]# ./echo_test.sh # 有了权限就直接运行
hello world


2.解释器直接运行(不需要给权限)

```shell
[root@centOS7 shell01]# chmod 644 echo_test.sh    # 把权限取消
[root@centOS7 shell01]# ll echo_test.sh           # 查看权限
-rw-r--r--. 1 root root 51 1月  19 13:58 echo_test.sh
[root@centOS7 shell01]# bash echo_test.sh         # 使用解释器运行shell脚本
hello world
[root@centOS7 shell01]# sh echo_test.sh           # 使用解释器运行shell脚本
hello world

shell中的特殊符号

~: 家目录  # cd ~ 代表进入用户家目录
!: 执行历史命令 !!执行上一条命令
$: 变量中取内容符
+ - * / %: 对应数学运算符 加 减 乘 除 取余
&: 后台执行
*: 星号是shell 通配符  匹配所有
?: 问号是shell通配符 匹配除回车以外的一个字符
;: 分号可以在shell中一行执行多个命令,命令之间用分号隔开
|: 管道符,上一个命令的输出作为下一个命令的输入 cat filename | grep "abc"
\: 转义字符
[root@centOS7 shell01]#  expr 3 * 3
expr: 语法错误
[root@centOS7 shell01]#  expr 3 \* 3    #进行转义,转成乘号
9
``: 反引号 命令中执行命令 echo "today is 	`date+%F`"
'': 单引号,脚本中字符串要用单引号引起来,但是不同于双引号的是,	单引号不解释变量
"": 双引号 脚本中出现的字符串可以用双引号引起来

shell中的管道应用

管道符|:很多组合命令都需要通过管道来实现完成输出,管道符其实就是下一个命令对上一个命令的输出做处理。

[root@centOS7 shell01]# cat /etc/passwd | grep "root"  #将检索出来的信息通过管道给grep,通过筛选“root”打印出结果
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

shell重定向

>  重定向输入   覆盖原数据
>> 重定向追加输入,在原数据的末尾添加
<  重定向输出   wc  -l < /etc/passwd
<< 重定向追加输出  fdisk /dev/sdb <<EOF   .........   EOF
# >    会覆盖原有的数据
[root@centOS7 shell01]# echo hello haha > ./text.txt
[root@centOS7 shell01]# cat text.txt
hello haha
[root@centOS7 shell01]# echo world > ./text.txt
[root@centOS7 shell01]# cat text.txt
world 
# >>   在原有的数据末尾追加
[root@centOS7 shell01]# echo world >> ./text.txt
[root@centOS7 shell01]# echo world >> ./text.txt
[root@centOS7 shell01]# cat text.txt
world
world
world
# <
[root@centOS7 shell01]# wc < text.txt
 3  3 18
[root@centOS7 shell01]# wc text.txt
 3  3 18 text.txt

shell数学运算

expr命令:只能做整数运算,格式比较古板,运算符与数字之间需要空格
[root@centOS7 shell01]# expr 1 + 2
3
[root@centOS7 shell01]# expr 1 - 2
-1
[root@centOS7 shell01]# expr 10 * 3   #必须进行转义
expr: 语法错误
[root@centOS7 shell01]# expr 10 \* 3
30
[root@centOS7 shell01]# expr 10 % 3
1

使用bc计算器处理浮点运算,scale=2代表小数点保留两位
[root@centOS7 shell01]# echo "scale=2;3+100"|bc    #脚本中使用管道符进行计算,控制台使用bc命令直接进入交互模式计算
103
[root@centOS7 shell01]# echo "scale=2;100-2"|bc
98
[root@centOS7 shell01]# echo "scale=2;100/3"|bc
33.33
[root@centOS7 shell01]# echo "scale=2;100*3"|bc
300
[root@centOS7 shell01]# 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'. 
scale=3
90/27
3.333

使用let命令也可以
[root@centOS7 shell01]# let sum=7+9
[root@centOS7 shell01]# echo $sum
16
使用(())
[root@centOS7 shell01]# echo $((1+9))
10
[root@centOS7 shell01]# echo $((2*9))
18
[root@centOS7 shell01]# echo $((9/2))
4
[root@centOS7 shell01]# echo $((100%3))
1
[root@centOS7 shell01]# echo $((100**3))   # 100的三次方
1000000

随机数

$RANDOM # 取值范围 0-32767

条件测试命令

test expression  | [ expression ] | [[ expression ]]
# expression前后必须有空白字符
状态码$?true返回0,否则返回1

# 变量测试
-v VAR 查看变量VAR是否定义
[ -v VAR ]

# 数值测试
-gt 是否大于
-ge	大于等于
-eq	等于
-ne	不等于
-lt	小于
-le	小于等于

# 字符串测试
-z "STRING" 字符串是否为空,空为真,不空为假
-n "STRING" 字符串是否不空,不空为真,空为假 
= 是否等于
!= 是否不等于
> ascii码是否大于ascii码
< 是否小于
== 左侧字符串是否和右侧的PATTERN相同
 注意:此表达式用于[[ ]]中,PATTERN为通配符
=~ 左侧字符串是否能够被右侧的PATTERN所匹配
 注意: 此表达式用于[[ ]]中;扩展的正则表达式
 
#文件测试-存在性测试
-a FILE:同 -e
-e FILE: 文件存在性测试,存在为真,否则为假
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件
比如:[ -d /etc ]
# 文件测试-权限测试
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
# 文件测试-属性测试
-s FILE: 是否存在且非空
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2
# 组合测试条件
[ EXPRESSION1 -a EXPRESSION2 ] 并且
[ EXPRESSION1 -o EXPRESSION2 ] 或者
[ ! EXPRESSION ] 取反

关于()和{}

( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash 
搜索(list)
{ list; } 不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }
范例: () 和 {}
[root@centos8 ~]# name=mage;(echo $name;name=wang;echo $name );echo $name
mage
wang
mage
[root@centos8 ~]# name=mage;{ echo $name;name=wang;echo $name; } ;echo $name
mage
wang
wang

退出脚本

exit NUM  退出脚本,释放系统资源,NUM代表一个整数,代表返回值 ,num范围为1-255
[root@centOS7 shell01]# cat exit_code.sh 
#!/usr/bin/bash
echo "hello world"
expr 6 \* 8
exit 178
[root@centOS7 shell01]# bash exit_code.sh 
hello world
48
[root@centOS7 shell01]# echo $?        # 输出上一个命令的返回值(退出码)
178
echo $?:
0表示成功(Zero - Success)
非0表示失败(Non-Zero  - Failure)

脚本调试

bash -n 脚本  # 检测脚本中的语法错误
bash -x 脚本	# 调试执行

shell格式化输出

一个程序需要有0个或以上输入,一个或多个输出

echo命令

功能:将内容输出搭配默认显示设备

#   echo命令的功能是在显示器显示一段文字,一般起到一个提示的作用。
语法:echo[-ne][字符串]
#  补充说明:echo会将输入的字符串送往标准输出,输出的字符串间以空格字符分开,并在最后加上换行符。
命令选项:
-n :不在最后自动换行
-e :若字符串中出现以下字符,则特别加以处理,而不会当做一般文字输出

转义字符:

\a  发出警告声
\b  删除前一个字符
\c  最后不加上换行符号
\f  换行但光标仍旧停留在原来的位置
\n  换行且光标移至行首
\r  光标移至行首,但不换行
\t  插入tab
\v  与\f相同
\插入\字符
\nnn  插入nnn,八进制所代表的ASCll字符
-help  显示帮助
-version 显示版本信息
[root@centOS7 shell01]# echo -n "date:";date
date:2021年 01月 20日 星期三 10:44:31 CST

[root@centOS7 shell01]# vim fruits.sh
#!/bin/bash
echo -e "\t\t\t\tFruits Shop"
echo -e "\t1) Apple"
echo -e "\t2) Banana"
echo -e "\t3) Orange"

[root@centOS7 shell01]# bash fruits.sh 
                                Fruits Shop
        1) Apple
        2) Banana
        3) Orange

颜色代码

脚本中echo显示内容带颜色显示。echo显示带颜色需要使用参数-e

格式:echo -e “\033[字背景颜色;字体颜色m 字符串\033[0m”
例子:
echo -e “\033[30m 黑色字 \033[0m”
echo -e “\033[31m 红色字 \033[0m”
echo -e “\033[32m 绿色字 \033[0m”
echo -e “\033[33m 黄色字 \033[0m”
echo -e “\033[34m 蓝色字 \033[0m”
echo -e “\033[35m 紫色字 \033[0m”
echo -e “\033[36m 天蓝字 \033[0m”
echo -e “\033[37m 白色字 \033[0m”

echo -e “\033[40;37m 黑底白字 \033[0m”	
echo -e “\033[41;37m 红底白字 \033[0m”
echo -e “\033[42;37m 绿底白字 \033[0m”
echo -e “\033[43;37m 黄底白字 \033[0m”
echo -e “\033[44;37m 蓝底白字 \033[0m”
echo -e “\033[45;37m 紫底白字 \033[0m”
echo -e “\033[46;37m 天蓝底白字 \033[0m”
echo -e “\033[47;30m 白底黑字 \033[0m”

\033[0m 关闭所有属性
\033[1m 设置高亮度
\033[4m 下划线
\033[5m 闪烁
\033[7m 反显
\033[8m 消隐
\033[30m – \033[37m 设置前景色
\033[40m – \033[47m 设置背景色
\033[nA 光标上移n行
\033[nB 光标下移n行
\033[nC 光标右移n行
\033[nD 光标左移n行
\033[y;xH设置光标位置
\033[2J 清屏
\033[K 清除从光标到行尾的内容
\033[s 保存光标位置
\033[u 恢复光标位置
\033[?25l 隐藏光标
\033[?25h 显示光标

shell基本输入

read命令

默认接受键盘的输入,回车符代表输入结束
read命令选项:
	-p 打印信息
	-t N 限定timeout时间为N
	-s 不回显,用于密码
	-n 限定输入字符个数
#!/bin/bash
clear
echo -n -e "Login: "
read login
echo -n -e "Password: "
read pass

echo  "login: $login     password:$pass"

shell变量

变量介绍

在编程中,总有一些临时数据需要临死存放在内存中,以待后续使用时快速读出。内存在系统启动的时候被按照1B一个单位编号(16进制编号),并对内存的使用情况做记录,保存在内存跟踪表中。
计算机单位
1B=8bit
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024EB
1ZB=1024EB
image-20210120165326559

变量分类

1.本地变量:用户私有变量,只有本用户可以使用,保存在家目录下的.bash_profile、.bashrc文件中
2.全局变量:所有用户都能使用,保存在/etc/profile、/etc/bashrc文件中
3.用户自定义变量:用户自定义,比如脚本中的变量

定义变量

变量格式

变量格式:变量名=值
##  注意:在shell中的变量名和等号之间不能有空格
变量命名规则:
	命名只能使用英文字母、数字和下划线,首个字符不能以数字开头
	中间不能有空格
	不能使用标点符号
	不能使用bash里的关键字
比如:name='ketty' score=88.8 age=18  var1=1
值可以是以下形式:
	name='root'
	name="$USER"
	name=`COMMAND` 或 name=$(COMMAND)

读取变量

读取变量内容:
	$变量名
[root@centOS7 shell01]# name='hello ketty'
[root@centOS7 shell01]# echo $name
hello ketty

取消变量unset和显示已定义的变量set

set
[root@centOS7 shell01]# unset name
[root@centOS7 shell01]# echo $name      #  打印出来的是null	

定义全局变量export

export name='hello'

上述变量都是一次性变量,系统重启就会丢失。如果希望本地变量或者全局变量可以永久使用,可以将需要设置的变量写入变量文件。

定义永久变量

本地变量:用户私有变量,只有本用户可以使用,保存在家目录的.bash_profile、.bashrc文件中
全局变量:所有用户都可以使用,保存在/etc/profile、/etc/bashrc中
本地变量:
	[root@centOS7 shell01]# tail -l ~/.bash_profile
全局变量:
	[root@centOS7 shell01]# tail -l /etc/profile

bash内的环境变量

PATH
PWD
SHELL
USER
UID
HOME
SHLVL
LANG
MAIL
HOSTNAME
HISTSIZE

位置变量

$1 $2....对应第一个、第二个参数
$0	命令本身,包括路径
$*	传递给脚本的所有参数,全部参数合为一个字符串
$@	传递给脚本的所有参数,每个参数为独立字符串
$#	传递给脚本的参数的个数
清空所有位置变量:set --

变量扩展

``	反引号,命令替换
\	反斜杠,禁止单个字符扩展
!	感叹号,历史命令替换

shell数组

数组语法

数组名称=(元素1  元素2  元素3)   元素以空格分开

数组读出

${数组名称[索引]}
索引默认从0开始
[root@centOS7 shell01]# student=(ketty xiaofei  daye)
[root@centOS7 shell01]# echo ${student[0]}
ketty
[root@centOS7 shell01]# echo ${student[2]}
daye

查看数组

declare -a
[root@centOS7 shell01]# declare -a 
declare -a student='([0]="ketty" [1]="xiaofei" [2]="daye")'

访问数组元素

echo ${array1[0]}    访问数组的第一个元素
echo ${array1[@]}    访问数组中的所有元素  等同于echo ${array1[*]}
echo ${#array1[@]}   统计数组元素的个数
echo ${!array1[@]}   获取数组元素的索引
echo ${array1[@]:1}  从数组下标1开始 
echo ${array1[@]:1:2}从数组下标1开始,访问两个元素
[root@centOS7 shell01]# echo ${student[0]}
ketty
[root@centOS7 shell01]# echo ${student[*]}
ketty xiaofei daye
[root@centOS7 shell01]# echo ${#student[@]}
3
[root@centOS7 shell01]# echo ${student[@]}
ketty xiaofei daye
[root@centOS7 shell01]# echo ${!student[@]}
0 1 2
[root@centOS7 shell01]# echo ${student[@]:1:2}
xiaofei daye

关联数组

关联数组可以允许用户自定义数组的索引

定义关联数组

# declare -A array1
# 声明一个关联数组  同时赋值多个
declare -A ass_array1
ass_array1=([name]='zhangshan' [age]='18')
echo ${ass_array1[name]}

# 声明一个关联数组  一个一个赋值
declare -A ass_array2
ass_array2[name]='lisi'
ass_array3[age]=19
echo ${ass_array2[name]}

shell流程控制-if判断语句

shell中的运算

数学比较运行

数学比较运算(比较的是整型)
-eq   等于
-gt   大于
-lt   小于
-ge   大于或等于
-le   小于或等于
-ne   不等于
	   INTEGER1 -eq INTEGER2
              INTEGER1 is equal to INTEGER2

       INTEGER1 -ge INTEGER2
              INTEGER1 is greater than or equal to INTEGER2

       INTEGER1 -gt INTEGER2
              INTEGER1 is greater than INTEGER2

       INTEGER1 -le INTEGER2
              INTEGER1 is less than or equal to INTEGER2

       INTEGER1 -lt INTEGER2
              INTEGER1 is less than INTEGER2

       INTEGER1 -ne INTEGER2
              INTEGER1 is not equal to INTEGER2


测试
[root@centOS7 local]# test 1 -eq 1;echo $?
0
[root@centOS7 local]# test 1 -gt 1;echo $?
1
[root@centOS7 local]# test 1 -ge 1;echo $?
0
[root@centOS7 local]# test 1 -lt 1;echo $?
1
[root@centOS7 local]# test 1 -le 1;echo $?
0
[root@centOS7 local]# test 1 -ne 1;echo $?
1

字符串比较运算

==		等于
!=		不等于
-n		检查字符串长度是否大于0
-z		检查字符串长度是否为0
####  记得加空格
[root@centOS7 shellstudy]# test $USER == "root";echo $? 
0

文件比较与检查

-d		#检查文件是否存在且为目录
-e		#检查文件是否存在(文件或者文件夹都可以)
-f		#检查文件是否存在且为文件
-r		#检查文件是否存在且可读
-s		#检查文件是否存在且不为空
-w		#检查文件是否存在且可写
-x		#检查文件是否存在且可执行
-O(大写O)#检查文件是否存在且被当前用户拥有
-G		#检查文件是否存在且默认组为当前用户组
file1 -nt file2  检查file1是否比file2新 
file1 -ot file2  检查file1是否比file2旧

[root@centOS7 shellstudy]# test -d shell01;echo $?
0
[root@centOS7 shellstudy]# test -r shell01/array1.sh;echo $?
0

逻辑运算

&&		逻辑与
||		逻辑或
!		逻辑非

赋值运算

=   赋值运算符

if语法

语句格式1  []中括号间一定要有空格
if [ condition ]    # condition值为false或true
	then
		commands
fi                  # 结束

语句格式2
if [ condition ]    # condition值为false或true
	then
		commands1
else
		commands2
fi                  # 结束

语句格式3
if [ condition1 ]    # condition值为false或true
	then
		commands1
elif [ condition2 ]
	then
		commands2
		............
else 
		commandx
fi                  # 结束



###  test
read NUM
if [ $NUM -eq 10 ]
  then
        echo "输入的`echo  $NUM`等于10"
elif [ $NUM -gt 10 ]
  then
        echo  "输入的`echo $NUM`大于10"
else
        echo  "输入的` echo $NUM`小于10"
fi

if高级应用

条件符号使用双圆括号,可以在条件中植入数学表达式
[root@centOS7 shell02_if]# cat if_avg.sh 
#!/bin/bash

if (( 100%3+1>1 ));then
        echo 'yes'
else
        echo 'no'
fi
[root@centOS7 shell02_if]# bash if_avg.sh 
yes
使用双方括号可以在条件中使用通配符
for i in ac ab ag rr rt rvv
    do 
        if [[ "$i" == r* ]]
           then
                echo "$i"
        fi
done
[root@centOS7 shell02_if]# bash if_avg.sh 
rr
rt
rvv

shell流程控制-for循环语句

for语法1

for var in value1  value2  ...
	do
		command
done

#### test
[root@centOS7 shell_for]# cat for_1.sh 
#!/bin/bash

for i in `seq 1 9`
  do
        echo "$i"
done 

for语法2

for((变量;条件;自增减运算))
	do
		commands
done
####### test
#!/bin/bash

for (( i=0;i<9;i++ ))
  do
    echo "$i"
done

无限循环
for ((;;))
  do 
    command
done

循环控制语句

#!/bin/bash
echo -n "倒计时:"
for i in `seq 9 -1 1`
    do
        echo -n  -e "\b$i"
        sleep 1
done
#  监控主机存活脚本

for (( ;; ))
  do 
     ping -c1  $1 &>/dev/null
     if [ $? -eq 0 ] 
        then 
           echo  "`date +"%F %H:%M:%S"` : $1 is up "
        else
           echo  "`date +"%F %H:%M:%S"` : $1 is down "
      fi
   # 控制脚本
   sleep 5
done    

continue跳过循环中的某次循环,break终止循环

[root@centOS7 shell_for]# cat continue.sh 
#! /bin/bash

for   (( i=0;i<10;i++ ))
   do 
     if  [ $i -eq 5 ]
       then 
          continue
     else
        echo $i
     fi
done
[root@centOS7 shell_for]# bash continue.sh 
0
1
2
3
4
6
7
8
9

shell流程控制-while循环语句

###  while循环语法
while [ condition ]
    do
      commands
done
## 使用while循环遍历文件夹内容
[root@centOS7 shell_for]# cat continue_1.sh 
#!/bin/bash

while   read i
  do  
        echo "$i"
done  <  $1

while循环控制与语句嵌套

# 嵌套 if for while
# 循环控制 sleep break continue
a1 () {
# 打印1-9 
i=1
while [ $i -lt 10 ]
 do 
   echo $i
   if [ $i -eq 5 ]
      then 
      break
   fi
   i=$((i+1))
done
}

a2 () {
# 打印1-9  当数值等于5 跳过当前循环
i=0
while [ $i -lt 10 ]
 do 
    i=$((i+1))
  if [ $i -eq 5 ]
      then
      continue
  fi
  if [ $i -eq 10 ]
    then 
     break
  else
   echo "$i"
   sleep 1
   fi
done
}

##  99乘法表
n=1
while [ $n -lt 10 ]
 do 
   for (( m=1;m<=$n;m++ )) 
    do 
       echo -n -e   " $m * $n =$((m*n))\t"
   done
   echo 
   n=$((n+1))
done

until语句

until介绍:和while正好相反,until是条件为假时开始执行,条件为真时停止执行
##   until语法
until [ condition ]
   do
      commands
done
##  until案例
#!/bin/bash

n=10
until [ $n -gt 20 ]
 do 
    echo $n
    n=$((n+1))
    sleep 1
done

case多条件分支语句

## case语法
case 变量1  in
条件1)
	执行代码1
;;
条件2)
	执行代码2
;;
  .......
esac
## case案例1
[root@centOS7 shell_case]# cat case_test.sh 
#!/bin/bash

read -p "NUM:" num
case $num in
1)
    echo "haha"
;;
2)
    echo "hehe"
;;
3)
    echo "heihei"
;;
*)
    echo "bye"
;;
esac
## case案例2
[root@centOS7 shell_case]# cat case_in.sh 
#!/bin/bash

case $1 in
zmn | ZMN)
    echo  "你好,丈母娘"
;;
lzr|LZR)
      echo "你好,老丈人"
;;
*)
      echo "USE: $0 zmn|lzr"
;;
esac

[root@centOS7 shell_case]# bash case_in.sh  zmn
你好,丈母娘
[root@centOS7 shell_case]# bash case_in.sh  LZR
你好,老丈人

shell特殊变量

##  特殊参数
$*   代表所有参数,其间隔为IFS内定参数的第一个字元
$@   与*类同,不同之处在于不参照IFS
$#   代表参数数量
$?   执行上一个指令的返回值
$-   最近执行的foreground pipeline的选项参数
$$   本身的process ID 进程id
$    执行上一个背景指令的PID
$_   显示出最后一个执行的命令
$N   shell的第几个外传参数
### 测试
[root@centOS7 shell_case]# cat shell_variable.sh 
#!/bin/bash
echo  "脚本的名字是:  $0"
echo  "脚本的参数是:  $*"
echo  "传参数量:$#"
echo  "脚本执行进程号:$$"
echo  "最后执行命令:$_"
echo  "第二个参数是: $2"

[root@centOS7 shell_case]# bash shell_variable.sh aa bb vv ff gg
脚本的名字是:  shell_variable.sh
脚本的参数是:  aa bb vv ff gg
传参数量:5
脚本执行进程号:43808
最后执行命令:脚本执行进程号:43808
第二个参数是: bb

shell函数

###  函数优点
1.代码模块化,调用方便,节省内存
2.代码模块化,代码量少,排错简单
3.代码模块化,可以改变代码的执行顺序
###  函数语法1
函数名  () {
   代码块
   return  N
}
###  函数语法2
function  函数名{
   代码块
   return N
}
[root@centOS7 function_test]# cat function_test1.sh 
#!/bin/bash
# 定义函数
start1 () {
   echo "apache  start ......    [OK]"
   return  0
}
function end1 {
   echo  "apache end .........  [OK]"
}
# 调用函数
start1
end1

nginx启动关闭重启脚本

[root@centOS7 function_test]# cat nginx_install.sh 
#!/bin/bash

#variable 变量
nginx_install_doc=/usr/local/nginx
nginxd=$nginx_install_doc/sbin/nginx
pid_file=$nginx_install_doc/logs/nginx.pid

#source function library
if [ -f  /etc/init.d/functions ]
  then
      . /etc/init.d/functions
  else
     echo "not found  /etc/init.d/functions file"
     exit
fi
###  -f 判断此文件是否存在 pid_file是nginx的进程文件,里面存储进程号
 if [ -f $pid_file ]           
    then
       nginx_process_id=`cat $pid_file`
       nginx_process_num=`ps aux | grep $nginx_process_id | grep -v "grep" | wc -l`
   fi

# function  函数
start (){
  # 判断nginx是否启动
  if [ -f $pid_file ] && [ $nginx_process_num -ge 1 ]
    then
         echo "nginx running ......"
   else
      if [ -f $pid_file ] && [ $nginx_process_num -lt 1 ]
        then 
           #  删除进程文件
           rm -f $pid_file
           # 重启nginx    
           echo "nginx start ` daemon $gninxd` " 
      fi
     echo "nginx start  `daemon  $nginxd`"
  fi
}

stop () {
   if [ -f $pid_file ] && [ $nginx_process_num -ge 1 ]
    then
      action "nginx stop"  killall -s QUIT nginx 
      rm -f $pid_file
   else 
     action "nginx stop"  killall -s QUIT nginx  2>/dev/null
fi
}

restart () { 
   stop 
   sleep 1
   start
}
reload () {
    if [ -f $pid_file ] && [ $nginx_process_num -ge 1 ]
    then
      action "nginx stop"  killall -s HUP nginx
      rm -f $pid_file
   else
     action "nginx stop"  killall -s HUP nginx  2>/dev/null
fi

}
status () {
   if [ -f $pid_file ] && [ $nginx_process_num -ge 1 ]
     then
        echo "nginx running ....."
    else
       echo "nginx stop ......."
fi
}

case $1 in
start) start;;
stop) stop;;
restart) restart;;
status)  status;;
reload)  reload;;
*)   echo "USE:  $0 start stop restart reload status";;
esac

正则表达式

#  正则表达式介绍
  正则表达式是一种文本模式匹配,包括普通字符(a-z)和特殊字符(元字符)。它是一种字符串匹配模式,可以用来检查一个字符串是否含有某种子串,将匹配的子串替换或者从某个字符串中取出某个条件的子串。
  shell也支持正则表达式,但不是所有的命令都支持正则表达式,常	见的命令只有grep、sed、awk命令支持正则表达式
### 特殊字符
定位符使用技巧:同时锚定开头和结尾,做精确匹配;单一锚定开头和结尾,做模糊匹配。
定位符						          说明
^                          锚定开头^a以a开头 ,默认锚定一个字符
$                          锚定结尾$a以a结尾 ,默认锚定一个字符  
#####  测试   egrep  等价于 grep -E
[root@centOS7 regular_expression]# egrep "^ac$" file   ###匹配以a开头,以c结尾的字符串
ac
## 匹配符  匹配字符串
.     匹配除回车以外任意字符
()    字符串分组
[]    定义字符类,匹配括号中的一个字符
[^]   表示否定括号中出现字符类中的字符,去翻
\     转义字符 
|     管道

[roo t@centOS7 regular_expression]# egrep "^(a|b)c$" file
ac
bc
[root@centOS7 regular_expression]# egrep "^a[0-9]c$" file
a3c
[root@centOS7 regular_expression]# egrep "^a[^0-9]c$" file
acc
abc
a_c
[root@centOS7 regular_expression]# egrep "^a.c$" file
acc
abc
a_c
aZc
a c
[root@centOS7 regular_expression]# egrep "^a\*c$" file     使用\进行转义
a*
##  限定符:对前面的字符或者字符串做限定说明
*        某个字符之后加星号表示该字符不出现或出现多次,只要出现就都是这个字符
?        与星号相似,表示该字符出现一次或不出现
+        与星号相似,表示前面的字符出现一次或多次,但必须出现一次
{n,m}    某个字符之后出现,表示该字符最少n次,最多m次
{m}      正好出现m次

  ### 测试
[root@centOS7 regular_expression]# egrep "^ab*c$" file
ac
abbc
abbbc
abc
[root@centOS7 regular_expression]# egrep "^ab?c$" file
ac
abc
[root@centOS7 regular_expression]# egrep "^ab+c$" file
abbc
abbbc
abc
[root@centOS7 regular_expression]# egrep "^ab{1,2}c$" file
abbc
abc
[root@centOS7 regular_expression]# egrep "^ab{2}c$" file
abbc
###POSIX特殊字符

image-20210128102146320

[root@centOS7 regular_expression]# egrep "^a[[:digit:]]c$" file
a3c
[root@centOS7 regular_expression]# egrep "^a[[:alpha:]]c$" file
acc
abc
aZc
apc
[root@centOS7 regular_expression]# egrep "^a[[:alnum:]]c$" file
acc
abc
aZc
a3c
apc
## IP地址的正则表达式  x.x.x.x
"^((25[0-5]|2[0-4][[:digit:]]|[01]?[[:digit:][[:digit:]]?).){3}(25[0-5]|2[0-4][[:digit:]]|[01]?[[:digit:][[:digit:]]?)"
### 分解((25[0-5]|2[0-4][[:digit:]]|[01]?[[:digit:][[:digit:]]?).){3}
25[0-5]                        250-255
2[0-4][[:digit:]]              200-249
[01]?[[:digit:][[:digit:]]?    0-199
{3}                            出现三次

shell对文件操作

###   sed命令
sed是linux中提供的一个外部命令,它是一个行(流)编辑器,非交互式的对文件内容进行增删改查的操作,使用者只能在命令行输入编辑命令、指定文件名,然后在屏幕上查看输出。它和文本编辑器有本质的区别。
文本编辑器:编辑对象是文件
行编辑器:编辑对象是文件中的行

image-20210128105608163

sed语法:sed [options] '{commands}[flags]'[filename]
命令选项(options):
	-e script  将脚本中指定的命令添加到处理输入时执行的命令中,多条件,一行中有多个操作
	-f script  将文件中指定的命令添加到处理输入时执行的命令中
	-n         抑制自动输出   只会打印需要打印的行
	-i         编辑文本内容,直接改变原文件内容,不打印
	-i.bak     修改时同时创建.bak备份文件,原文件不改变,备份文件为修改后文件
	-r         使用扩展的正则表达式
	!          取反(跟在模式条件后与shell有所区别)
sed常用内部命令(commands):
	a		在匹配后面添加(追加)
	i		在匹配前面添加(插入)
	p		打印
	d		删除
	s		查找替换  只替换第一次查找到的匹配字符串
	c		更改
	y		转换 N D P
### 测试
[root@centOS7 shell_sed]# sed 'aHello world' data   ### 每一行后面添加hello world(换行后添加)
[root@centOS7 shell_sed]# sed '3aHello world' data  ### 第三行后面添加  
[root@centOS7 shell_sed]# sed '2,4aHello world' data  ###第二到四行添加
[root@centOS7 shell_sed]# sed '/3  the/a\Hello world' data   ###在//中将添加匹配字符串
[root@centOS7 shell_sed]# sed 'i\Hello world' data  ###在每行前面添加
[root@centOS7 shell_sed]# sed 'd' data               ### 删除所有行
[root@centOS7 shell_sed]# sed '3d' data              ### 删除第三行
[root@centOS7 shell_sed]# sed -r '/(^#|#|^$)/d' nginx.conf  ##删除所有#开头、包含#、空格的所有行
[root@centOS7 shell_sed]# sed 's/dog/cat/' data   ##将所有dog换为cat
[root@centOS7 shell_sed]# sed '/3  the/s/dog/cat/' data ##把第三行的dog换为cat
[root@centOS7 shell_sed]# sed 'y/abcdef/ABCDEF/' data  ##把a转换成A,把b转换成B...把f转换成F

flags:
	数字   表示新文本替换的模式
	g     表示用新文本替换现有文本的全部实例
	p     表示打印原始内容
	w filename   将替换的结果写入文件
	
[root@centOS7 shell_sed]# sed 's/dog/cat/2' data ##把每一行第二个dog换为cat
[root@centOS7 shell_sed]# sed 's/dog/cat/g' data ##把每一行所有dog换为cat
[root@centOS7 shell_sed]# sed 's/dog/cat/w newfile' data ##把每一行第二个dog换为cat,写入新文件
[root@centOS7 shell_sed]# sed -e 's/dog/cat/;s/brown/green/' data  # -e支持多条件,多操作
sed小技巧:
$=  统计文本有多少行
=   打印文本内容时加上行号
[root@centOS7 shell_sed]# sed -n '$=' data
5
[root@centOS7 shell_sed]# sed  '=' data
1
1  the quick brown fox jumps over the lazy dog
2
2  the quick brown fox jumps over the lazy dog
3
3  the quick brown fox jumps over the lazy dog
4
4  the quick brown fox jumps over the lazy dog
5
5  the quick brown fox jumps over the lazy dog

shell对输出流的处理

[root@centOS7 shellstudy]# head /proc/meminfo   #计算机内存信息
MemTotal:        1867048 kB
MemFree:         1001308 kB
MemAvailable:    1228012 kB
Buffers:            2116 kB
Cached:           348292 kB
SwapCached:            0 kB
Active:           332572 kB
Inactive:         290484 kB
Active(anon):     273604 kB
Inactive(anon):     9628 kB
[root@centOS7 shell_awk]# head -3 /proc/meminfo | awk 'NR==1{print $2}'
1867048

awk介绍

awk介绍
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk的工作方式是读取数据,将每一行数据视为一条记录(record),每条记录以字段分隔符分成若干字段,然后输出各个字段的值。
awk语法:[options][BEGIN]{program}[END][file]
options命令选项:
	-F  fs         指定描述一行中数据字段的文件分隔符。默认是空格
	-f  file       指定读取程序的文件名
	-v  var=value  定义awk程序中使用的变量和默认值
#注意:awk程序脚本由左大括号和右大括号定义,脚本命令必须放在两个大括号之间。由于awk命令行假脚本是单文本字括在单引号中。
awk运行优先级:
	1)BEGIN:在开始处理数据流之前执行,可选项
	2)program:如何处理数据流,必选
	3)END:处理完数据流后执行,可选。

awk基本用法

awk对字段(列)的提取

字段提取:提取一个文本中的一列数据并打印输出
字段相关内置变量
	$0  表示整行文本
	$1  表示文本行中第一个数据字段
	$2  表示文本行中第二个数据字段
	$N  表示文本行中第N个数据字段
	$NF 表示文本行中最后一个数据字段

[root@centOS7 shell_awk]# awk '{print $1}' data
1
2
3
4
5
[root@centOS7 shell_awk]# awk '{print $NF}' data
dog
[root@centOS7 shell_awk]# awk 'NR==3{print $1,$3,$5}' data  # 打印第三行1,3,5列
3 quick fox
[root@centOS7 shell_awk]# awk 'NR==3{print $1 "-" $3 "-" $5}' data
3-quick-fox

awk对行(记录)的提取

记录提取:提取一个文本中的一列数据并打印输出
提取的方法有两种:通过行号;通过正则匹配
记录相关内置变量
	NR  指定行号
# 打印第三行所有
[root@centOS7 shell_awk]# awk 'NR==3{print $0}' data
3  the quick brown fox       jumps over the lazy dog

awk执行优先级

[root@centOS7 shell_awk]# awk 'BEGIN{print "begin"}NR==3{print $1,$3}END{print "end"}' data
begin
3 quick
end

awk高级用法

awk定义数组

数组定义方式:数组名[索引]=值
[root@centOS7 shell_awk]# awk 'BEGIN{array1[0]="hello";print array1[0]}' 
hello

awk运算

1.赋值运算 =
2.比较运算 >  >=  <  <=  == !=
3.数学运算 + - * / % ** ++ --
4.逻辑运算 &&  ||
5.匹配运算 ~ !~  模糊匹配
1.赋值运算
变量运算:name=""  数组赋值:array[1]=100
[root@centOS7 shell_awk]# awk 'BEGIN{array1[0]="hello";print array1[0]}' 
hello
[root@centOS7 shell_awk]# awk 'BEGIN{name="hello";print name}' 
hello
2.比较运算
如果比较的是字符串则按ASCII编码顺序表比较,结果为真返回1,结果为假返回0
[root@centOS7 shell_awk]# awk 'BEGIN{ print "a" >= "b" }' 
0
[root@centOS7 shell_awk]# awk 'BEGIN{ print "a" <= "b" }' 
1
[root@centOS7 shell_awk]# awk 'BEGIN{ print 100!=400 }' 
1
[root@centOS7 shell_awk]# awk 'BEGIN{ print 1+8 }' 
9
[root@centOS7 shell_awk]# awk 'BEGIN{ print 100>=2 && 100>=3 }' 
1
[root@centOS7 shell_awk]# awk 'BEGIN{ print 100<2 || 100<3 }' 
0
[root@centOS7 shell_awk]# awk 'BEGIN{count=1; print ++count }' 
2
[root@centOS7 shell_awk]# awk -v count=0 'BEGIN{count--; print count }' 
-1

awk环境变量

FIELDWIDTHS  以空格分隔的数字列表,用空格定义每个数据字段的精确宽度
FS           输入字段分隔符号
OFS          输出字段分隔符号
RS           输入记录分隔符号
ORS          输出记录分隔符号
FIELDWIDTHS:重定义列宽并打印,不可以使用$0打印所有
[root@centOS7 shell_awk]# awk 'BEGIN{FIELDWIDTHS="5"}NR==1{print $1}' data 
1  th
[root@centOS7 shell_awk]# awk 'BEGIN{FS="fox"}NR==1{print $1}' data    # 以fox为分隔符
1  the quick brown
[root@centOS7 shell_awk]# awk 'BEGIN{FS="fox";OFS="-"}NR==1{print $1,$2}' data # 以-为分隔符输出
1  the quick brown - jumps over the lazy dog

awk流程控制

1.if判断语句
2.for循环语句
3.while循环语句
4.do...while语句
5.循环控制
if语句
[root@centOS7 shell_awk]# awk '{if($1>5) print $1}' num
6
7
8
9
10
[root@centOS7 shell_awk]# awk '{if($1<5) print $1*2 ;else if($1>5)print $1-2}' num
2
4
6
8
4
5
6
7
8
for语句
[root@centOS7 shell_awk]# cat num1
1 2 3
4 5 6
7 8 9
[root@centOS7 shell_awk]# awk '{sum=0;for(i=1;i<4;i++){sum+=$i}print sum}' num1
6
15
24
while语句
[root@centOS7 shell_awk]# cat num1
1 2 3
4 5 6
7 8 9
[root@centOS7 shell_awk]# awk '{sum=0;i=1;while(i<4){sum+=$i;i++}print sum}' num1
6
15
24
do while语句
[root@centOS7 shell_awk]# cat num1
1 2 3
4 5 6
7 8 9
[root@centOS7 shell_awk]# awk '{sum=0;i=1;do{sum+=$i;i++}while(i<4);print sum}' num1
6
15
24
控制循环
[root@centOS7 shell_awk]# cat num1
1 2 3
4 5 6
7 8 9
[root@centOS7 shell_awk]# awk '{sum=0;i=1;while(i<4){sum+=$i;if(sum>6){break};i++}print sum}' num1
6
9
7

awk小技巧

# 打印行数
[root@centOS7 shell_awk]# awk 'END{print NR}' num1
3
# 打印最后一行文本
[root@centOS7 shell_awk]# awk 'END{print $0}' num1
7 8 9
# 打印文本列数
[root@centOS7 shell_awk]# awk 'END{print NF}' num1
3