shell编程四

7.函数

7.1 概述

  • 把一堆代码,起个名字。
  • 对脚本中重复使用到的代码,设置函数,精简脚本的内容。
  • 让脚本更加的规范。
  • 应用场景:
    • 在书写脚本的时候,尽量使用函数,规范脚本。
    • 让脚本的开发,更加模块化。
    • 方便后期调试,调试的时候只需要注释函数即可。

7.2 格式及实战应用

7.2.1 函数格式

查看代码
 #定义方式01 最完整
function show() {
命令
命令
内容
return n #函数的返回值
}

#定义方式02 精简写法 一般使用这一种.
show() {
命令
命令
内容
return n #函数的返回值
}

#定义方式03
function show {
命令
命令
内容
return n #函数的返回值
}

7.2.2 基本格式与使用

# 1 创建函数
function test(){
    echo "这是一个函数"
    echo "我的名字是test"
    echo "欢迎大家来调用我 "
}
# 2 调用函数
test

7.2.3 域名是否可以访问函数化

查看代码
 #!/bin/bash
# 1.输入
function input_content(){
    read -p "请输入待检查的ip或域名:" urls
}

# 2.检查urls变量
function check_url(){
   if [ -z "$urls" ] ;then
     echo "请重新输入: $0 ip或域名"
     exit 1
   fi
}

# 3. ping
function ping_url(){        
	# ping检查
	ping -c1 ${url}   &>/dev/null
	# 检查返回值
	if [ $? -eq 0 ];then
	   echo "${url} 可以访问的"
	else
	   echo "${url} 不可以访问的"
	fi
} 

# 4.for 循环
function for_ping(){
    for  url in  $urls
    do
		ping_url
    done
}

# 5. main函数
function main(){
	input_content
	check_url
	for_ping
}

main

7.3 函数传参

函数传参与脚本传参类似。使用$xxxxx形式进行。

位置参数 shell脚本中 函数中
$n 脚本的第n个参数 函数的第n个参数
$0 脚本的名字 脚本的名字
$# 脚本的参数的个数 函数参数个数
$@/ $* 脚本所有的参数 函数所有的参数

7.3.1 $n,$#,$* 在脚本和函数中的区别

查看代码
  #!/bin/bash
##############################################################
# File Name:func_param.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################

function show (){
    echo "show函数说有参数:$*"
    echo "show函数参数个数:$#"
    echo '$1: ' $1
    echo '$2: ' $2
    echo '$3: ' $3
}

show 1 two name  

