命令记不住

登陆

Shell 脚本总结

Shell脚本总结

1.Shell变量核心基础知识

  1. 什么是变量
  2. 自定义环境变量
  3. 三种变量的定义方式
  4. Shell特殊位置重要变量
    案例:
[[email protected] ~]$ set -- "I am" x86cloud.com.cn teacher
[[email protected] ~]$ for i in "$@";do echo $i;done 
I am
x86cloud.com.cn
teacher
[[email protected] ~]$ for i in "$*";do echo $i;done 
I am x86cloud.com.cn teacher
	read从键盘读入变量值
	read 变量名 
	read -p "提示信息: " 变量名 
	read -t 5 -p "提示信息: " 变量名
	//示例
	# vim first.sh 
	back_dir1=/var/backup 
	read -p "请输入你的备份目录: " back_dir2 
	echo $back_dir1 
	echo $back_dir2 

	# vim ping2.sh
	#!/bin/bash
	read -p "Input IP: " ip
	ping -c2 $ip &>/dev/null
	if [ $? -eq 0 ];then
	    echo "host $ip is ok"
	else
	    echo "host $ip is fail"
	fi
//注意事项: 定义或引用变量时注意事项: " "弱引用 ' '强引用
[[email protected] ~]# x86cloud.com.cn=test 
[[email protected] ~]# echo "${x86cloud.com.cn} is good" 
test is good 
[[email protected] ~]# echo '${school} is good' 
${x86cloud.com.cn} is good

变量子串和删除替换

   	[[email protected] ~]# x86cloud="I am x86cloud"
	[[email protected] ~]# echo ${x86cloud}    
	I am x86cloud
	[[email protected] ~]# echo ${#x86cloud}
	11
	[[email protected] ~]# echo ${x86cloud:2}
	am x86cloud
	[[email protected] ~]# echo ${x86cloud:2:2}
	am
	[[email protected] ~]# echo ${x86cloud:2:4}
	am o

扩展:取字符串长度的方法

	[[email protected] ~]# echo ${#x86cloud}
	11
	[[email protected] ~]# echo ${x86cloud}|wc -L
	11
	[[email protected] ~]# expr length "$x86cloud"
	11
	[[email protected] ~]# echo ${x86cloud}|awk '{print length}'
	11
	[[email protected] ~]# echo ${x86cloud}|awk '{print length($0)}'
	11

