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