Linux运维 第二阶段 (九)shell编程

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

shell编程:

一、知识点:

1、相关概念:

1)脚本编程

#bash -n  SCRIPT_FILE(判断脚本是否有语法错误)

#bash -x  SCRIPT_FILE(判断脚本是否有语法错误,并详细列出执行的每一个步骤)

#basename /root/sum.shstrip directory and suffix from filenames直接取路径的基名(文件名),脚本中常用#basename  $0

编译器、解释器

2)编程语言:机器语言、汇编语言、高级语言

静态语言:编译型语言、强类型(变量在使用前必须事先说明,甚至还需初始化)、执行前先编译,要事先转换好,如:CC++JAVAC#

动态语言:解释型语言、弱类型(变量用时声明,甚至不区分类型)、边解释边执行(ON THE FLY),如:ASPPHPSHELLPYTHONPERL

面向过程:LINUX的内核是面向过程的C语言,SHELL脚本;

面向对象:JAVAPYTHON

注:PERLC++既面向过程,也面向对象;

3)生成随机数:#echo  $RANDOMbash内部自动维护的,生成数在0-32768之间;随机数生成器:/dev/random,/dev/urandom,默认都到熵池中去取随机数,若被取空,ramdom会停下来等待生成更多的随机数,所以会阻塞用户,urandom会用软件自动生成。

 

2、变量:内存空间(编址的存储单元);

十进制数10:字符型存:16bit;数值型存:8bit

变量类型(事先确定数据的存储格式和长度):字符型、数值型(整型、浮点型)、布尔型(真假);

整型:8bit0255,若存256则会溢出;缓冲区溢出:(精心设计的溢出——网络攻击);

 

变量名称:只能包含字母、数字、下划线,且不能以数字开头;不能与系统中存在的环境变量重名;最好做到见名知义;

变量赋值:VAR_NAME=VALUE

 

逻辑运算:与&、或|、非!、异或^

短路逻辑运算:知道其中一个就知道其结果,如:对于与,其中一个为假,结果就为假;对于或,其中一个真,结果就为真;

 

3bash变量类型:环境变量、本地变量(局部变量)、位置变量($1,$2,...)、特殊变量($?,$*,$#,$@;

环境变量:作用域为当前SHELL进程及其子进程;脚本在执行时会启动一个子SHELL进程;命令行中启动的脚本会继承当前SHELL环境变量;系统自动执行的脚本(非命令行启动)就需要自我定义需要的各环境变量;#export  VAR_NAME=VALUE赋值并声明为环境变量;

本地变量:作用域为整个BASH进程;

局部变量:作用域为当前代码段;

位置变量:$1,$2,$3,....引用脚本的参数;

特殊变量:$?(上一个命令执行状态的返回值),程序执行完,可能有两类返回值(程序的执行结果、程序状态返回代码(其中0为正确执行,1255为错误执行)),写脚本时可自定义程序退出的代码;127为命令错误,2为参数错误;$@$*$#(参数的个数)

#id root  &>  /dev/null

#echo $?

 

引用变量:${VAR_NAME},花括号有时可省去,但下列情形花括号不能省,

#animal=pig

#echo “There are some ${animal}s.”  (注意单双引号的区别)

 

撤销变量:#unset  VAR_NAME  (不是操作变量的值,就不需加$

查看变量:#set  (查看当前SHELL所有变量)

#printenv (以下三个都是查看环境变量)

#env

#export

 

4、脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序

#!/bin/bash(此句必须是文件的第一行,shabang魔数)

#which bash

#file /bin/ls  ELF可执行可链接的文件格式)

执行脚本:一、赋予可执行权限,用绝对路径执行;二、#bash  脚本文件

 

条件测试类型:整数测试、字符串测试、文件测试

条件测试的表达式:[  expression  ][[  expression ]]test  expression

整数测试:-eq,-ne,-gt,-lt,-ge,-le

字符串测试:==,!=,-n  string(空为真),-z  string(不空为真)

文件测试:-e,-f,-d,-r,-w,-x

#bash -n  script.sh  (测试脚本是否有语法错误)

#bash -x  script.sh  (测试脚本是否有语法错误,每一步执行都显示出来)

 

命令间的逻辑关系:逻辑与&&、逻辑或||

&&:前一个语句假后一个语句不执行,前一个语句真后一个语句执行;

||:前一个语句假后一个语句执行,前一个语句真后一个语句不执行;

举例:

#! id  user1  && useradd  user1  || echo  “user1  exists!”

#! id  user1  && useradd  user1  && echo  “user1”  | passwd  --stdin  user1 ||  echo  “user1 exists”

 

组合测试条件:

-a(与关系)

-o(或关系)

!(非关系-not

举例:[  !  \( $1  ==  ‘q’  -o  $1 ==  ‘quit’  -o $1  ==  ‘Q’ \)  ]

 

算术运算:

#A3

#B6

#let c=$A+$B  (第一种方式,#help  let

#d=$[$A+$B]  (第二种方式)

#e=$(($A+$B))  (第三种方式)

#f=`expr $A  +  $B`  (第四种方式,expr算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用,#g=$(expr  $A  +  $B)

注:shell默认所有类型均为字符串,不能做算术运算。

 

常用的赋值表达式:

i+=1(类似于i++;i-=1(i--);i*=1;i/=1;i%=1

++i;--i

 

 

5、脚本编程知识点:

1)顺序结构(按行依次写命令即可,若一行执行多个语句用分号分隔)

2)选择结构:if单分支、双分支、多分支;case语句

3)循环结构:forwhileuntil

4)函数

5)截取路径:#man  bash