面试题: 取出长度小于3的字符串

	 echo "I am x86cloud teacher I am 35"|xargs -n1|awk '{if (length <3)print}'
	for n in I am x86cloud teacher I am 30
	do
	         if [ ${#n} -lt 3 ]
	        then
	                echo $n
	        fi
	done
	 echo "I am x86cloud.com.cn teacher I am 30"|awk '{for(i=1;i<NF;i++)if(length($i)<3)print $i}'

1.从前面往后删除变量内容

[[email protected] ~]# url=www.sina.com.cn
//从前往后,最短匹配
[[email protected] ~]# echo ${url#*.}
//从前往后,最长匹配(贪婪匹配)
[[email protected] ~]# echo ${url##*.}

2.从后往前删除环境变量

[[email protected] ~]# url=www.sina.com.cn
[[email protected] ~]# echo ${url}
//从后往前,最短匹配
[[email protected] ~]# echo ${url%.*}
//从后往前,最长匹配 贪婪匹配
[[email protected] ~]# echo ${url%%.*}
[[email protected] ~]# url=www.sina.com.cn
[[email protected] ~]# echo ${url#a.}
[[email protected] ~]# echo ${url#*sina.}

3.内容变量替换

[[email protected] ~]# url=www.sina.com.cn 
[[email protected] ~]# echo ${url/sina/baidu}
[[email protected] ~]# url=www.sina.com.cn 
[[email protected] ~]# echo ${url/n/N}
//贪婪匹配
[[email protected] ~]# echo ${url//n/N}

4.变量自增

[[email protected] ~]# a=1
[[email protected] ~]# b=1
[[email protected] ~]# let x=a++	先赋值在运算
[[email protected] ~]# let y=++b	先运算在赋值
[[email protected] ~]# echo $a
2
[[email protected] ~]# echo $b
2
[[email protected] ~]# echo $x
1
[[email protected] ~]# echo $y
2

实际案例

[[email protected] scripts]# cat i++.sh 
#!/bin/sh
IP=8.8.8.8
i=1
while [ $i -le 3 ]
do
        ping -c 1 $IP &>/dev/null
        if [ $? -eq 0 ];then
                echo "$IP is up..."
        fi
        let i++
done

2.变量数值运算

1.整数运算expr + - * / %

expr 1 + 2 
expr $num1 + $num2

2.整数运算 $(()) + - * / %

echo $(($num1+$num2)) 
echo $((num1+num2)) 
echo $((5-3*2)) 
echo $(((5-3)*2)) 
echo $((2**3)) 
sum=$((1+2)); echo $sum
  1. 整数运算 $[] + - * / %
echo $[5+2]
echo $[5**2]
  1. 整数运算 let + - * / %
let sum=2+3; 
echo $sum 
i=1
let i++
echo $i
  1. 小数运算 bc + - * / %
echo "2*4" |bc 
echo "2^4" |bc 
echo "scale=2;6/4" |bc 
awk 'BEGIN{print 1/2}' 
echo "print 5.0/2" |python

3.Shell条件测试

1.文件测试

[ -e dir|file ] 存在则为真
[ -d dir ] 目录是否存在
[ -f file ] 文件是否存在 
[ -r file ] 文件是否有读权限
[ -x file ] 文件是否有执行权限
[ -w file ] 文件是否有写权限

常用测试

[[email protected] ~]# test -d /opt/test
[[email protected] ~]# echo $?
1
[[email protected] ~]# [ ! -d /opt/test ] && mkdir /opt/test
[[email protected] ~]# [ -d /opt/x86cloud.com.cn ] || mkdir /opt/x86cloud.com.cn

2.数值比较
数值比较 [ 整数 1 操作符 整数 2 ] 

[ 1 -gt 10 ] 大于 
[ 1 -lt 10 ] 小于 
[ 1 -eq 10 ] 等于 
[ 1 -ne 10 ] 不等于 
[ 1 -ge 10 ] 大于等于 
[ 1 -le 10 ] 小于等于

案例:
查看磁盘/当前使用状态,如果使用率超过80%则报警发邮件

//怎么看磁盘使用率,怎么获取对应的值
[[email protected] scripts]# cat disk_use.sh 
#!/bin/sh
DATE=$(date +%F)
Disk_Use=$(df -h|grep '/$'|awk '{print $5}'|awk -F% '{print $1}')
if [ $Disk_Use -ge 10 ]
then
    echo "Disk Is use ${Disk_Use}%" >/tmp/${DATE}-diskuse.txt
fi

案例2 内存超过百分80报警输出

[[email protected] scripts]# cat memory_use.sh 
#!/bin/sh
Mem_Use=$(free -m|grep ^M|awk '{print $3/$2*100}')
if [ ${Mem_Use%.*} -ge 30 ]
then
    echo "Memory IS ERROR ${Mem_Use%.*}%"
else
    echo "Memory IS OK ${Mem_Use%.*}%"
fi

案例3 自己写一个监控负载状态的脚本

ab -n 200000 -c 2000 http://127.0.0.1/index.html

案例4 自己用脚本打印出 系统版本 内核版本平台 虚拟平台 静态主机名 eth0网卡IP地址 lo网卡IP地址 当前外网IP地址

curl icanhazip.com

3.字符串比较

  1. 字符串比对、必须加双引号
[[email protected] ~]# [ "$USER" = "root" ];echo $?
0
[[email protected] ~]# AAA=""
[[email protected] ~]# echo ${#AAA}
0
#字符长度为 0
[[email protected] ~]# [ -z "$AAA" ]
[[email protected] ~]# echo $?
0
#字符长度不为 0
[[email protected] ~]# [ -n "$AAA" ]
[[email protected] ~]# echo $?
1
[[email protected] ~]# [ "$USER" = "root" ];echo $?
0
[[email protected] ~]# [ "$USER" = "x86cloud.com.cn" ];echo $?  
1
[[email protected] ~]# [ "$USER" != "x86cloud.com.cn" ];echo $?
0
  1. 多整数比较
[[email protected] ~]# [ 1 -lt 2 -a 5 -gt 10 ];echo $?
1
[[email protected] ~]# [ 1 -lt 2 -o 5 -gt 10 ];echo $?
0

正则会用到[[]]

[[email protected] ~]# [[ 1 -lt 2 && 5 -gt 10 ]];echo $?
1
[[email protected] ~]# [[ 1 -lt 2 || 5 -gt 10 ]];echo $?
0

5.正则比对

[[email protected] ~]# [ "$USER" =~ ^r ];echo $?
-bash: [: =~: binary operator expected
2
[[email protected] ~]# [[ "$USER" =~ ^r ]];echo $?
0
[[email protected] ~]# num=123
[[email protected] ~]# [[ "$num" =~ ^[0-9]+$ ]];echo $?
0
[[email protected] ~]# num=123a
[[email protected] ~]# [[ "$num" =~ ^[0-9]+$ ]];echo $?
1

案例:

[[email protected] scripts]# cat test01.sh 
#!/bin/sh

read -p "please input number " num
if [[ ! "$num" =~ ^[0-9]+$ ]]
then
    echo "please input 数字"
    exit 1
fi
echo "Number Is $num"

案例2:
批量创建添加用户脚本

[[email protected] scripts]# cat test02.sh 
#!/bin/sh
read -p "Please Input number " num
if [[ ! $num =~ ^[0-9]+$ ]]
then
    echo "Please Input 数字"
    exit 1
fi
read -p "Please Input prefix " prefix
if [ -z "$#prefix" ]
then
    echo "Please Input 前缀"
    exit 2
fi

for i in `seq "$num"`
do
        USER=$prefix$i
        useradd $USER
        echo "123"|passwd --stdin $USER &>/dev/null
        if [ $? -eq 0 ];then
                echo "$USER Is create ok"
        fi
done

1.自己用脚本打印出 系统版本 内核版本平台 虚拟平台 静态主机名 eth0网卡IP地址 lo网卡IP地址 当前外网IP地址

#!/bin/sh
System=$(hostnamectl |grep System|awk '{print $3,$4,$5}')
Kernel=$(hostnamectl|grep Kernel|awk -F: '{print $2}')
Vt=$(hostnamectl|grep Virtualization|awk '{print $2}')
Statichostname=$(hostnamectl|grep "Static hostname"|awk '{print $3}')
Eth0=$(ifconfig eth0|awk 'NR==2{print $2}')
Lo=$(ifconfig lo|awk 'NR==2{print $2}')
Network_T=$(curl -s icanhazip.com)

echo "当前系统版本是: $System"
echo "当前系统内核是: $Kernel"
echo "当前虚拟平台是: $Vt"
echo "当前静态主机名是: $Statichostname"
echo "当前Eth0IP地址是: $Eth0"
echo "当前lo地址是: $Lo"
echo "当前外网地址是: $Network_T"

2.批量创建添加用户脚本

[[email protected] scripts]# cat test02.sh 
#!/bin/sh
read -p "Please Input number " num
if [[ ! $num =~ ^[0-9]+$ ]]
then
    echo "Please Input 数字"
    exit 1
fi
read -p "Please Input prefix " prefix
if [ -z "$#prefix" ]
then
    echo "Please Input 前缀"
    exit 2
fi

for i in `seq "$num"`
do
        USER=$prefix$i
        useradd $USER
        echo "123"|passwd --stdin $USER &>/dev/null
        if [ $? -eq 0 ];then
                echo "$USER Is create ok"
        fi
done

3.猜数字游戏
随机输出一个1-100的数字
要求用户输入数字(数字处加判断)
如果比随机数小则提示比随机数小了 大则提示比随机数大了
正确则退出 错误则继续死循环
最后统计猜了多少次(猜对的情况

[[email protected] ~]# cat ping.sh 
#!/bin/sh
num=$(echo $((RANDOM%100+1)))
echo $num

i=1
while true
do
read -p "Please Input number: 1-100: " num1
if [[ ! $num1 =~ ^[0-9]+$ ]];
then
    echo "Please Input number: 1-100"
    continue
fi
if [ $num1 -lt $num ];then
        echo "你输入的数字小了"
elif [ $num1 -gt $num ];then
        echo "你输入的数字大了"
elif [ $num1 -eq $num ];then
        echo "猜中了"
        break
fi
let i++
done
        echo "一共猜了 $i 次"

4.流程控制语句

1.单分支结构

if [ 如果你有房 ];then 
    我就嫁给你
fi

双分支结构

if [ 如果你有房 ];then 
        我就嫁给你
    else
        再见
fi

多分支结构

if [ 如果你有房 ];then 
        我就嫁给你
elif [ 你有车 ];then
        我就嫁给你
elif [ 你有钱 ];then
        我就嫁给你
    else
        再见
fi

案例:根据不同的操作系统安装不同的源

#!/bin/sh
#Version v1.0
#Author lzy

os_version=$(cat /etc/redhat-release|awk '{print $4}')

if [ "$os_version" = "(Final)" ]
        then
        os_version=$(cat /etc/redhat-release|awk '{print $3}')
fi
if [ ${os_version%%.*} -eq 7 ]
        then
        mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
        wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
        yum makecache
elif [ ${os_version%%.*} -eq 6 ]
        then
        mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
        wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
        yum makecache
elif [ ${os_version%%.*} -eq 5 ]
        then
        mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
        curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-5.repo
else
        echo "Please check version"
fi

案例:安装不同的PHP版本

[[email protected] ~]# cat php.sh
#!/usr/bin/bash
#install php
install_php56() {
        yum install epel-release
        rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
        yum install --enablerepo=remi --enablerepo=remi-php56 php php-opcache php-devel php-mbstring php-mcrypt php-mysqlnd php-phpunit-PHPUnit php-pecl-xdebug php-pecl-xhprof
}
install_php70() {
    echo "install php7.0......"
}
install_php71() {
    echo "install php7.1......"
}
while :
do
    echo "################################"
    echo -e "\t1 php-5.6"
    echo -e "\t2 php-7.0"
    echo -e "\t3 php-7.1"
    echo -e "\tq exit"
    echo "################################"

    read -p "version[1-3]: " version
    if [ "$version" = "1" ];then
        install_php56   
    elif [ "$version" = "2" ];then
        install_php70
    elif [ "$version" = "3" ];then
        install_php71
    elif [ "$version" = "q" ];then
        exit
    else
        echo "error"  
    fi
done

2.流程控制语句case
case语句

case 变量 in 
模式 1) 
    命令序列 1;; 
模式 2) 
    命令序列 2;; 
模式 3) 
    命令序列 3 ;; 
*) 
    无匹配后命令序列 