[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash func_param.sh 1 2 3 4 5 6
show函数说有参数:1 two name
show函数参数个数:3
$1:  1
$2:  two
$3:  name

# 现象:
1. 函数内部调用时,函数名 + 参数  可实现传参 (show 1 two name)
2. 外部调用时,函数名+参数  调用不生效(bash func_param.sh 1 2 3 4 5 6)

7.3.2 函数传参

查看代码
 #!/bin/bash
##############################################################
# File Name:func_param.sh
##############################################################

function show (){
    echo "show函数说有参数:$*"
    echo "show函数参数个数:$#"
    echo '$1: ' $1
    echo '$2: ' $2
    echo '$3: ' $3
}

show $* 
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash func_param.sh 1 2 3 4 5 6
show函数说有参数:1 2 3 4 5 6
show函数参数个数:6
$1:  1
$2:  2
$3:  3
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 

# 解决
1.外部调用时,需在内部函数调用后面+ $* (show $*)
2.外部调用多个函数时,需要在每个调用后 + $*
3.位置参数正常使用即可

7.4 小结

  • 应用:书写脚本尽量使用变量,函数规范脚本。
  • 使用函数流程:分析问题,列出步骤,需求-->步骤-->函数-->命令
  • 把常用的判断,内容写成函数,创建个人函数库.(哪些功能通用的.)
  • 函数传参:$* $@ $n $0

8. 个人函数库搭建

  • 把脚本中常用的功能创建成函数.
  • 系统函数库/etc/init.d/functions

8.1 颜色

8.1.1 各种颜色的字

查看代码
 echo -e "\E[1;31mhello everyone\E[0m"
echo -e "\E[2;31mhello everyone\E[0m"
echo -e "\E[3;31mhello everyone\E[0m"
echo -e "\E[4;31mhello everyone\E[0m"
echo -e "\E[5;31mhello everyone\E[0m"
echo -e "\E[6;31mhello everyone\E[0m"
echo -e "\E[7;31mhello everyone\E[0m"
echo -e "\E[8;31mhello everyone\E[0m"


\E 或\033  # 表示要开启这种功能。
[1;31m     # [字体效果;颜色m
\E[0m      # 颜色设置结束。
在上述命令中:
echo -e可以识别转义字符,这里将识别特殊字符的含义,并输出。 \n \t
Linux下面回车是 \n
Windows下面回车是 \r\n

1表示加粗,2正常的,5表示闪烁

for  n in {30..50}; do  echo -e "\E[1;${n}m${n}hello word\E[0m"   ;done

8.1.2 自定义颜色函数

查看代码
 #!/bin/bash
##############################################################
# File Name:func_color.sh
##############################################################

# 红色闪烁加粗
function red_flicker_echo (){
    local str="$*"
    echo -e "\E[5;31m${str}\E[0m"
}

# 红色加粗
function redecho (){
    local str="$*"
    echo -e "\E[1;31m${str}\E[0m"
}

# 绿色加粗
function greenecho (){
    local str="$*"
    echo -e "\E[1;32m${str}\E[0m"
}

# 黄色加粗
function yellowecho (){
    local str="$*"
    echo -e "\E[1;33m${str}\E[0m"
}

# 蓝色加粗
function blueecho (){
    local str="$*"
    echo -e "\E[1;34m${str}\E[0m"
}

[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 
# 将脚本文件加载到当前环境
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# source func_color.sh 
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 
# 调用自定义字体颜色函数
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# yellowecho hello
hello
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# red hello
red      redecho  rediff   
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# redecho hello
hello
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# blueecho hello
hello
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# greenecho hello
hello
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 

 8.1.3 检查服务状态

查看代码
 #!/bin/bash
##############################################################
# File Name:check_server.sh
##############################################################

# 1.颜色
function redecho (){
    local str="$*"
    echo -e "\E[1;31m${str}\E[0m"
}


function greenecho (){
    local str="$*"
    echo -e "\E[1;32m${str}\E[0m"
}

# 2.参数
service=$1

# 3. 判断参数是否存在
function param_is_exist (){
    test ${#service} -eq 0 && redecho "请输入参数" && exit 1
}

# 4.判断服务是否存在
function services_is_exist(){
    ser_count=`systemctl list-unit-files | grep ${service}.service | wc -l`
    if [ $ser_count = 0 ];then
        redecho "服务不存在"
        exit 1
    fi
}

# 5.判断服务状态
function services_status(){
    active_status=`systemctl is-active ${service}` 
    test  "$active_status" = "active" && greenecho $service "服务启动"  || redecho $service "未启动"

    enabled_status=`systemctl is-enabled ${service}`
    test "$enabled_status" = "enabled" && greenecho $service "服务开机自启" || redecho $service "未做开机自启"
}

# main
function main(){
    param_is_exist
    services_is_exist
    services_status
}

main
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_server_color.sh
请输入参数
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_server_color.sh nginx
nginx 未启动
nginx 未做开机自启
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_server_color.sh sshd
sshd 服务启动
sshd 服务开机自启
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_server_color.sh firewalld
firewalld 服务启动
firewalld 服务开机自启
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# systemctl disable firewalld
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_server_color.sh firewalld
firewalld 服务启动
firewalld 未做开机自启

8.1.4 脚本里引用其他脚本函数

# 1 将其他脚本函数赋值过来
function redecho (){
    local str="$*"
    echo -e "\E[1;31m${str}\E[0m"
}

function greenecho (){
    local str="$*"
    echo -e "\E[1;32m${str}\E[0m"
}

# 2 将其他脚本引用过来(更加专业)
func_include=`/server/scripts/shell-pro/func_color.sh`
if [ -f $func_include ];then 
    . $func_include
else
    echo "函数库 $func_include 不存在,请检查路径"
    exit 1
fi

更多颜色 https://man7.org/linux/man-pages/man4/console_codes.4.html

8.2 判断

  • 判断参数个数
  • 判断参数是否为数字
  • 判断命令返回值

8.3 日志(后续大型脚本使用)

给脚本创建日志.

检查脚本关键步骤,执行情况.

方便后期调试.

 

log函数的需求

查看代码
 # log函数
使用格式:
2个参数
log 警告级别 "执行情况与做啥"
第个参数:警告级别
info 正常信息
error 错误
第2个参数
记录下来的内容
使用
log INFO "执行检查操作"
日志文件内容:
/var/log/脚本名字.log
年-月-日 时:分:秒 [错误级别] "执行情况与做啥"
年-月-日 时:分:秒 [INFO] "执行检查操作"


#日志函数
function log() {
log_file=$0.log
level=$1
msg=$2
time=`date +%F_%T`
echo "$time [${level}] ${msg}" >>$log_file
}


#日志函数
function log() {
#log 级别 内容 文件
level=$1
msg=$2
#日志文件与脚本文件同名存放在/var/log下面
filename=`basename $0`
log_file=/var/log/${filename}.log
time=`date +%F_%T`
echo "$time [$level] $msg" >>$log_file
}

8.4 函数库小结

  • 会创建颜色日志函数.
  • 后面创建脚本的时候把函数直接复制到脚本开头即可.

9. 核心命令

9.1 命令概述

脚本常用监控命令

说明  

端口

一般用于检查端口是否存在,是否能连接

是否存在: ss -lntup|grep 端口号

netstat -lntup |grep lsof -i:80

是否能访问: telnet, nc ,nmap

进程

检查进程状态,指标 ps /top/iotop

网络

检查连通性 ping,iftop(流量),dig(DNS)...

web

http请求 curl/wget

系统全能

atop(all)  

9.2 端口检查

9.2.1 是否存在(远程连接后使用)

ss -lntup |grep 80
netstat -lntup |grep 80
lsof -i:80

9.2.2 能否访问(远程测试)

查看代码
 telnet
nc -z -w 0.5
nmap -p端口过滤open即可

# telnet
-e指定逃脱字符,遇到这个字符相当于按ctrl+c.
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo q | telnet -eq 39.106.44.157 80
Telnet escape character is 'q'.
Trying 39.106.44.157...
Connected to 39.106.44.157.
Escape character is 'q'.

telnet> Connection closed.
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo $?
0
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 

# nc(ncat netcat)
-z 无io模式,用于检查端口是否连通。 非交互模式.
-w 指定超时时间.
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# nc -z 39.106.44.157 80
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo $?
0
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# nc -z -w 0.5 39.106.44.157 80
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo $?
0
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# nc -z -w 0.5 39.106.44.157 22
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# echo $?
0

 9.2.3 检查指定的地址的端口是否可以访问

check_port_color.sh
 #!/bin/bash
##############################################################
# File Name:check_port_color.sh
##############################################################

# 1 颜色函数
function redecho (){
    local str="$*"
    echo -e "\E[1;31m${str}\E[0m"
}

function greenecho (){
    local str="$*"
    echo -e "\E[1;32m${str}\E[0m"
}

# 2 传参
ip=$1
port=$2

# 3 检查参数是否为空
function is_null(){
    if [ -z $ip ];then
		redecho "地址为空"
		exit 1
	fi	 
	 
	if [ -z $port ];then
	    redecho "端口为空"
		exit 1
    fi	
}

# 4 检查命令是否存在
function check_cmd (){
    which nc >/dev/null 2>&1
	[ $? -ne 0 ] &&{
	    redecho "请安装nc"
	    exit 1
	}
}

# 5 ping ip
function ping_ip (){
    ping -c1 -W1 $ip >/dev/null 2>&1
	[ $? -eq 0 ] ||{
	    redecho "ping不通"
		exit 1
	} 
}

# 6 判断指定端口IP能否访问
function telnet_port(){
    ping_ip
	# 判断指定端口IP能否访问
	nc -z $ip $port >/dev/null 2>&1
	if [ $? -eq 0 ];then
		greenecho "$ip 端口 $port 畅通"
		exit 0
	else
		redecho "$ip 端口 $port 不通"
		exit 1
	fi
}

# 7 main
function main (){
    is_null
    check_cmd
    telnet_port
}

main
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_port_color.sh qq.com 80
qq.com 端口 80 畅通
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_port_color.sh 10.0.0.36 80
10.0.0.36 端口 80 不通

9.3 进程检查

参考进程管理部分:ps,top命令。

9.4 网络检查

  • ping
  • iftop
  • .....
-c 2 次数,ping几次
-W timeout 超时时间,等待响应的超时时

9.5 web与api测试命令

curl/wget

curl: -v -L 跟随跳转

   -H 修改请求头

   -I 只显示响应头

       -w 按照指定格式输出

        -o 输出指定到文件或空.

       -s一般使用管道需要加上.

9.5.1 wget

  • wget:
    • -t 失败后,重复尝试次数、
    • -T timeout 超时时间
    • -q quiet 不显示wget输出
    • --spider 不下载文件,仅访问.
[root@Kylin-V10-sp3 ~]# wget -t 3 -T 1 -q --spider www.baidu.com
[root@Kylin-V10-sp3 ~]# echo $?
0
[root@Kylin-V10-sp3 ~]# 

9.5.2 curl

查看代码
 [root@Kylin-V10-sp3 ~]# curl -L -s -I baidu.com |awk 'NR==1{print $2}'
200
[root@Kylin-V10-sp3 ~]# curl -L -s -w '%{http_code}\n' -o /dev/null jd.com
200
[root@Kylin-V10-sp3 ~]#

#01 curl 获取状态码
#-s slient 安静模式 如果不使用默认输出下载进度
#-o curl的输出到指定位置的文件
#-w 按照指定格式与内容输出 %{http_code}状态码 更多格式 man curl 搜索 variable
[root@Kylin-V10-sp3 ~]# curl -s -w '%{http_code}\n' -o /dev/null www.baidu.com
200
[root@Kylin-V10-sp3 ~]# 

#02 curl 获取响应头
[root@Kylin-V10-sp3 ~]# curl -I www.baidu.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Connection: keep-alive
Content-Length: 277
Content-Type: text/html
Date: Wed, 25 Sep 2024 13:20:47 GMT
Etag: "575e1f6f-115"
Last-Modified: Mon, 13 Jun 2016 02:50:23 GMT
Pragma: no-cache
Server: bfe/1.0.8.18

[root@Kylin-V10-sp3 ~]# 

9.5.3 检查指定网站/api是否可以访问

查看代码
 #!/bin/bash
##############################################################
# File Name:net_isvisit.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################

# echo 颜色
function redecho (){
    local str="$*"
    echo -e "\E[5;31m${str}\E[0m"
}

function greenecho (){
    local str="$*"
    echo -e "\E[1;32m${str}\E[0m"
}

# 1 传参
file="/server/files/urls"
urls=`cat $file`

# 2 检查参数是否为空
function is_null(){
    [ -f $file ] ||{
		redecho "文件为空"
		exit 1
	}
}

# 3 检查命令
function check_cmd(){
    which curl >/dev/null 2>&1
    [ $? -ne 0 ] && {
        echo "curl 不存在,请自行安装"
        exit 1
    }
}

# 4 检查网站是否可以访问
function is_visit(){
        curl -Lv $i >/dev/null 2>&1
	if [ $? -eq 0 ];then
		greenecho "$i 可以访问"
	else
		redecho "$i 不可以访问"
	fi
	return $?
}


# 5 循环
function for_nets(){
    for i in $urls
	do
	    is_visit
	done
}

# 6 main
function main(){
    check_cmd 
    is_null
    for_nets
}

main
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash net_isvisit.sh 
10.0.0.36 不可以访问
qq.com 可以访问
baidu.com 可以访问
12306.cn 可以访问
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# 

9.6 全能信息

9.6.1 atop

# 增加一个yum源
wget -O /etc/yum.repos.d/epel.repo
https://mirrors.aliyun.com/repo/epel-7.repo
yum install atop -y
systemctl enable atop
systemctl start atop
atop

9.6.2 glances

wget -O /etc/yum.repos.d/epel.repo
https://mirrors.aliyun.com/repo/epel-7.repo
# 安装
yum install -y glances
#使用
glances
#把输出写入到all.csv文件中 表格
glances --export-csv all.csv
#web页面使用端口是61208
yum install -y python-bottle
glances -w

9.7 命令小结

  • 端口: nc,telnet,nmap
  • 进程: ps,top
  • 网络: ping
  • web: curl/wget
  • ....

9.8 检查域名是否过期

  • 输入一个域名检查域名还有多少天过期
  • 检查www.域名
  • eg: baidu.com
  • 检查baidu.com域名剩余时间
check_domains_expire
'''
Registrar Registration Expiration Date: 2034-07-27T00:00:00+0000
Registry Expiry Date: 2025-07-02T23:59:59.0Z
'''

#!/bin/bash
##############################################################
# File Name:check_domains_expire.sh
# Version:V1.0
# Author:xk
# Organization: none
# Desc:
##############################################################

# 1 vars
domains="jd.com baidu.com 12306.cn"

# 2 diy_funcs
func=/server/scripts/shell-pro/func_color.sh
if [ -f $func ];then 
    . $func
else
    echo "函数库 $func 不存在,请检查路径"
    exit 1
fi

# 3 检查
check_cmd(){
    if ! which whois >/dev/null 2>&1;then
	    echo "whois 命令不存在,请安装"
		echo "kylin jwhois,其它系统whois"
		exit 1
	fi
}

# 4 检查域名过期
check_domains(){
    for domain in $domains
	do
	    # 获取域名过期时间	
	    domain_expire_date=`whois $domain | egrep -i "(Expiry|Expiration) (Date|Time)" | awk -F '[ T]+' '{print $(NF-1)}'`
	    # 将域名过期时间转化为时间戳
	    domain_expire_seconds=`date +%s -d "${domain_expire_date}"`
	    # 将当前时间转化为时间戳
	    domain_today_seconds=`date +%s`
	    # 计算剩余天数
            domain_expire_days=`echo "(${domain_expire_seconds} - ${domain_today_seconds})/60/60/24" | bc`
	    if [ ${domain_expire_days} -le 30 -a ${domain_expire_days} -gt 0 ];then
		redecho "$domain 将要过期,还有$domain_expire_days天"
            elif [ ${domain_expire_days} -le 0 ];then
		redecho "$domain 已经过期,过期了$domain_expire_days天"
	    else
                greenecho "$domain 没有过期,还有$domain_expire_days天"
	    fi
		
	done
}

# 5 主函数
main(){
    check_cmd
    check_domains
}

main
[root@Kylin-V10-sp3 /server/scripts/shell-pro]# bash check_domains_expire.sh
jd.com 没有过期,还有1623天
baidu.com 没有过期,还有744天
12306.cn 没有过期,还有1569天
[root@Kylin-V10-sp3 /server/scripts/shell-pro]#

9.9 小结

  • 根据脚本需要,去使用与选择命令,然后书写对应的语句(变量,判断,循环)。
  • 目标:简单,易用。(能用,然后逐渐优化),多种方法书写脚本.
  • 不断练习,每个脚本步骤与思路。

 

posted @ 2024-09-25 21:56  老虎死了还有狼  阅读(4)  评论(0编辑  收藏  举报