${parameter#*word}从左至右截取;

${parameter##*word}

${parameter%*word}从右至左截取;

${parameter%%*word}

例如1#FILE=’/usr/local/src’

#echo ${FILE#*/}结果为/usr/local/src

#echo ${FILE##*/}结果为src

#echo ${FILE%/*}结果为/usr/local,此项常用,用于自动复制命令及命令的库文件的脚本

#echo ${FILE%%/*}结果为空

例如2#A=`stty  -F  /dev/console size`显示屏幕大小

#echo ${A#*  }

#echo ${A%  *}

 

6#echo  ${#VARNAME}列出变量所包含的的字符串长度

例如:#echo  ${#FILE}结果为14

 

7)变量赋值:

${parameter:-word}如果parameter为空或未定义,则变量展开为word;否则展开为parameter的值;

${parameter:+word}如果parameter为空或未定义,不做任何操作;否则展开为word值;

${parameter:=word}如果parameter为空或未定义,则变量展开为word;并将展开的值赋给parameter

${parameter:offset}

${parameter:offset:length}取子串,从offset处的后一个字符开始,取length长度的子串。

例如:#echo  ${A:-30}A为空,则展开为30)常用

#echo ${A:+30}A为空则空,此项可用来判断A是否有数据)

#echo ${A:=30}A为空,30赋值给A

#A=’hello world’

#echo ${A:2}(显示结果为llo  world

#echo ${A:2:3}(显示结果为llo

 

8/etc/rc.d/init.d/服务脚本

/etc/sysconfig/服务脚本同名的配置文件

 

9)局部变量:

local VARNAME=VALUE

比较有local和无local的差别,变量的作用域之间是如何影响的,例如:

#!/bin/bash

#

a=1

test() {

 local a=$[3+4]  #local仅在当前函数中生效

}

test

 

10#mktemp  FILE|DIR(创建临时文件或目录,脚本中防止创建的文件重名,可用X代替随机数的个数)

例如:#mktemp  /tmp/file.XXXXX为随机数的个数)

#mktemp -d  /tmp/dir.XXXXX-d创建目录)

#FILE=`mktemp  /tmp/file.XXXXXXX`

#eecho $FILE

 

11)信号:

#kill -lPrint a list of signal names

常用信号:

-SIGHUPhangup1

-SIGINTinterrupt2ctrl+c,中断前台正在运行的进程)

-SIGKILL9

-SIGTERMtermination15

-SIGCONTcontinue18#bg  %JOBID,将后台停止的作业让其继续运行)

-SIGSTOP19ctrl+z将前台作业放至后台运行)

脚本中可实现信号捕捉,但915信号无法捕捉。

#trap ‘command’  SIGNAL

例如:

#!/bin/bash

#

trap ‘echo “you go…”’  INT

while :;do

 date

 sleep 2

done

 

12)数组array(连续的内存空间,元素element(数据中每一个独立的变量),每一个元素用index标示)

#declare -a  AA(声明一个数组)

数组赋值方法一:

#declare -a  AA

#AA[0]=jerry

#AA[1]=tom

#AA[2]=wendy

#AA[6]=natasha

#AA[4]=”nikita black”(值中包含空格要用引号)

数组赋值方法二:

#declare -a  AA

#AA=(jerry tom  wendy)

#AA=([0]=jerry  [1]=tom [2]=wendy  [6]=natasha  [7]=”nikita black”)

 

#echo ${AA[0]}(查看数组中某元素的值)

#echo ${AA[2]}

#echo ${#AA[6]}(查看数组中某元素的值的字符个数)

#echo ${AA[*]}(查看数组中所有元素的值)

#echo ${#AA[*]}(查看数组中值不为空的元素的个数)

#echo ${#AA[@]}(查看数组中值不为空的元素的个数)

 

13)脚本中使用选项(getopts,获取bash 脚本的选项及选项后的参数,并在脚本中调用,格式如下)

#man getopts

#help getopts

getopts optstring  name  [arguments]

注:optstring表示可用的选项都有哪些,仅支持短选项,默认只获取一个选项

$OPTARG$OPTIND(这是getopts内置的两个变量,$OPTARG表示选项后参数的值;$OPTIND表示选项的索引index,永远指向下一个,如有一个选项时该值是2,有两个选项时该值是3

shift $[$OPTIND-1](表示踢走前面的选项)

getopts “b:d:”  OPTbd后的冒号表示选项后必须要跟参数,否则会报错)

getopts “:b:d:”  OPT(第一个冒号表示不输出错误信息,这个错误信息是getopts的错误信息而不是脚本)

使用方法:

while getopts  “:d:”  OPT;do

 case  $OPT  in

   d)

echo  “the option is d”

echo  $OPTARG

   ;;

   *)

echo  “Usage: ……

   ;;

 esac

done

具体用法见以下(举例2122

 

 

 

2)条件判断,控制结构:

单分支if语句:

if  判断条件;then

 statement1

 statement2

......

fi

双分支if语句:

if  判断条件;then

 statement1

 statement2

......

else

 statement3

 statement4

......

fi

多分支if语句:

if  判断条件1then

 statement1

......

elif 判断条件2then

 statement2

......

elif 判断条件3then

  statement3

......

else

 statement4

......

fi

case 变量  in

 value1)

  statement

  ;;

 value2)

  statement

  ;;

  *)

  statement

  ;;

esac

 

3)循环:进入条件,退出条件,for,while,until

for  变量  in  列表;do

  循环体

 done

生成列表的方式:{1..100}seq  [起始数 [步进数]  尾数;

整个语句将列表遍历完成之后退出;

 

for ((expr1;expr2;expr3));do

循环体

done

注:此种写法近似C语言风格,其中expr1表示初始值,expr2表示退出条件,expr3表示修正变量值)

 