esac

案例:

[[email protected] ~]# cat del.sh
#!/usr/bin/bash
read -p "请输入需要删除的用户前缀,以及用户的位数: " delname delnum

echo "你将要删除如下账户
        用户前缀是: $delname
        用户的个数: $delnum
"
read -p "你确定要删除吗[y|Y|Yes|n|N|NO]?" reday

for i in $(seq $delnum);do
userfull=$delname$i
        case $reday in
                y|Y|YES)
                        id $userfull &>/dev/null
                        if [ $? -eq 0 ];then
                                userdel $userfull &>/dev/null
                                echo "userdel is ok $userfull...."
                        else
                                echo "$userfull" no such user
                        fi
                        ;;
                n|N|no|NO|No)
                        exit 1
                        ;;
                *)
                read -p "你确定要删除吗[y|Y|Yes|n|N|NO]?" reday

        esac
done

案例:

[[email protected] ~]# cat caidan.sh 
#!/usr/bin/bash
caidan(){
cat <<EOF
===================
h 显示命令帮助  
f 显示登陆信息 
d 显示磁盘挂载 
m 查看内存使用 
u 查看系统负载 
q 退出程序
=====================
EOF
}
caidan
while true
do
        read -p "请输入你想查看系统状态对应码[d/m/u/q]: " sys
        case "$sys" in 
                h)
                        clear
                        caidan
                        ;;
                f)
                        clear
                        w
                        ;;
                d)
                        clear
                        df -h
                        ;;
                m)
                        clear
                        free -m
                        ;;
                u)
                        clear
                        uptime
                        ;;
                q)
                        break
                        ;;
                *)
                        echo "error"
                        exit 1;
        esac
done

案例 jumpserver简单实现

trap
信号说明

HUP(1)    挂起,通常因终端掉线或用户退出而引发
INT(2)    中断,通常因按下Ctrl+C组合键而引发
QUIT(3)  退出,通常因按下Ctrl+组合键而引发
ABRT(6)  中止,通常因某些严重的执行错误而引发
ALRM(14)  报警,通常用来处理超时
TERM(15)  终止,通常在系统关机时发送
SIGTSTP   停止进程     终端来的停止信号
[root@web02 ~]# cat /home/x86cloud.com.cn/jumpserver.sh 
#!/usr/bin/bash

#jumpServer 

Mysql_master=10.0.0.10
Mysql_slave1=10.0.0.11
Mysql_slave2=10.0.0.12
Nginx_Up=10.0.0.6
Nginx_WEB1=10.0.0.7
Nginx_WEB2=10.0.0.8

meminfo(){
cat <<-EOF
-------------------------------
|       1) mysql-master         |
|       2) mysql-slave1         |
|       3) mysql-slave2         |
|       4) Nginx-Upstream       |
|       5) Nginx-WebNode1       |
|       6) Nginx-WebNode2       |
|       h) help                 |
---------------------------------
EOF
}
        #调用函数打印菜单
        meminfo
        #控制不让输入ctrl+c,z
        trap "" HUP INT TSTP