while CONDITION;do(条件满足进入循环,条件不满足退出循环,适用于循环次数未知的场景,注意要有退出条件)

 statement

done

 

until CONDITON;do(条件不满足进入循环,条件满足退出循环)

 statement

done

 

break(提前退出循环,可用来控制死循环)

continue(提前结束本轮循环,而进入下一轮循环)

while特殊用法一(死循环,需break控制退出):

while :;do

statement

done

while特殊用法二:

while read  LINE;do

statement

done <  /PATH/TO/SOMEFILE

 

4)函数:

功能function,把执行的一段代码封装成一个独立的功能,并给之取个名字,需要时直接调用(调用时直接写函数名)

结构化编程的重要思想,主要目的实现代码重用,不能独立运行,需要调用时执行,可以被多次调用;库文件.so能被多个进程调用

定义一个函数,两种方式,函数名可以是字母数字下划线,不能数字开头:

function FUNCNAME{

 COMMAND

]

FUNCNAME() {

 COMMAND

}

自定义执行状态返回值:return  #(退出函数,0-255

exit #(退出脚本)

 

 

 

 

 

二、操作:

举例1

#!/bin/bash

#使用脚本添加或删除用户

if [  $#  -lt 1  ]; then

 echo  “Usage: adminusers ARG.”

 exit  7

fi

if [  $1  ==  ‘add’  ];then

 for  I  in {1..10};do

  if  id  user$I &> /dev/null;then

echo “user$Iexists.”

  else

useradd  user$I

echo  “user$I” | passwd  --stdin user$I  &> /dev/null

echo  “Add user$I finished.”

   fi

 done

elif  [ $1  ==  ‘del’ ];then

 for  I  in {1..10};do

  if  id  user$I &>  /dev/null;then

userdel  -r user$I

echo  “Delete user$I finished.”

  else

echo  “No user$I.”

   fi

 done

else

 echo  “Unknown  ARG.”

 exit  8

fi

-------------------------------------------------------------------------------------------------------------

举例2

#!/bin/bash

#打印1到100偶数和与奇数和

declare -i  EVENSUM=0

declare -i  ODDSUM=0

for I  in  {1..100};do

 if  [  $[$I%2] -eq  0  ];then

  let  EVENSUM+=$I

 else 

  ODDSUM+=$I

  fi

done

echo “Oddsum is $ODDSUM.”

echo “Evensum is $EVENSUM.”

-------------------------------------------------------------------------------------------------------------

举例3

#!/bin/bash

#打印1100的和

declare -i  SUM=0

for ((I=1;I<=100;I++));do

  let  SUM+=$I

done

echo “1+2+..100=$SUM.”

-------------------------------------------------------------------------------------------------------------

#!/bin/bash

#

declare -i  SUM=0

for I  in  {1..100};do

 let  SUM+=$I

done

echo “1+2+..100=$SUM.”

-------------------------------------------------------------------------------------------------------------

#/bin/bash

#

declare -i  SUM=0

for I  in  `seq 1  1  100`;do

 let  SUM+=$I

done

echo “1+2+...100=$SUM.”

-------------------------------------------------------------------------------------------------------------

#!/bin/bash

#

decalre -i  SUM=0

declare -i  I=0

while [  $I  -le 100  ];do

 let  SUM+=$I

 let  I++

done

echo “1+2+...100=$SUM.”

-------------------------------------------------------------------------------------------------------------

#!/bin/bash

#

declare -i  I=0

declare -i  SUM=0

until [  $I  -gt 100  ];do

 let  SUM+=$I

 let  I++

done

echo “1+2+...100=$SUM.”

-------------------------------------------------------------------------------------------------------------

举例4

#!/bin/bash

#检测用户hadoop是否在线,若在线则打印至屏幕并退出

until who  |  grep  “hadoop”  &> /dev/null;do(此句也可写为while  !  who | grep “hadoop”  &> /dev/null;do

 echo “hadoop is not come!”

 sleep  5

done 

 echo  “hadoop is logged in.”

-------------------------------------------------------------------------------------------------------------

举例5

#!/bin/bash

#随机生成10个数,比较最大数最小数

declare -i MAX=0

declare -i MIN=0

for I in {1..10};do

MYRANDOM=$RANDOM

[ $I -eq 1 ] && MIN=$MYRANDOM

if [ $I -le 9 ];then

  echo -n "$MYRANDOM,"

 else

  echo "$MYRANDOM"

  fi

 [$MYRANDOM -gt $MAX ] && MAX=$MYRANDOM

 [$MYRANDOM -lt $MIN ] && MIN=$MYRANDOM

done

  echo $MAX,$MIN


举例6

#!/bin/bash

#将用户输入的字符转为大写,当输入q时退出

read -p  “Input string:  “ STRING

while [  $STRING  !=  ‘q’  ];do

 echo  $STRING  | tr  ‘a-z’  ‘A-Z’

 read  -p  “Input string again:  “ STRING

done


举例7

#!/bin/bash

#按步骤生成yum仓库文件

REPOFILE=/etc/yum.repos.d/$1

if [ -e $REPOFILE ];then

   echo "$1 is exists."

   exit 3

fi

read -p "Repository ID: " REPOID

until [ $REPOID == 'quit' ];do

   echo "[$REPOID]" >> $REPOFILE

   read -p "Repository Name: " REPONAME

   echo "name=$REPONAME" >> $REPOFILE

   read -p "Repository baseurl: " REPOURL

   echo "baseurl=$REPOURL" >> $REPOFILE

   echo -e "enabled=1\ngpgcheck=0" >> $REPOFILE

   read -p "Repository ID: " REPOID

done

echo "Bye!"

 

举例8

#!/bin/bash

#理解break

declare -i SUM=0

for I in {1..200};do

   let SUM+=$I

   if [ $SUM -gt 5000 ];then

       break

   fi 

done

echo $I

echo $SUM

 

举例9

#!/bin/bash

#理解continue

let SUM=0

let I=0

while [ $I -lt 100 ];do

   let I++

   if [ $[$I%2] -eq 0 ];then

       continue

   fi 

   let SUM+=$I

done

echo $SUM

 

举例10

#!/bin/bash

#while特殊用法一

while :;do

   read -p "File path: " FILEPATH

    [$FILEPATH == 'quit' ] && break

   if [ -e $FILEPATH ];then

       echo "$FILEPATH exists."

   else

       echo "No $FILEPATH."

   fi 

done

 


#!/bin/bash

#while特殊用法二

useradd user1

useradd user2

useradd user3

useradd user4

useradd user5

let I=0

while read LINE;do

    [`echo $LINE | awk -F: '{print $3}'` -gt 503 ] && continue

    [`echo $LINE | awk -F: '{print $7}'` == '/bin/bash' ] && echo $LINE |awk -F: '{print $1}' && let I++

    [$I -eq 5 ] && break

done < /etc/passwd

 

举例11

#!/bin/bash

#检查一脚本是否有语法错误,若有错误按任意键(除qQ)编辑,若无错则直接退出

until bash -n $1 &> /dev/null;do

   read -p "Syntax error,[Q\q] to quit,other for editing: "CHOICE

   case $CHOICE in

   q|Q)

   echo "Something wrong,quiting."

   exit 5

   ;; 

   *) 

   vim + $1

   esac