while true
do
        read -p "请输入要连接的主机编号: " num
        case $num in 
                1|mysql-master)
                        ssh root@$Mysql_master
                        ;;
                2|Mysql_slave1)
                         ssh root@$Mysql_slave1
                        ;;
                3|Mysql_slave2)
                        ssh root@$Mysql_slave2
                        ;;
                h|help)
                        clear
                        meminfo
                        ;;
                #退出脚本后门, 不要让其他人知道
                exec)
                        break
                        ;;
        esac
done

案例:

[[email protected] ~]# cat start_nginx.sh
#!/usr/bin/bash
# manager Nginx start stop restart reload
source  /etc/init.d/functions

act=$1
te(){
if [ $? -eq 0 ];then
                action "Nginx Is $act" /bin/true
        else
                action "Nginx Is $act" /bin/false
fi
}

start(){
        /usr/sbin/nginx &>/dev/null
        te

}
stop(){
        /usr/sbin/nginx -s stop &>/dev/null
        te
}

reload(){
        /usr/sbin/nginx -s reload
        te
}

status(){
        Ngx_status=$(ps aux|grep "[n]ginx"|grep master|awk '{print $2}')
        Nginx_Status_Port=$(netstat -lntp|grep nginx|awk '{print $4}')
        echo "Nginx_status_Pid: $Ngx_status"
        echo "Nginx_status_Port: $Nginx_Status_Port"
}

case $1 in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                sleep 1
                start
                ;;
        reload)
                reload
                ;;
        status)
                status
                ;;
        *)
                echo "Usage: $0 {start|stop|status|restart|reload|}"
esac

3.交互脚本expect
1.简单实现面交互登陆

#!/usr/bin/expect
spawn ssh [email protected]

expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "centos\r" };
} 
interact

2.expect定义变量实现交互方式

#!/usr/bin/expect
set ip 10.0.0.5
set user root
set password centos
set timeout 5

spawn ssh $user@$ip

expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "$password\r" };
} 

交互方式
interact

5.For循环

1.for循环语法

for 变量名  in [ 取值列表 ] 
do 
    循环体
done

案例1:

[[email protected] ~]# cat ping.sh 
#!/bin/
#循环主机
for i in {1..254}
do       #并发执行
        {   
        IP=39.107.76.$i
        ping -c1 $IP &>/dev/null
        if [ $? -eq 0 ];then
        echo "$IP" >>ip.txt
        fi
        }&
done
   wait
   echo "获取在线IP完成"

案例2

#!/bin/sh
for i in `cat user.txt`
do
        id $i &>/dev/null
        if [ $? -ne 0 ];then
           useradd $i
           echo "123"|passwd --stdin $i &>/dev/null
           echo "Create $i OK"
        else
           echo "useradd: $i already exists"
        fi
done

2.while循环
while循环基础语法

//当条件测试成立(条件测试为真),执行循环体
while 条件测试 
do 
    循环体 
done

案例1:用while创建用户

[[email protected] ~]# cat scripts/while.sh 
#!/bin/sh
while read line
do
        id $line &>/dev/null
        if [ $? -eq 0 ];then
           echo "useradd: user $line already exists"
        else
           useradd $line
           if [ $? -eq 0 ];then
                echo "create $line success"
           fi
        fi