done

 

举例12

#!/bin/bash

#理解函数

TWOSUM() {

   echo $[$1+$2]

}

for I in {1..10};do

   let J=$[$I+1]

   TWOSUM $J $I

done

echo "$J plus $I is `TWOSUM $J$I`"

 

举例13

#!/bin/bash

#函数应用:添加用户(存在显示failure,不存在则添加)

ADDUSER(){

    USERNAME=$1

    if ! id -u $USERNAME &>/dev/null;then

        useradd $USERNAME

        echo "$USERNAME" | passwd--stdin $USERNAME &> /dev/null

        return 0

    else

        return 1

    fi 

}

   for I in `seq 1 5`;do

    ADDUSER user$I

    if [ $? -eq 0 ];then

        echo "add user$I is success."

    else

        echo "add user$I failure."

fi 

   done

 

举例14

#!/bin/bash

#函数应用:查看指定网段是否畅通

PING() {

   if ping -c 1 -w 1 $1 &> /dev/null;then

       return 0

   else

       return 1

   fi 

}

for I in {150..160};do

   PING 192.168.1.$I

   if [ $? -eq 0 ];then

       echo "192.168.1.$I is up."

   else

       echo "192.168.1.$I is down."

   fi 

done

 

举例15

#!/bin/bash

#查看分区、内存、交换区使用情况。

cat << EOF

d)show disk usages.

m)show memory usages.

s)show swap usages.

q)quit.

EOF

read -p "Your choice: " CHOICE

until [ $CHOICE == 'q' ];do

   case $CHOICE in

   d) 

   echo "Disk Usages:"

   df -hP

   ;; 

   m) 

   echo "Memory Usages:"

   free -m | fgrep "Mem"

   ;; 

   s) 

   echo "Swap Usages:"

   free -m | fgrep "Swap"

   ;; 

   *) 

   echo "Unknow!."

   cat << EOF

   d)show disk usages.

   m)show memory usages.

   s)show swap usages.

   q)quit.

EOF

   esac

   read -p "Your choice again: " CHOICE

done

举例16

#!/bin/bash

#函数应用:查看磁盘、内存、交换分区使用情况。

SHOW() {

   cat << EOF

   d)show disk usage.

   m)show memory usage.

   s)show swap usage.

   q)show quit.

EOF

}

read -p "Your choice: " CHOICE

until [ $CHOICE == 'q' ];do

   case $CHOICE in

   d) 

   echo "Disk Usages:"

   df -hP

   ;; 

   m) 

   echo "Memory Usages:"

   free -m | fgrep "Mem"

   ;; 

   s) 

   echo "Swap Usages:"

   free -m | fgrep "Swap"

   ;; 

*) 

echo “Unknow!”

   SHOW

   ;; 

   esac

 read -p "Your choice again: " CHOICE

done

 

举例17

#!/bin/bash

#trap练习,信号捕捉及临时文件的创建删除

NET='192.168.101.'

FILE=`mktemp /tmp/file.XXXXX`

clearup() {

   echo 'quit.'

   rm -f $FILE

   exit 1

}

trap 'clearup' INT

for I in {200..210};do

   if ping -c 1 -W 1 $NET$I &> /dev/null;then

       echo "$NET$I is up."

   else

       echo "$NET$I is down."

   fi

done

 

举例18

#!/bin/bash

#数组练习,找出已知数组中的最大数

declare -a ARRAY=(1 2 3 44 5 6 7 8 9 10)

declare -i MAX=${ARRAY[0]}