done<ip.txt

#文件中存在用户和密码
[[email protected] ~]# cat while1.sh 
#!/bin/sh
while read user
do
        u=$(echo $user|awk '{print $1}')
        p=$(echo $user|awk '{print $2}')
        id $u &>/dev/null
        if [ $? -ne 0 ];then
             useradd $u
             echo $p|passwd --stdin $u &>/dev/null
             echo "Create $u is ok"
        else
             echo "useradd: $u already exists"
        fi
done<user.txt

6.Shell内置命令


命令 含义
exit 退出整个程序
break 结束当前循环,或跳出本层循环
continue 忽略本次循环剩余的代码,直接进行下一次循环

exit示例

[[email protected] ~]# cat exit.sh 
while true
do
  echo "123"
  exit
  echo "456"
done
echo "done..."

执行后的结果

[[email protected] ~]# sh exit.sh 
123

break示例

[[email protected] ~]# cat break.sh 
while true
do
  echo "123"
  break
  echo "456"
done
echo "done..."

执行后的结果

[[email protected] ~]# sh break.sh 
123
done...

continue 示例
假如创建前创建一个test1 break会直接跳出循环、continue会跳出继续循环

[[email protected] ~]# cat continue.sh 
#!/bin/sh
for i in `seq 10`
do
        useradd test$i
        if [ $? -eq 0 ];then
        echo "Create $i Success"
        else
             continue
        fi
done

7.函数

1.Shell中函数的作用

1.命令合集,完成特定功能的代码块
2.在shell中定义函数可以使用代码模块化, 便于复用代码,加强可读性
3.函数和变量类似, 先定义才可调用,如果定义不调用则不会被执行

传参 $1,$2
变量 local
返回值 return $?
  1. 如何定义和调用函数
# 方式一
函数名() {
    command
}
# 方式二
function 函数名 { 
    command
}
调用函数非常简单, 只需要在脚本中写入函数的名称即可
// 在脚本中直接写入函数名即可完成函数调用
function_name

3.函数传参

fun $1  传入脚本后第一个参数
fun $*  接收所有参数的传递

案例:

[[email protected] ~]# cat fun3.sh 
t_file(){                   # 函数判断
    if [ -f $1 ];then
        echo "$1 exists"
    else
        return 1
    fi
}
# 调用函数
t_file  $1
1.
[[email protected] ~]# cat fun.sh 
#!/bin/sh
# 定义一个函数
count01(){
num=10
for i in `seq 10`
do
        total=$[$i + $num]

done
        echo "计算结果是: $total"
}
count01    #  调用函数
[[email protected] ~]# sh fun.sh 
计算结果是: 20
[[email protected] ~]# cat fun.sh 
#!/bin/sh
count01(){
for i in `seq 10`
do
        total=$[$i + $num]

done
        echo "计算结果是: $total"
}
num=10
count01
[[email protected] ~]# sh fun.sh 
计算结果是: 20
3.
[[email protected] ~]# cat fun.sh 
#!/bin/sh
count01(){
num=$1
for i in `seq $num`
do
        total=$[$i + $num]

done
        echo "计算结果是: $total"
}
count01 $1
count01 $2
count01 $3
[[email protected] ~]# sh fun.sh 10 20 30
计算结果是: 20
计算结果是: 40
计算结果是: 60

传参使用场景:

[[email protected] ~]# cat nginx.sh 
source /etc/init.d/functions
Test() {
    if [ $? -eq 0 ];then
        action "Nginx $1 is ok" /bin/true
    else
        action "Nginx $1 is error" /bin/false
    fi
}
case $1 in
    start)
        nginx
        Test $1
        ;;
    stop)
        nginx -s stop
        Test $1
        ;;
    reload)
        nginx -s reload
        Test $1
        ;;
    *)
        echo "USAGE: $0 { start|stop|reload }"
esac

函数的返回值
echo 返回函数返回值
return 返回指定函数退出状态码
1.