INDEX=$[${#ARRAY[*]}-1]

 

for I in `seq 0 $INDEX`;do

   if[ $MAX -lt ${ARRAY[$I]} ];then

    MAX=${ARRAY[$I]}

   fi

done

echo $MAX

 

举例19

#!/bin/bash

#数组练习,随机生成数组中各元素的值,找出最大值

for J in {0..9};do

 ARRAY[$J]=$RANDOM

 sleep 1

 echo -n "${ARRAY[$J]} "

done

 echo

declare -i MAX=${ARRAY[0]}

INDEX=$[${#ARRAY[*]}-1]

 

for I in `seq 0 $INDEX`;do

  if[ $MAX -lt ${ARRAY[$I]} ];then

   MAX=${ARRAY[$I]}

  fi

done

echo $MAX

 

举例20

#!/bin/bash

#自动生成空白脚本文件的头部;检查已存在脚本文件的语法

if ! grep "[^[:space:]]" $1&> /dev/null;then

cat > $1 << EOF

#!/bin/bash

# name: `basename $1`

# description:

# version: 0.0.1

# author: jowin

# datetime: `date "+%F %T"`

# Usage: `basename $1`

 

EOF

chmod +x $1

vim + $1

fi

 

until bash -n $1 &> /dev/null;do

 read -p "syntax error:q|Q is quit,others is edit: " OPT

 case $OPT in

  q|Q)

   echo "quit."

   exit 4

   ;;

   *)

   vim + $1

   ;;

 esac

done

 

-------------------------------------------------------------------------------------------------------------

举例21:

#!/bin/bash

#在上例基础上,使用选项为脚本头部添加描述信息,用法为./mkscript –d “STRING” SCRIPT_FILE

while getopts ":d:" OPT;do

 case$OPT in

  d)

  DEC=$OPTARG

  ;;

  *)

  echo "Usage: mkscript [-d DESCRIPTION] FILE"

  ;;

 esac

done

shift $[$OPTIND-1]

 

if ! grep "[^[:space:]]" $1&> /dev/null;then

cat > $1 << EOF

#!/bin/bash

# name: `basename $1`

# description: $DEC

# version: 0.0.1

# author: jowin

# datetime: `date "+%F %T"`

# Usage: `basename $1`

 

EOF

chmod +x $1

vim + $1

fi

 

until bash -n $1 &> /dev/null;do

 read -p "syntax error:q|Q is quit,others is edit: " OPT

 case $OPT in

  q|Q)

echo"quit."

   exit 4

   ;;

   *)

   vim + $1

   ;;

 esac

done

  

-------------------------------------------------------------------------------------------------------------

举例22

#export PATH=$PATH:/root

#mkscript -d  “get  interface ip”  getinterface.sh(使用上例的脚本生成此脚本文件,编辑如下)

#!/bin/bash

# name: getinterface.sh

# description: get interface ip

# version: 0.0.1

# author: jowin

# datetime: 2015-10-27 19:23:13

# Usage: getinterface.sh

USAGE() {

echo "Usage: getinterface.sh [-i INTERFACE] [-I IP_ADDR]"

}

SHOWIP() {

 if !ifconfig | grep -o "^[^[:space:]]\{1,\}" | grep $1 &>/dev/null;then

 return 13;

 fi

 echo -n "${1}: "

 ifconfig $1 | grep -o "inetaddr:[0-9\.]\{1,\}" | cut -d: -f2

}

SHOWETHER() {

 if !ifconfig | grep -o "inet addr:[0-9\.]\{1,\}" | cut -d: -f2 | grep $1&> /dev/null;then

 return 14;

 fi

 echo-n "${1}: "

 ifconfig | grep -B 1 $1 | grep -o"^[^[:space:]]\{1,\}"

}

 

while getopts ":i:I:" OPT;do

 case$OPT in

  i)

  SHOWIP $OPTARG

   [$? -eq 13 ] && echo "wrong interface"

  ;;

  I)

 SHOWETHER $OPTARG

  [$? -eq 14 ] && echo "wrong ip"

  ;;

  *)

 USAGE

  ;;

 esac

done

 

 

-------------------------------------------------------------------------------------------------------------

 

 

-------------------------------------------------------------------------------------------------------------

 

 

 

 

 

以上是学习《马哥运维课程》做的笔记。

 

 

 

 

 







一、1、基础正则表达式:

         *         前一个字符匹配0次或任意多次

         .         匹配除了换行符外任意一个字符

         ^         匹配行首,例:^Hello,匹配以Hello开头的行

         $         匹配行尾,例:Hello$匹配以Hello结尾的行

         []        中括号中指定的一个字符,例:[0-9][a-z]

         [^]       匹配中括号字符以外的任意一个字符,例:[^0-9][^a-z]

         \         转义符,取消特殊符号的含义

         \{n\}     表示其前面的字符恰好出现n次,例:[0-9]\{4\}、手机号[1][3-8][0-9]\{9\}

         \{n,\}    表示其前面的字符出现不小于n次,例:[0-9]\{2,\}表示2位以上的数字

         \{n,m\}   表示其前面的字符至少出现n次,最多出现m次,例:[a-z]\{6,8\}表示68位小写字母

         2、扩展正则表达式:#grep–E  egrep

         +        前一个字符匹配1次或任意多次

                前一个字符出现0次或1次,例:colou?r匹配colourcolor

         |        匹配两个或多个分支选择,例:was|his,匹配包含was的行,也包含his的行

         ()       匹配其整体为一个字符,即模式单元,可理解为由多个单个字符组成的大字符,例:(dog)会出现dog,dogdog,dogdogdog等;hello(world|earth),匹配hello worldahello earth

注:grepawksed等命令支持正则表达式;lsfindcp支持shell通配符

         3#grep “a*”          t.txt          (匹配任何内容

         #grep“aa*” t.txt     (匹配至少包含一个a的行

         #grep“aaa*” t.txt    (匹配至少包含二个的行

         #grep“s..d” t.txt    (匹配sd之间一定有2个字符的单词

         #grep“s.*d” t.txt    (匹配sd之间有任意个字符

         #grep“^M” t.txt      (匹配以M开头的行

         #grep“N$” t.txt      (匹配以N结尾的行

         #grep“^$” t.txt      (匹配空白行

         #grep“^….$” t.txt   (匹配四个字符的行

         #grep“[0-9]” t.txt   (匹配含数字的行

         #grep“^[a-z]” t.txt  (字母开头的行

         #grep“[^A-Z]” t.txt  (非大写字母的行

         #grep“\.$” t.txt     (以点结尾的行

         #grep“a\{3\}” t.txt  (三个连续a的行

         #grep“[0-9]\{3,\} t.txt     (至少三个数字开头的行

         #grep“[su]a\{3,\}[iI] t.txt suiI之间至少有三个连续的a

         #grep“sa\{1,3\}i” t.txt    si之间最少有1a最多有3a

二、字符截取和替换命令

         1#cut 选项 文件名

         -f列号                fields提取第几列

         -d“分隔符”          delimiter指定分隔符

         -c字符范围            通过字符范围进行字段提取,行首为0;“n-”表示从第n个字符到行尾;“n-m”表示从第n个字符到第m个字符;“-m”表示从第1个字符到第m个字符

         例:#cut –f 2s.txt

         #cut–f 2,3 s.txt

         #cut–c 8- s.txt

         #cut–d “:” –f 1,3 s.txt

         2awk编程

         >#printf ’输出类型输出格式’  输出内容

         输出类型:

     %ns          输出字符串,n指代输出几个字符

         %ni         输出整数,n指代输出几个数字

         %m.nf       输出浮点数,m代表总数位,n是小数位。例:%8.2f表示6位整数,2位小数

         例:#printf ‘%s’$(cat s.txt)

         #printf‘%s\t%s\t%s\t%s\t \n’ $(cat s.txt)

         #printf‘%i\t%s\t%i\t%8.2f \n’ $(cat s.txt)  grep –v Name

  • awk ‘条件1{动作1} 条件2{动作2}……’ 文件名

动作:格式化输出,流程控制语句

         注:在awk编程中因命令语句长,输入格式时需注意:

         》多个条件{动作}可用空格分割也可用回车分割;

         》在一个动作中,如果需要执行多个命令,要用分号分割或用回车分割;

         》变量的赋值与调用都不用加$符号;

         》条件判断两个值是否相同使用==,不要和变量赋值混淆。

         例:#awk ‘{printf$2 “\t” $6 “\t” “\n” }’ s.txt    printf输出时在输出格式的最后要加“\n”,而print则不用。

         #df–h | awk ‘{print $2 “\t” $6}’ s.txt      

         #cats.txt | grep –v Name | awk ‘$6 >= 87 {print $2}’    (加入条件后,只有条件成立动作才执行

         #awk‘BEGIN {print “this is a transcript”}  {print $2 “\t” $6}’ s.txt       awk只要检测不到完整的‘’就不会执行,所以不用加换行符;BEGIN在读取数据前仅执行一次

         #awk‘END {print “The end!”} {print $2 “\t” $3}’ s.txt   

         #awk‘$2 ~ /sb/ {print $6}’ s.txt       (第二个字段包含有sb则打印第六字段

         #awk‘/sd/ {print}’ s.txt               (打印sd的成绩

         #df–h | awk ‘/sda[0-9]/ {print $1 “\t” $5}’

         #cat/etc/passwd | grep “/bin/bash” | awk ‘BEGIN{FS=”:”} {print $1 “\t” $3}’

         #cat/etc/passwd | grep “/bin/bash” | awk ‘BEGIN{FS=”:”} {print $1 “\t” $3 “\t 行号:”\