[[email protected] ~]# cat fun2.sh 
fun2() {
echo 100
return 1
}
result=`fun2`
echo "函数的状态码是: $?"
echo "函数的返回值是: $result"
[[email protected] ~]# sh fun2.sh 
函数的状态码是: 1
函数的返回值是: 100
[[email protected] ~]# cat fun3.sh 
file=/etc/ttt               # 定义文件
t_file(){                   # 函数判断
    if [ -f $file ];then
        return 0
    else
        return 1
    fi
}
# 调用函数
t_file

#根据函数返回状态码进行输出
if [ $? -eq 0 ];then
    echo "该文件存在 $file"
else
    echo "该文件不存在 $file"
fi
  1. 统计文件行
[[email protected] ~]# cat read.sh 
#!/bin/sh
File=/etc/passwd
function count(){

        local i=0
while read line
do
        let ++i

done<$File
        echo $i

}

8.Shell数组的应用

1.数组的分类
普通数组:只能使用整数 作为数组索引 
关联数组:可以使用字符串 作为数组索引

2数组赋值方式一, 针对每个索引进行赋值

#数组名[索引]=变量值
[[email protected] ~]# arraytest[0]=zhangsan
[[email protected] ~]# arraytest[1]=lisi
[[email protected] ~]# arraytest[2]=laowang

3数组赋值方式二, 一次赋多个值

#数组名=(多个变量值)
[[email protected] ~]# array=(1 2 3)
[[email protected] ~]# array=(1 2 3 "test" [10]=x86cloud)

3.查看数组赋值结果

[[email protected] ~]# declare –a     #查看普通数组
[[email protected] ~]# declare –A     #查看关联数组

4.如何访问数组中的元数

[[email protected] ~]# echo ${array[0]}  #第一个元素
1
[[email protected] ~]# echo ${array[@]} #访问数组所有的元素
1 2 3 test x86cloud
[[email protected] ~]# echo ${#array[@]}  #统计元素的个数

6.如何访问数组中的索引

# 获取数组元素的索引 !
[[email protected] ~]# echo ${!array[@]}
0 1 2 3 10

7.关联数组
1.定义关联数组,申明是关联数据

[[email protected] ~]# declare -A array_1
[[email protected] ~]# declare -A array_2

2.关联数组的赋值方式一,针对每个索引进行赋值

#数组名[索引]=变量值
[[email protected] ~]# declare -A array_1
[[email protected] ~]# declare -A array_2
[[email protected] ~]# array_1[index1]=zhangsan
[[email protected] ~]# array_1[index2]=lisi
[[email protected] ~]# array_1[index3]=laowang

3.关联数组的赋值方式二,一次赋多个值

[[email protected] ~]# declare array_2=([index1]=x86cloud [index2]=li [index3]=zhang)
[[email protected] ~]# declare –A

3.访问数据元素

[[email protected] ~]# echo ${array_2[index2]}
li
[[email protected] ~]# echo ${array_2[@]}   
x86cloud li zhang
[[email protected] ~]# echo ${!array_2[@]} 
index1 index2 index3

8.遍历数组

已知文件里有名字对应的性别 请统计性别出现的总次数
let array_pa[m]++
let array_pa[f]++
let array_pa[x]++
let array_pa[m]++

[[email protected] ~]# cat sex.txt 
zs m
ls m
lw f
ll m
lz f
lq m
[[email protected] ~]# cat count_sex.sh 
#!/bin/sh
declare -A sex
while read line
do
        type=$(echo $line|awk '{print $2}')
        let sex[$type]++
done<sex.txt
#遍历数组
for i in ${!sex[*]}
do
        echo $i共有${sex[$i]}个
done

案例2
统计nginx日志IP访问次数

[[email protected] ~]# cat nginx_count.sh 
#!/bin/sh
declare -A array_nginx
while read line
do
        type=$(echo $line|awk '{print $1}')
        let array_nginx[$type]++

done</var/log/nginx/access.log

for i in ${!array_nginx[*]}
do
  
    echo "IP是 $i 共出现了${array_nginx[$i]}次"
done

案例3
统计tcp状态信息

[[email protected] ~]# cat nginx_status.sh 
#!/bin/sh
declare -A array_nginx
type=`ss -an|grep 80|awk '{print $2}'`
for i in $type
do
        let     array_nginx[$i]++
done
for n in ${!array_nginx[*]}
do
        echo $n ${array_nginx[$n]}
done
推荐阅读