>NR “\t 字段数: “ NF}’        NR总数据的第几行,NF总字段数

         注:awk是列提取命令,但也要按行来读入,执行过程:

         》如有BEGIN,则先执行BEGIN定义的动作;

         》读入第一行,第一行的数据依次赋予$0,$1,$2等变量,$0代表此行的整体数据,$1代表第一个字段,$2代表第二个字段;

         》依据条件判断动作是否执行,符合执行,否则读入下一行数据,若没条件,则每行都执行动作

         》读入下一行数据,重复以下步骤。

         #awk‘NR==2 {php1=$3}

         NR==3{php2=$3}

         NR==4{PHP=$3;total=php1+php2+php3;print”total php is ” total}’ s.txt

 

         #awk‘NR>=2 {test=$4}

         test>90{print $2 “is a good man!”}’ s.txt

        

        

         function函数名 (参数列表){

         函数体

         }

      #awk ‘functiontest(a,b) {print a “\t” b}

         {test($2,$6)}’ s.txt

        

         #vipass.awk

         BEGIN‘{FS=”:”}

         {print$1 “\t” $3}

         #awk–f pass.awk /etc/passwd

        

         3sedstreameditor,对文本文件和标准输入进行编辑,键盘输入、文件重定向、字符串、变量、来自管道的文本

         #sed选项 ‘动作’文件名

         -n      有此项,输出时只会显示sed处理的行

         -e      对输入数据应用多条sed命令编辑

         -f脚本文件     #awk –f类似

         -r      支持正则表达式

         -I      直接修改源文件中数据,而不是由屏幕输出

         动作:

         a\     append追加,在当前行后添加一行或多行,每行末尾用\代表数据未完,最后一行不用

         c\     行替换,用c后面的字符串替换原数据行,多行时用\代表数据未完,最后一行除外

         i\     insert在当前行前插入一行或多行,多行时每行末尾用\代表数据未完,最后一行除外

         d      删除指定的行

         p      打印输出指定的行

         s      字符替换,格式:行范围s/旧字串/新字串/g

         行数据操作:例子:

         #sed–n ‘2p’ s.txt

         #sed‘2,4d’ s.txt

         #sed‘2a hello’ s.txt

         #sed‘2i hello \

         >world’s.txt    (行末用\代表数据未完,在第二行前插入两行数据

         #sed–n ‘2i’ hello \

         >world’s.txt    (仅显示处理的行

         #cats.txt |sed ‘2c No such person’ (将第二行替换

         #sed–i ‘2c No such a person’ s.txt(直接处理文件数据,-i谨慎使用

         字串替换:例子:

         #sed‘s///g’ s.txt

         #sed‘3s/74/99/g’ s.txt

         #sed‘4s/^/#/g’ s.txt

         #sed–e ‘s/sb//g ; s/sd//g’ s.txt

三、字符处理命令

         #sort 选项 文件名

         -f      忽略大小写ignore-case(foldlower case to upper case characters)

         -b      忽略每行前面的空白部分ignoreleading blanks

         -n      以数值排序numeric-sort

         -r      反射排序reverse

         -u      排除重复行,uniqu命令

         -t      指定分隔符,默认是制表符

         -kn[,m]    按指定的字串范围,从n字段开始,m字段结束(默认到行尾)

         例:#sort/etc/passwd

         #sort–r /etc/passwd

         #sort–t “:” –k 3,3 /etc/passwd       (只用第3字段排序

         #sort–n –t “:” –k 3,3 /etc/passwd

         #uniq 选项 文件名    (-i 忽略大小写

         #wc 选项 文件名      (-l,line;-w,word;-m字符数

四、条件判断

         1、文件类型判断:

         例:#[  -e /root/sh/  ]

         #echo$?

         #[ -d /root/sh  ] && echo “yes”|| echo “no”

         2、文件权限判断:

         #[  -w s.txt  ]&& echo “yes” ||echo “no”

         3、两个文件之间进行比较:

         #[ /root/s.txt -ef  /tmp/sut.txt ] && echo “yes”|| echo "no”                         (判断是否硬链接

         4、两个整数之间比较:

         #[  23  -ge  22  ]&& echo “yes” || echo “no”

         5、字符串的判断:

         #[  -z  “$name”  ] && echo “yes” || echo “no”

         6、多重条件判断:

         #[  -n  “$aa”  -a -n  “$aa”  -gt  23] && echo “yes” || echo “no”

五、流程控制:

         1if条件判断:

         》单分支:

         if[  条件判断式  ];then

             程序

         fi

         

         if[  条件判断式  ]

         then

             程序

         fi

         注:使用fi结尾,和一般语言使用大括号不同;条件判断式使用test命令判断,中括号和条件判断式之间必须有空格;then扣是符合条件之后执行的程序,then可放在[]之后用分号分隔,也可换行写入不写分号

         例:#vi  fi1.sh

         #!/bin/bash

         rate=$(df–h | grep “/dev/sda3” | awk ‘{print $5}’ | cut –d “%” –f 1)

         if[  “$rate”  -ge 80  ]

         then

             echo“Warning! /dev/sda3 is full!”

         fi

         》双分支

         if  [  条件判断式  ]

                then

                   条件成立时执行的程序

                else 

                   条件不成立时执行的程序

         fi

         例:#vi  backmysql.sh

         #!/bin/bash

         ntpdateasia.pool.ntp.org &>/dev/null

         date=$(date+%Y%m%d)

         size=$(du–sh /var/lib/mysql)

         if[  -d /tmp/dbbak  ]

                then

                  echo“Date: $date!” > /tmp/dbbak/dbinfo.txt

                  cd/tmp/dbbak

                  tar–zcf  mysql-lib-$date.tar.gz  /var/lib/mysql  dbinfo.txt &>/dev/null

                  rm–rf  /tmp/dbbak/dbinfo.txt

                else

                   mkdir/tmp/dbbak

                   echo“Date: $date!” > /tmp/dbbak/dbinfo.txt

                   echo“Date size: $size” >> /tmp/dbbak/dbinfo.txt

                   cd  /tmp/dbbak

                   tar–zcf  mysql-lib-$date.tar/gz  /var/lib/mysql  &>/dev/null

                   rm–rf /tmp/dbbak/dbinfo.txt

         fi

         例:vi  autostart.sh

         #!/bin/bash

         port=$(nmap–sT 192.168.4.210 | grep tcp | grep http| awk ‘{print $2}’)

         if  [  “$port”  ==  “open”  ]

                   then

                       echo“$(date) httpd is OK!” >> /tmp/autostart-acc.log

                   else

                       /etc/rc.d/init.d/httpdstop       &>/dev/null

                       /etc/rc.d/init.d/httpdstart    &>/dev/null

                       echo“$(date) restart httpd!” >> /tmp/autostart-err.log

         fi

         》多分支

         if  [  条件判断式  ]

                   then

                      当条件判断式1成立时,执行程序1

         elif  [  条件判断式  ]

                   then

                      当条件判断式2成立时,执行程序2

         ……

         else

                     当所有条件都不成立时,执行此程序

         fi

         例:#vi  if-elif.sh

         #!/bin/bash

         read–p “please input a filename:  “ file

         if  [ -z  “$file”  ]

                   then

                            echo“Error,please input a filename.”

         elif  [  ! –e “$file” ]

                   then

                            echo“Your input is not a file”

         elif  [ -f  “$file”  ]

                   then

                            echo“$file is a regulaar file.”

         elif  [ -d  “$file”  ]

                   then

                            echo“$file is a directory!”

         else

                            echo“$file is an other file!”

         fi

         2、多分去case条件语句:case只判断一种条件关系,而if可判断多种条件关系。

         case$变量名 in

                   “1”)

                   如果变量的值等于值1,则执行程序1

                   ;;

                   “2”)

                   如果变量的值等于值2,则执行程序2

                   ;;

         ……

                   *

                   如果变量的值都不是以上的值,执行此程序

                   ;;

         esac

         注:case语句会取出变量中的值,与语句体中的值逐一比较,符合则执行相应程序,不符依次比较下一个值。若所有值都不符合,则执行*)后的程序,*代表所有其它值;以case开头,esac结尾;每个分支之后要用;;结尾,代表该程序段结束。

         例:#vi case.sh

         #!/bin/bash

         read–p  “please chose yes/no: “ cho

         case$cho in

                   “yes”)

                   echo“Your choose is yes!”

                   ;;

                   “no”)

                   echo“Your choose is no”

                   ;;

                   *)

                   echo“Your choose is error!”

                   ;;

         esac

         3for循环是固定循环,在循环时已知道要循环几次,也称计数循环

         for  变量  in  1  2  3

                   do

                            程序

                   done

         注:in后有几个值就循环几次,每次循环都把值赋予变量

         for  ((初始值;循环控制条件;变量变化))

                  do

                            程序

                   done

         注:初始值,在循环开始时需要给变量赋予初始值,如i=1;循环控制条件,用于指定循环的次数,如i<=100;每次循环之后,变量该如何变化,如i=i+1,每次循环之后变量都加1.

         例:vi  auto-tar.sh

         #!/bin/bash

         cd  /bin/bash

         cd  /lamp

         ls  *.tar.gz > ls.log

         for  i  in $(cat ls.log)

                  do

                     tar  -zxf $i  &>/dev/null

                   done

         rm–rf /lamp/ls.log

         例:#vi  useradd.sh

         #!/bin/bash

         read  -t 30 -p “Please input username: “ name

         read  -t 30 -p “please input the number of users: “ num

         read  -t 30 -p “please input the password: “ pass

         if  [ -n  “$name” –a  -n  “$num”  -a -n  “$pass”  ]

              then

                 y=$(echo  $num | sed ‘s/[0-9]//g’)

                   if  [  -z  “$y”  ]

                      then

                         for  ((i=1;i<=$num;i=i+1))

                             do

                              /usr/sbin/useradd  $name$i &>/dev/null

                              echo  $pass | /usr/bin/passwd --stdin $name$i  &>/dev/null

                             done

                   fi

         fi

         4while循环:只要条件判断式成立,循环就一直继续,直到条件不成立才停止。

         while[  条件判断式 ]

                   do

                       程序

                   done

         5until循环:条件判断式不成立则进行循环,条件成立,则中止循环。

         until[  条件判断式  ]

                   do

                       程序

                   done

         6、函数:

         function  函数名 () {

                   程序

         }

         7、特殊流程控制语句:

         exit语句:在脚本中是退出当前脚本,#exit 返回值,返回值可自己定义,用$?查询,若没定义返回值,则是执行exit语句之前最后执行的命令的返回值。        

         break语句会结束整个当前循环,而continue语句结束单次当前循环,下次循环会继续

         for  ((条件判断语句))

                   do

                       程序语句

                       break(continue)

                       程序语句

                   done

         例:#vi  ping.sh

         #/bin/bash

        

         echo “这个脚本是统计/root/ip.txt所有ip地址的丢包率

         for  i $(cat  /root/ip.txt)

                   do

                            aa=$(ping  -c 3 $i | grep ttl | wc  -l)

                            bb=$((  3 - $aa ))

                            cc=$(echo  “$bb 3” | awk ‘{ print “%5.2f% \n”,$1/$2*100}’)

                            echo “$i的丢包率是:$cc”

                   done



本文转自 chaijowin 51CTO博客,原文链接:http://blog.51cto.com/jowin/1651732,如需转载请自行联系原作者

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
运维 监控 网络协议
|
21天前
|
缓存 运维 监控
【运维必备知识】Linux系统平均负载与top、uptime命令详解
系统平均负载是衡量Linux服务器性能的关键指标之一。通过使用 `top`和 `uptime`命令,可以实时监控系统的负载情况,帮助运维人员及时发现并解决潜在问题。理解这些工具的输出和意义是确保系统稳定运行的基础。希望本文对Linux系统平均负载及相关命令的详细解析能帮助您更好地进行系统运维和性能优化。
45 3
|
2月前
|
Web App开发 网络协议 Linux
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
这篇文章是关于Linux命令的总结,涵盖了从基础操作到网络配置等多个方面的命令及其使用方法。
70 1
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
|
1月前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
2月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
48 1
|
2月前
|
Shell
Shell编程(下)
Shell编程(下)
99 1
|
2月前
|
Shell Linux Windows
Shell编程(上)
Shell编程(上)
42 1
|
2月前
|
Shell Linux 开发工具
|
2月前
|
监控 Unix Shell
shell脚本编程学习
【10月更文挑战第1天】shell脚本编程
74 12
|
2月前
|
存储 运维 监控
自动化运维:使用Shell脚本简化日常任务
【9月更文挑战第35天】在IT运维的日常工作中,重复性的任务往往消耗大量的时间。本文将介绍如何通过编写简单的Shell脚本来自动化这些日常任务,从而提升效率。我们将一起探索Shell脚本的基础语法,并通过实际案例展示如何应用这些知识来创建有用的自动化工具。无论你是新手还是有一定经验的运维人员,这篇文章都会为你提供新的视角和技巧,让你的工作更加轻松。
67 2