知识体系说明
工作、面试:
配合定时任务执行备份 检查
监控系统:自定义监控(只要能通过命令/脚本取出来的内容 就可以监控)
服务管理脚本:sersync 编译安装的软件 systemctl start|stop|network network
批量维护与管理
shell入坑指南
linux半边天
要求能力:
1. 熟练使用70-80个常见命令
2. 正则与三剑客
3. vim 快捷键 https://www.jianshu.com/p/c5e6724f4c3d
4. 掌握:根据需求 书写脚本能力
如何入坑:
书写建议
把需求拆分 3步或更多
分析每个步骤 给出每个步骤使用的命令 或语法 测试成功
每个步骤ok, 书写合并脚本
测试
学习建议
尽量分析 系统脚本(想得多) 别人发出来的脚本 读懂。
后面模仿
shell基础规则与习惯
基础规则- 执行脚本
#方法1 sh ※※※※※※
[root@manager /server/scripts]# sh 2.3-1-exec.sh
tar: 从成员名中删除开头的“/”
#方法2 .或source
[root@manager /server/scripts]# . 2.3-1-exec.sh
tar: 从成员名中删除开头的“/”
#方法3 输入重定向方法
[root@manager /server/scripts]# sh <2.3-1-exec.sh
tar: 从成员名中删除开头的“/”
[root@manager /server/scripts]# ll /tmp/etc.tar.gz
-rw-r--r-- 1 root root 10246600 1月 8 10:51
/tmp/etc.tar.gz
#linux 支持 < 很多 tr xargs 三剑客
#方法4 绝对路径方法
[root@manager /server/scripts]# ll
/server/scripts/2.3-1-exec.sh
-rwxr-xr-x 1 root root 31 1月 8 10:50
/server/scripts/2.3-1-exec.sh
[root@manager /server/scripts]# /server/scripts/2.3-1-
exec.sh
tar: 从成员名中删除开头的“/”
执行方法 | 应用场景 |
---|---|
sh | 执行各种命令 必备 |
./source | 在脚本中调用使用其他文件方法在脚本中实现nginx include功能 , ./etc/init.d/fuctions 服务、命令检查脚本 |
sh < | 几乎不会用 |
绝对路径 | 系统脚本 系统使用的脚本 需要+x权限 |
#./source 了解
[root@manager /server/scripts]# .
/etc/init.d/functions
[root@manager /server/scripts]# action "crond is
running" /bin/true
crond is running
[ 确定 ]
[root@manager /server/scripts]# action "crond is not
running" /bin/false
crond is not running
[失败]
书写shell脚本的习惯
书写脚本 加上 命令解释器 #!/bin/bash 脚本默认使用的命令解释器
#! 幻数
[root@manager /server/scripts]# head -1 /bin/yum
#!/usr/bin/python
[root@manager /server/scripts]# file 2.3-2-checkweb.sh
3-2-check-web.sh: UTF-8 Unicode text
[root@manager /server/scripts]#
[root@manager /server/scripts]# file 2.3-2-checkweb.sh
2.3-2-check-web.sh: Bourne-Again shell script, UTF-8
Unicode text executable
shell变量
普通变量(局部变量)
变量:
存放我们经常使用的内容(shell脚本中)
本质:内存中空间
空间的位置 变量名
空间的内容 变量值
变量的命名规则
不能以数字开头 最好也不要包含特殊符号 ! - 最好用_ 下划线
命名规律: 推荐 多个单词通过下划线连接 (表名变量的作用) bingbing_age=16
驼峰写法: 多个单词从第2个单词开始 首字母大写 lidaoAge=99 numberOfPeople=61
变量赋值注意事项
[root@manager /server/scripts]# oldbing=666
[root@manager /server/scripts]# echo $oldbing
666
[root@manager /server/scripts]# oldbing=爱生活 爱冰冰
-bash: 爱冰冰: 未找到命令
[root@manager /server/scripts]# oldbing="爱生活 爱冰冰"
[root@manager /server/scripts]# echo $oldbing
爱生活 爱冰冰
引号 | 含义 |
---|---|
单引号 | 所见即所得 单引号里面内容 原封不动输出 |
双引号 | 与单引号类似 解析特殊符号 `` $() ! |
不加引号 | 与双引号类似 支持通配符 * {} |
反引号 | 优先执行命令 |
example:
[root@manager ~]# echo '$PATH $(hostname) `whoami`
{1..5}'
$PATH $(hostname) `whoami` {1..5}
[root@manager ~]# echo "$PATH $(hostname) `whoami`
{1..5}"
/sbin:/usr/sbin:/bin:/usr/bin manager root {1..5}
[root@manager ~]# echo $PATH $(hostname) `whoami`
{1..5}
/sbin:/usr/sbin:/bin:/usr/bin manager root 1 2 3 4 5
环境变量(全局变量)
特点
1.Linux系统创建
2.大写
3.Linux大部分地方都可以使用
查看所有环境变量
env
export
declare
创建环境变量
[root@manager ~]# oldboy=666
[root@manager ~]# echo $oldboy
666
[root@manager ~]# env |grep oldboy
[root@manager ~]# #export 变量 变量成为环境变量
[root@manager ~]# export oldboy=666
[root@manager ~]# env |grep oldboy
oldboy=666
环境变量相关的文件和目录
环境变量相关文件和目录 | 应用场景 | |
---|---|---|
/etc/profile | 别名 环境变量 | |
/etc/bashrc | 别名 | |
~/.bashrc | 当前用户的别名 | |
~/.bash_profile | 当前用户环境变量 | |
/etc/profile.d/ | 目录里面的内容 .sh结尾的 会在用户登录后运行 | 存放shell跳板机脚本存放用户行为记录脚本 |
shell特殊变量
表示位置的特殊变量
位置变量 | 例子 | 含义 |
---|---|---|
$数字 | $1,$1… | 脚本的第1个 第2个参数 |
$0 | echo "Usage: $0{start|restart|stop}" | 脚本的文件名 |
$# | 脚本参数的个数 脚本一共有几个参数 | |
$* | 取出脚本所有的参数 | |
$@ | 取出脚本所有的参数 |
1. $数字
#基础用法
[root@manager ~]# cat /server/scripts/2.5-1-arg.sh
#!/bin/bash
echo $1 $2
[root@manager ~]# sh /server/scripts/2.5-1-arg.sh a b
a b
[root@manager ~]#
#实际案例
/etc/init.d/network start === $1=start
#进阶: 脚本有多个参数
[root@manager ~]# echo echo \${1..12}
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12
[root@manager ~]# echo echo \${1..12} >>
/server/scripts/2.5-1-arg.sh
[root@manager ~]# cat /server/scripts/2.5-1-arg.sh
#!/bin/bash
echo $1 $2
echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12
[root@manager ~]# sh /server/scripts/2.5-1-arg.sh
{1..12}
1 2
1 2 3 4 5 6 7 8 9 10 11 12
#脚本参数超过9个 脚本参数需要使用 ${10} ${11} ※※※※※※
[root@manager ~]# cat /server/scripts/2.5-1-arg.sh
#!/bin/bash
echo ${1} ${2}
echo ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9}
${10} ${11} ${12}
[root@manager ~]# sh /server/scripts/2.5-1-arg.sh
{a..z}
a b
a b c d e f g h i j k l
#认识 ${} $ 一致 取出变量的内容
[root@manager ~]# age=18
[root@manager ~]# echo $age
18
[root@manager ~]# echo $agesui
[root@manager ~]# echo ${age}sui
18sui
[root@manager ~]# #金庸新作
[root@manager ~]# #${金庸}新作
小结
$数字 脚本传参 命令行内容 传递到脚本的内部 /etc/init.d/network start
#脚本参数超过9个 脚本参数需要使用 ${10} ${11}
$与${}
2. $0
脚本的名字
#简单案例
[root@manager ~]# cd /server/scripts/
[root@manager /server/scripts]# sh 2.5-1-arg.sh
2.5-1-arg.sh
[root@manager /server/scripts]# sh
/server/scripts/../../server/scripts/2.5-1-arg.sh
/server/scripts/../../server/scripts/2.5-1-arg.sh
#实际应用
#书写脚本 如果脚本执行出错 错误提示会使用 $0
##usage 使用帮助 使用说明
[root@manager /server/scripts]# /etc/init.d/network
oldboy
Usage: /etc/init.d/network {start|stop|status|restart|force-reload}
$0
[root@manager /server/scripts]# sh 2.5-1-arg.sh
2.5-1-arg.sh
Usage: 2.5-1-arg.sh {start|stop|restart}
[root@manager /server/scripts]# cat 2.5-1-arg.sh
#!/bin/bash
echo ${1} ${2}
echo ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9}
${10} ${11} ${12}
echo $0
echo "Usage: $0 {start|stop|restart}"
小结
$0 使用在 脚本遇到错误的时候 错误提示
3. $# 脚本参数的个数
#基础用法
[root@manager /server/scripts]# cat 2.5-1-arg.sh
#!/bin/bash
#echo ${1} ${2}
#echo ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9}
${10} ${11} ${12}
#echo $0
#echo "Usage: $0 {start|stop|restart}"
echo $1 $2 $#
[root@manager /server/scripts]# sh 2.5-1-arg.sh
0
[root@manager /server/scripts]# sh 2.5-1-arg.sh
oldboy oldbing lidao
oldboy oldbing 3
#实际应用
##一般与 判断一起使用 如果脚本参数个数=0 ? 提示报错信息
/etc/init.d/network
案例 : /etc/init.d/functions
452 if [ "$#" = 0 ] ; then
453 echo "Usage: status [-p pidfile]
{program}"
454 return 1
455 fi
小结
$# 脚本参数的个数
一般配合判断 判断脚本参数个数如果是0 提示报错信息
4. $ 与 $@*
$* | 取出脚本所有参数 $1 $2 $3 …$999 一般配合循环 | 加上双引号的时候区别 : 表示1个整体 1个参数 |
$@ | 取出脚本所有参数 $1 $2 $3 …$999 一般配合循环 | 加上双引号的时候区别 : 每个参数独立 |
$* 和 $@区别
#set 可以设置命令行参数
[root@manager ~]# set oldboy alex
[root@manager ~]# echo $1
oldboy
[root@manager ~]# echo $2
alex
# 通过set 测试 $* $@ 区别
[root@manager ~]# set oldboy oldbing oldlidao
oldguo
[root@manager ~]# for n in "$*"; do echo $n; done
oldboy oldbing oldlidao oldguo
[root@manager ~]# for n in $*; do echo $n; done
oldboy
oldbing
oldlidao
oldguo
[root@manager ~]# for n in $@ ; do echo $n; done
oldboy
oldbing
oldlidao
oldguo
[root@manager ~]# for n in "$@" ; do echo $n; done
oldboy
oldbing
oldlidao
oldguo
# 了解: $@ "$@" 区别
[root@manager ~]# set "I am" oldboy linux teacher
[root@manager ~]# echo $#
4
[root@manager ~]# for n in $@ ; do echo $n; done
I
am
oldboy
linux
teacher
[root@manager ~]# for n in "$@" ; do echo $n; done
I am
oldboy
linux
teacher
小结
$* $@ 取出脚本所有参数 一般配合for循环使用
$* $@ 区别
5. 位置参数小结
位置变量 | 含义 | 应用场景 |
---|---|---|
$数字 | 脚本的第1个 第2个参数 | 实现脚本传参/etc/init.d/network start服务管理脚本 |
$0 | 脚本的名称 | 脚本执行报错 错误提示中 使用echo "Usage: $0 start |
$# | 脚本参数的个数 脚本一共有几个参数 | 一般与判断一起使用 检查脚本参数个数是否为0 |
$* | 取出脚本所有的参数 | 一般与for循环一起使用 ; 与shell数组一起使用 |
$@ | 取出脚本所有的参数 | 一般与for循环一起使用 ; 与shell数组一起使用 |
表示状态变量
1. $?
# $? 上1个命令或脚本 返回值
#简单含义 与 应用
##0 表示成功
##非0 表示故障 失败
root@manager ~]# ls
ansible_playbook ansible_tasks
student.txt
ansible-project1 ansible_variables
yj.sh
ansible_role ansible_variableszip.zip
ansible_role_2019-12-23.zip ssh-key.sh
[root@manager ~]# echo $?
0
#应用
##与判断 结合 检查命令 脚本执行是否成功
#ping wget 。。。。
[ "$?" -eq 0 ] #equal 等于 判断返回值如果是0 则xxx
小结
$? 配合判断 检查命令 脚本 执行是否成功
2. $$
# $$ 当前脚本的pid 进程id
###pid文件
[root@manager ~]# systemctl start nginx
[root@manager ~]#
[root@manager ~]# ps -ef |grep nginx
root 8504 1 0 11:33 ? 00:00:00
nginx: master process /usr/sbin/nginx
nginx 8505 8504 0 11:33 ? 00:00:00
nginx: worker process
root 8507 7560 0 11:33 pts/0 00:00:00 grep
--color=auto nginx
[root@manager ~]# #kill 8504
[root@manager ~]# cat /run/nginx.pid
8504
[root@manager ~]# kill `cat /run/nginx.pid`
[root@manager ~]# ps -ef |grep nginx
root 8519 7560 0 11:35 pts/0 00:00:00 grep
--color=auto nginx
### 手动创建pid文件
[root@manager ~]# cat /server/scripts/2.5-3-pid.sh
#!/bin/bash
#author:oldboy lidao
echo $$
sleep 9999
[root@manager ~]#
[root@manager ~]# sh /server/scripts/2.5-3-pid.sh
8578
[root@manager ~]# ps -ef |grep 8578
root 8578 7560 0 11:36 pts/0 00:00:00 sh
/server/scripts/2.5-3-pid.sh
root 8579 8578 0 11:36 pts/0 00:00:00
sleep 9999
root 8581 7493 0 11:37 pts/2 00:00:00 grep
--color=auto 8578
[root@manager ~]#
[root@manager ~]# echo oldboy
oldboy
[root@manager ~]# echo oldboy |tee oldboy.txt
oldboy
[root@manager ~]# cat oldboy.txt
oldboy
[root@manager ~]# #tee 多向输出 前面的信息输出屏幕 同时写入
到文件
`
[root@manager ~]# cat /server/scripts/2.5-3-pid.sh
#!/bin/bash
#author:oldboy lidao
echo $$ |tee /run/lidao.pid
sleep 9999
[root@manager ~]# sh /server/scripts/2.5-3-pid.sh
8589
[root@manager ~]# cat /run/lidao.pid
8589
小结
$$ 在脚本中获取 脚本的pid 创建pid文件
3. 表示状态环境变量小结
变量子串
对变量的内容 进行 替换 删除
变量子串 parameter表示变量 | |
---|---|
基础 | |
${parameter} | 取变量内容 |
${#parameter} | 统计变量的长度(多少个字符) |
截取 类似cut 命令 | |
${parameter:1} | |
${parameter:1:2} | |
删除 | |
${parameter#word} | 删除 |
${parameter##word} | |
${parameter%word} | |
${parameter%%word} | |
替换 | |
${parameter/找谁/替换为什么} | |
${parameter//找谁/替换为什么} |
1. ${#parameter}
#基础用法
[root@manager ~]# oldboy=oldbing
[root@manager ~]# echo ${oldboy}
oldbing
[root@manager ~]# echo ${#oldboy}
7
#企业面试题
##4.3-1面试题: I am oldboy linux,welcome to our
training. 显示这串字符中 单词字符数大于6的单词
##分析:
###1.通过for循环 取出每个单词
###2.判断 字符数 > 6 ?
###1)大于6显示
###2)不大于 继续 读取下1个单词
[root@manager ~]# vim /server/scripts/2.5-3-word.sh
#!/bin/bash
#author oldboy lidao
str="I am oldboy linux,welcome to our training. "
for n in $str
do
if [ ${#n} -gt 6 ] #great than
then
echo ${#n} $n
fi
done
[root@yida scripts]# cat test_word.sh
#!/bin/bash
str=$(echo 'I am oldboy linux,welcome to our training.' |sed 's#[,.]# #g')
for n in $str
do
if [ ${#n} -gt 6 ]
then
echo ${#n} $n
fi
done
[root@yida scripts]# sh test_word.sh
7 welcome
8 training
[root@manager ~]# echo I am oldboy linux,welcome to our
training.|
> awk -vRS="[ ,.]" 'length()>6'
welcome
training
2. 变量截取
[root@manager ~]# oldboy=oldboyedu.com
[root@manager ~]# #echo ${oldboy:起始点:一共取多少个字符}
[root@manager ~]#
[root@manager ~]# echo ${oldboy:4:3}
oye
#截取功能字符是从0开始
[root@manager ~]# echo ${oldboy:3:3}
boy
[root@manager ~]# echo ${oldboy:3}
boyedu.com
3. 删除
${parameter#word} | # 删除匹配前缀(去掉左边,最短匹配模式) |
---|---|
${parameter##word} | ## 删除匹配前缀(去掉左边最长匹配模式) |
${parameter%word} | % 删除匹配后缀( 去掉右边,最短匹配模式) |
${parameter%%word} | %% 删除匹配后缀(去掉右边,最长匹配模式) |
#简单使用
[root@manager ~]# test='I am oldboy teacher'
[root@manager ~]# echo ${test#I}
am oldboy teacher
[root@manager ~]# echo ${test#o}
I am oldboy teacher
[root@manager ~]# echo ${test#I am o}
ldboy teacher
[root@manager ~]# echo ${test#*o}
ldboy teacher
[root@manager ~]# echo ${test##*o}
y teacher
[root@manager ~]# test='I am oldboy teacher'
[root@manager ~]# echo ${test%r}
I am oldboy teache
[root@manager ~]# echo ${test%er}
I am oldboy teach
[root@manager ~]# echo ${test%o*}
I am oldb
[root@manager ~]# echo ${test%%o*}
I am
#应用
##简单 sed 比较麻烦 使用 变量子串里面删除功能
[root@manager ~]# net='/etc/sysconfig/networkscripts/ifcfg-eth0'
[root@manager ~]#
[root@manager ~]# echo ${net##*/}
ifcfg-eth0
[root@manager ~]# echo ${net%%/*}
[root@manager ~]# echo ${net%/*}
/etc/sysconfig/network-scripts
[root@manager ~]#
[root@manager ~]# dirname /etc/sysconfig/networkscripts/ifcfg-eth0
/etc/sysconfig/network-scripts
[root@manager ~]# basename /etc/sysconfig/networkscripts/ifcfg-eth0
ifcfg-eth0
#使用linux命令 效率 比 变量子串 低
root@manager ~]# time for n in {1..10000} ;do echo
${#n} &>/dev/null ; done
real 0m0.154s
user 0m0.097s
sys 0m0.056s
[root@manager ~]# time for n in {1..10000} ;do
echo ${n}|wc -L &>/dev/null ; done
real 0m20.292s
user 0m8.485s
sys 0m11.692s
小结:
变量子串删除部分 主要用来在脚本中删除路径 里面的名字 或路径部分
4. 替换
替换 | |
---|---|
${parameter/找谁/替换为什么} | 只替换第1个 |
${parameter//找谁/替换为什么} | 全局替换 |
[root@manager ~]# test='I am oldboy teacher'
[root@manager ~]# echo ${test/[a-z]/oldboy}
I oldboym oldboy teacher
[root@manager ~]# echo ${test//[a-z]/oldboy}
I oldboyoldboy oldboyoldboyoldboyoldboyoldboyoldboy
oldboyoldboyoldboyoldboyoldboyoldboyoldboy
[root@manager ~]#
[root@manager ~]# test='I am oldboy teacher'
[root@manager ~]# echo ${test//oldboy/}
I am teacher
[root@manager ~]# echo ${test/oldboy/} #把oldboy替换为空
即删除
I am teacher
5. 变量子串小结
变量子串 parameter表示变量 | |
---|---|
基础 | |
${parameter} | 取变量内容 |
${#parameter} | 统计变量的长度 (多少个字符) |
截取(切片) 类似cut 命令 | 用法:cut -c |
${parameter:1} | |
${parameter:1:2} | |
删除 | 处理文件名路径 |
${parameter#word} | 删除变量中开头的word 最小匹配 |
${parameter##word} | 删除变量中开头的word 最长匹配 |
${parameter%word} | 删除变量中结尾的word 最小匹配 |
${parameter%%word} | 删除变量中结尾的word 最长匹配 |
替换 | |
${parameter/找谁/替换为什么} | 最小匹配 |
${parameter//找谁/替换为什么} | 最大匹配 |
#通配符
*
{}
[]
[^]
?
特殊变量
功能: 实现给变量设置默认值。
内容 | 含义 |
---|---|
${parameter:-word} | 如果parameter没有被赋值或者其值为空,那么就以word作为其值 |
${parameter:=word} | 如果parameter没有被赋值或者其值为空,那么就以word作为其值,并且将word赋值给parameter |
${parameter:?word} | 如果parameter没有被赋值或者其值为空,那么就把word作为错误输出.否则显示parameter内容 |
${parameter:+word} | 如果parameter没有被赋值或者其值为空,就什么都不做.否则用word替换变量内容 |
[root@manager ~]# echo $oldbing
[root@manager ~]# echo ${oldbing:-14}
14
[root@manager ~]# oldbing=13
[root@manager ~]# echo ${oldbing:-14}
13
[root@manager ~]# echo ${lidao:-14}
14
[root@manager ~]# echo $lidao
[root@manager ~]# echo ${lidao:=14}
14
[root@manager ~]# echo $lidao
14
[root@manager ~]# echo ${lidao:?14}
-bash: lidao: 14
root@manager ~]# lidao=99
[root@manager ~]# echo ${lidao:+14}
14
[root@manager ~]# echo ${lidaov2:+14}
6. 特殊变量总结
状态
位置变量 man bash Special Parameters 特殊参数
变量子串 man bash parameter expansion 变量扩展
位置变量
状态变量
变量子串
其他变量
特殊变量
位置变量 | $数字 $0 $# $ $@* |
---|---|
状态 | $? $$ $_ $! |
变量子串 | 基础${oldboy} ${#oldboy} |
截取${parameter:1} ${parameter:1:2} | |
删除${oldboy#word} ${oldboy%word} | |
替换${oldboy/谁/替换为什么} ${oldboy//谁/替换为什么} | |
变量扩展 | 给变量设置默认值:${oldboy:-word}${oldboy:=word} |
运算
运算符
注:
i=i+1 i++ 计数统计次数
sum=sum+xxx
sum+=xxxx 累加求和
[root@manager ~]# #生成指定范围的随机数
[root@manager ~]## echo $RANDOM%数字 |bc
Linux计算方法
计算方法 | |
---|---|
bc | |
(()) | |
let | |
awk | |
expr | |
$[ ] |
1. bc basic calc
#基础用法
[root@manager ~]# echo 1+2 |bc
3
[root@manager ~]# echo 10/3 |bc
3
[root@manager ~]# echo 1/3 |bc
0
#bc显示小数
[root@manager ~]# echo 1/3 |bc -l
.33333333333333333333
[root@manager ~]# echo 10/3 |bc -l
3.33333333333333333333
[root@manager ~]#
#指定位数的小数 了解
[root@manager ~]# echo 'scale=2;10/3' |bc -l
3.33
2. (())
[root@manager ~]# ((1+1))
[root@manager ~]# ((a=1+1))
[root@manager ~]# echo $a
2
[root@manager ~]# ((i=i+1))
[root@manager ~]# echo $i
1
[root@manager ~]# ((i=i+1))
[root@manager ~]# echo $i
2
[root@manager ~]# ((i=i+1))
[root@manager ~]# echo $i
3
[root@manager ~]# echo $((1+1))
2
3. let
[root@manager ~]# unset i
[root@manager ~]# let i++
[root@manager ~]# echo $i
1
[root@manager ~]# let i++
[root@manager ~]# echo $i
2
[root@manager ~]# let a=1+1
[root@manager ~]# echo $a
2
4. awk
[root@manager ~]# awk 'BEGIN{print 1/3}'
0.333333
[root@manager ~]# awk 'BEGIN{print 1/3,2^10,2^16}'
0.333333 1024 65536
5. expr
#基本及小坑
#使用 * 乘法 需要转义
[root@manager /opt]# expr 10 * 10
100
[root@manager /opt]# expr 10 \* 10
100
#隐藏功能 判断参数、变量是否为数字
[root@manager /opt]# expr 10 + 10
20
[root@manager /opt]# echo $?
0
[root@manager /opt]# expr a + 10
expr: non-integer argument
[root@manager /opt]# echo $?
2
#判断参数、变量是否为数字
[root@manager /opt]# expr 10 + b
expr: non-integer argument
[root@manager /opt]# echo $?
2
[root@manager /opt]# expr 10 + 10b
expr: non-integer argument
[root@manager /opt]# echo $?
2
# 使用expr判断参数是否为数字 坑
[root@manager /opt]# x=0
[root@manager /opt]# y=0
[root@manager /opt]# expr $x + $y
0
[root@manager /opt]# echo $?
1
[root@manager /opt]# expr $x + $y + 1
1
[root@manager /opt]# echo $?
0
6. $[ ]
[root@manager /opt]# echo $[1+1]
2
[root@manager /opt]# echo $[1/3]
0
7. 运算方法小结
计算方法 | |
---|---|
bc | 计算 显示小数 |
(()) | 计算整数 里面变量直接使用 不需要加上$ ((运算公式)) 输出到屏幕 echo $(()) |
let | 计算整数 里面变量直接使用 不需要加上$ 后面接上 公式 |
awk | 计算 显示小数 过滤 |
expr | 计算整数 判断参数或变量是否为数字 |
$[ ] | 计算整数 |
shell条件语句 条件表达式
条件表达式----通过 符号 判断 文件 变量 比较大小放在 if判断 或 循环中
基础格式
格式 | |
---|---|
test <条件> | |
[ <条件> ] | 一般情况通用 |
[[ <条件> ]] | [ ] 升级版 支持正则表达式 |
(( <条件> )) |
判断文件相关
表达式符号 | |
---|---|
-f | file 判断文件是否存在 存在则为真 |
-d | directory 判断目录是否存在 存在则为真 |
-e | exist 判断这个是否存在(文件 目录 软连接) |
-x | execute 判断是否有x权限 |
-s | size 判断文件是否为空 (大小是否为0) 如果大于0 则为真 |
-r | read 是否有读 |
-w | write 是否有写 |
-L | Symlink (symbolic link或soft link) 判断文件是否存在并且 是否为软连接 |
f1 -nt f2 | file1 newer than file2 |
f1 -ot f2 | file2 older than file2 |
[root@manager /opt]# [ -f /etc/hosts ]
[root@manager /opt]# [ -f /etc/hos ]
[root@manager /opt]# echo $?
1
[root@manager /opt]# [ -f /etc/hosts ] && echo 真 存在
|| echo 假 不存在
真 存在
[root@manager /opt]# [ -f /etc/host ] && echo 真 存在
|| echo 假 不存在
-bash: cho: command not found
假 不存在
[root@manager ~]# [ -f /etc/hosts ] && echo 真 存在
|| echo 假 不存在
真 存在
[root@manager ~]# [ -d /etc/hosts ] && echo 真 存在
|| echo 假 不存在
假 不存在
[root@manager ~]# [ -d /etc/init.d ] && echo 真 存在
|| echo 假 不存在
真 存在
[root@manager ~]# [ -x /sbin/ip ] && echo 真 存在 ||
echo 假 不存在
真 存在
#
[ -x /sbin/ip ] || exit 1
#-s
[root@manager ~]# > oldboy.txt
[root@manager ~]# [ -s oldboy.txt ] && echo 真 ||
echo 假
假
[root@manager ~]# echo 1 >oldboy.txt
[root@manager ~]# [ -s oldboy.txt ] && echo 真 ||
echo 假
真
字符串比较
符号 | 含义 |
---|---|
"串1" = "串2" | 判断两个字符串 是否相等 如果相等则真 |
"串1" != "串2" | 判断两个字符串 是否相等 如果不相等则真 |
-z | zero 如果字符串、变量 是空的 则为真 |
-n | not zero 如果字符串、变量 不是空的 则为真 |
# 判断字符串是否相等
[root@manager ~]# [ "oldboy" = "oldboy" ] && echo 等于
||echo 不等于
等于
[root@manager ~]# [ "oldboy" != "oldboy" ] && echo 不等
于 ||echo 等于
等于
[root@manager ~]#
# 小坑
[root@manager ~]# [ "oldboy" = "oldboy" ] && echo 等于
||echo 不等于
等于
[root@manager ~]# [ "oldboy" != "oldboy" ] && echo 不等
于 ||echo 等于
等于
[root@manager ~]#
[root@manager ~]# echo $oldboy
[root@manager ~]# [ -z $oldboy ] && echo 空 || echo 不
空
空
[root@manager ~]# [ -n $oldboy ] && echo 不空 || echo
空
不空
#在使用字符串 变量比较时候要使用双引号 把字符串或变量引起来
[root@manager ~]#
[root@manager ~]# [ -n "$oldboy" ] && echo 不空 || echo
空
空
#实际案例
[ "${NETWORKING}" = "no" ] && exit 6
if [ -z "$DEVICE" ] ; then DEVICE="$i"; fi
小结:
给字符串、变量 加上双引号
一般配合if
数字比较
[root@manager ~]# [ 1 -eq 1 ] && echo 真 ||echo 假
真
[root@manager ~]# [ 99 -gt 1 ] && echo 真 ||echo 假
真
[root@manager ~]# [ 1 -gt -10 ] && echo 真 ||echo 假
真
[root@manager ~]# [ 1.1 -gt -10 ] && echo 真 ||echo 假
-bash: [: 1.1: 期待整数表达式
假
[root@manager ~]# [ 1 -gt -10 ] && echo 真 ||echo 假
真
[root@manager ~]# test 1 -gt -10 && echo 真 ||echo 假
真
[root@manager ~]#
[root@manager ~]#
[root@manager ~]#
[root@manager ~]#
[root@manager ~]# [[ 2 >= 10 ]] && echo 真 ||echo 假
-bash: 条件表达式中有语法错误
-bash: `10' 附近有语法错误
[root@manager ~]# [[ 2 > 10 ]] && echo 真 ||echo 假
真
[root@manager ~]# (( 2 >= 10 )) && echo 真 ||echo 假
假
[root@manager ~]# (( 2 <= 10 )) && echo 真 ||echo 假
真
条件表达式的使用格式
[ 条件 ] && {
命令1
命令2
命令3
}
[ 条件 ] || {
命令1
命令2
命令3
}
#脚本输入2个参数 比较两个是否相等 相等 显示相等 不相等显示不相
等
#脚本输入2个参数 比较两个数字大小 大于 显示 > 小于 <
等于 =
#脚本输入2个参数 比较两个数字大小 大于 显示 > 小于 <
等于 = 输入必须是数字
#脚本输入2个参数 比较两个是否相等 相等 显示相等 不相等显示不相
等
#脚本输入2个参数 比较两个是否相等 相等 显示相等 不相等显示不相
等
##分析:
###通过命令行传递 2个参数 给脚本
####判断参数个数如果不是2
###脚本对比两个参数 一致
####如果相等
####如果不等
[root@manager /server/scripts]# sh 2.5-4-comp.sh
Must have two args
[root@manager /server/scripts]# sh 2.5-4-comp.sh 10
2b
Usage: Must have two number
[root@manager /server/scripts]# sh 2.5-4-comp.sh 10
20
10 -lt 20
[root@manager /server/scripts]# sh 2.5-4-comp.sh 20
10
20 -gt 10
[root@manager /server/scripts]# sh 2.5-4-comp.sh 10
10
10 -eq 10
逻辑测试符号
逻辑运算符 [ ] 或 test | [[ ]] | |
---|---|---|
-a | and并且 | && |
-o | or或者 | || |
! | !取反 | ! |
[root@manager /server/scripts]# [ -d /etc -a -f
/etc/hosts ] && echo 1 真 || echo 0 假
1 真
[root@manager /server/scripts]# [ -d /et -a -f
/etc/hosts ] && echo 1 真 || echo 0 假
0 假
[root@manager /server/scripts]# [ -d /et -o -f
/etc/hosts ] && echo 1 真 || echo 0 假
1 真
[root@manager /server/scripts]#
[root@manager /server/scripts]# [ ! -d /et ] &&
echo 1 真 || echo 0 假
1 真
#表示大于等于10并且小于等于100的数字
[root@manager /server/scripts]# num=4
[root@manager /server/scripts]# [ $num -ge 10 -a $num
-le 100 ] && echo 1 || echo 0
0
[root@manager /server/scripts]# num=50
[root@manager /server/scripts]# [ $num -ge 10 -a $num
-le 100 ] && echo 1 || echo 0
1
[root@manager /server/scripts]# test $num -ge 10 -a
$num -le 100 && echo 1 || echo 0
1
[root@manager /server/scripts]#
[root@manager /server/scripts]# [[ $num -ge 10 && $num
-le 100 ]] && echo 1 || echo 0
1
[root@manager /server/scripts]# # 10 ~ 100
[root@manager /server/scripts]# # <10 >100
[root@manager /server/scripts]#
[root@manager /server/scripts]# num=1
[root@manager /server/scripts]# [ ! $num -ge 10 -o !
$num -le 100 ] && echo 1 || echo 0
1
[root@manager /server/scripts]# [ $num -lt 10 -o
$num -gt 100 ] && echo 1 || echo 0
1
正则表达式
[[ “oldboy123” =~ ^[0-9]+$ ]]
[root@manager ~]# [[ "12345" =~ [0-9] ]] && echo 1
|| echo 0
1
[root@manager ~]# [[ "oldboy" =~ [0-9] ]] && echo 1
|| echo 0
0
[root@manager ~]# [[ "oldboy123" =~ [0-9] ]] && echo
1 || echo 0
1
#精确匹配数字
[root@manager ~]# [[ "oldboy123" =~ ^[0-9]+$ ]] &&
echo 1 || echo 0
0
命令行传入1个字符或数字,数字等于1则显示1,如果等于2则显示2,如果
既不等于1也不等于2,就显示输入不对,然后退出程序
从命令行传入1个参数
是否为1或2,否则退出
如果1 显示1
如果2 显示2
[root@manager ~]# cat /server/scripts/2.5-5-input.sh
#!/bin/bash
#author: oldboy
str=$1
#[ "$str" -ne 1 -o "$str" -ne 2 ]
[[ ! "$str" =~ ^[12]$ ]] && {
echo input error
exit 1
}
[ "$str" -eq 1 ] && echo 1
[ "$str" -eq 2 ] && echo 2
[root@manager ~]# sh /server/scripts/2.5-5-input.sh
input error
[root@manager ~]# sh /server/scripts/2.5-5-input.sh 3
input error
[root@manager ~]# sh /server/scripts/2.5-5-input.sh
12
input error
[root@manager ~]# sh /server/scripts/2.5-5-input.sh 1
1
[root@manager ~]# sh /server/scripts/2.5-5-input.sh 2
2
[root@manager ~]# sh /server/scripts/2.5-5-input.sh a
input error
[root@manager ~]# [[ "oldboy123" =~ [12] ]] && echo
1 || echo 0
1
[root@manager ~]# [[ "1" =~ [12] ]] && echo 1 ||
echo 0
1
[root@manager ~]# [[ "2" =~ [12] ]] && echo 1 ||
echo 0
1
[root@manager ~]# [[ "12" =~ [12] ]] && echo 1 ||
echo 0
1
[root@manager ~]# [[ "12" =~ ^[12]$ ]] && echo 1 ||
echo 0
[root@manager ~]# [[ "12" =~ ^[12]$ ]] && echo 1 ||
echo 0
0
[root@manager ~]# [[ "1111" =~ ^[12]$ ]] && echo 1
|| echo 0
0
[root@manager ~]# [[ "1" =~ ^[12]$ ]] && echo 1 ||
echo 0
1
[root@manager ~]# [[ "2" =~ ^[12]$ ]] && echo 1 ||
echo 0
1
条件表达式总结
内容 | |
---|---|
符号 | test [ ] [[ ]] (()) |
文件 | -d -f -x -s -r -w -L -h |
字符串 | 使用双引号 = != -z -n |
数字 | -eq -ne -gt -ge -le -lt |
逻辑 | -a -o ! |
正则 | [[ 变量/字符 =~ 正则 ]] |
变量与后台运行
变量赋值方式
赋值方式 | 案例 |
---|---|
直接赋值 | oldboy=123 ; name=`hostname` |
参数传递(脚本传参) | oldboy=$1 sh oldboy.sh 10 |
通过read赋值 交互式赋值 | read -p ‘input password:’ pass |
#read交互式 复制
[root@manager ~]# read -p 'input password:' pass
input password:*******
[root@manager ~]# read -p 'input password:' pass
input password:oldboy
[root@manager ~]# echo $pass
oldboy
#read交互式赋值多个变量
[root@manager ~]# read -p 'input num1 num2:' n1 n2
input num1 num2:10 20
[root@manager ~]# echo $n1
10
[root@manager ~]# echo $n2
20
#把 之前比较大小 脚本修改为read命令方式
[root@manager ~]# cat /server/scripts/2.8-1-compread.sh
#!/bin/bash
#author: oldboy
read -p "input num1 num2:" num1 num2
#number
#expr $num1 + $num2 + 1 &>/dev/null
#[ $? -ne 0 ] && {
[[ "$num1" =~ ^[0-9]+$ && "$num2" =~ ^[0-9]+$ ]] || {
echo "Usage: Must have two number"
exit 2
}
#compare
[ $num1 -gt $num2 ] && echo "$num1 -gt $num2"
[ $num1 -lt $num2 ] && echo "$num1 -lt $num2"
[ $num1 -eq $num2 ] && echo "$num1 -eq $num2"
[root@manager ~]#
[root@manager ~]# sh /server/scripts/2.8-1-compread.sh
input num1 num2:10 20
10 -lt 20
[root@manager ~]# sh /server/scripts/2.8-1-compread.sh
input num1 num2:10 10b
Usage: Must have two number
[root@manager ~]# sh /server/scripts/2.8-1-compread.sh
input num1 num2:10
Usage: Must have two number
[root@manager ~]# sh /server/scripts/2.8-1-compread.sh
input num1 num2:20b
Usage: Must have two number
[root@manager ~]# sh /server/scripts/2.8-1-compread.sh
input num1 num2:
Usage: Must have two number
命令、脚本后台运行
让命令或脚本去后台运行 防止断网 远程连接工具突然断开
后台运行方法 |
---|
& 或 nohup command & |
ctrl + z 与 bg |
screen |
1. & 或 nohup command &
[root@manager ~]# sleep 99 &
[1] 7965
[root@manager ~]# ps -ef |grep sleep
root 7965 7944 0 11:14 pts/0 00:00:00 sleep
99
root 7967 7944 0 11:14 pts/0 00:00:00 grep
--color=auto sleep
2. ctrl + z配合 bg
#ctrl + z 让进程去后台挂起 (暂停)
[root@manager ~]# sleep 666
^Z
[2]+ 已停止 sleep 666
#bg 让后台挂起的 继续运行 background
[root@manager ~]# bg
[2]+ sleep 666 &
[1] 完成 sleep 99
#查看后台运行
jobs
#应用场景:杀掉 顽固进程
##执行顽固进程
##ctrl + z
##kill %1 #数字
3. screen
#screen基础用法
screen
xshell断开
xshell重新连接
[root@manager ~]# screen -ls
There is a screen on:
7977.pts-0.manager (Detached)
1 Socket in /var/run/screen/S-root.
[root@manager ~]#
[root@manager ~]#
[root@manager ~]#
[root@manager ~]#
#查看所有screen窗口
[root@manager ~]# screen -ls
There is a screen on:
7977.pts-0.manager (Detached)
1 Socket in /var/run/screen/S-root.
#重新连接到指定窗口
[root@manager ~]# screen -r 7977
快捷键:
ctrl + a d 退出screen窗口 窗口会继续会继续运行
ctrl + a k 结束当前screen窗口
检查 自己是否在 screen中 ctrl +a v #version
判断
if 判断3种格式
1.单分支判断
# 单分支判断
应用在脚本开头 做检查,检查失败退出脚本 参数个数 脚本 命令是否有权限
if [ 条件 ];then
命令
fi
2. 双分支判断
#双分支判断
检查 服务 进程
if [ 条件 ]
then
命令
else
命令
fi
Example
检查 crond服务是否运行中 如果运行提示 crond is running 否则 提示 crond is failed
#后面检查服务的脚本 检查哪个服务脚本名字不要以服务命名
[root@yida scripts]# cat check_cr.sh
#!/bin/bash
#检查 crond服务是否运行中 如果运行提示 crond is running 否则 提示 crond is failed
. /etc/init.d/functions
Name=$(ps -ef |grep crond |grep -vc grep)
if [ $Name -ge 1 ];then
action "crond is running" /bin/true
else
action "crond is failed" /bin/false
fi
3. 多分支判断
[root@manager ~]# vim /server/scripts/2.8-1-comp-readmulti-if.sh
#!/bin/bash
#author: oldboy
read -p "input num1 num2:" num1 num2
#number
#expr $num1 + $num2 + 1 &>/dev/null
#[ $? -ne 0 ] && {
if [[ ! "$num1" =~ ^[0-9]+$ || ! "$num2" =~ ^[0-9]+$
]]
then
echo "Usage: Must have two number"
exit 2
fi
#compare
if [ $num1 -gt $num2 ]
then
echo "$num1 -gt $num2"
elif [ $num1 -lt $num2 ] #else if
then
echo "$num1 -lt $num2"
else
echo "$num1 -eq $num2"
fi
服务检查方式及命令
内容 | 方法 |
---|---|
端口 | 本地检查: netstat -lntup/ss -lntup /lsof -i:80 |
远程检查: telnet ip port /nc ip port /nmap | |
进程 | ps -ef/ ps aux |
客户端模拟监控 | ping -c1 -i1 -W1 ip /curl /wget -q --spider |
数据库 | mysql -e 'show databases;' |
端口检查
#ss 或 netstat
[root@manager ~]# ss -lntup |grep 22
udp UNCONN 0 0 127.0.0.1:323
*:* users:
(("chronyd",pid=5220,fd=1))
udp UNCONN 0 0 ::1:323
:::* users:
(("chronyd",pid=5220,fd=2))
tcp LISTEN 0 128 *:22
*:* users:
(("sshd",pid=7061,fd=3))
[root@manager ~]# ss -lntup |grep -w :22
tcp LISTEN 0 128 *:22
*:* users:
(("sshd",pid=7061,fd=3))
#lsof
[root@manager ~]# lsof -i :22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE
NAME
sshd 7061 root 3u IPv4 39278 0t0 TCP
*:ssh (LISTEN)
sshd 7322 root 3u IPv4 40265 0t0 TCP
manager:ssh->10.0.0.100:49510 (ESTABLISHED)
sshd 7392 root 3u IPv4 43630 0t0 TCP
manager:ssh->10.0.0.100:50037 (ESTABLISHED)
#nc telnet
[root@manager ~]# telnet 10.0.0.61 22
Trying 10.0.0.61...
Connected to 10.0.0.61.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.4
Protocol mismatch.
Connection closed by foreign host.
[root@manager ~]# nc 10.0.0.61 22
SSH-2.0-OpenSSH_7.4
Protocol mismatch.
#nmap
nmap -p22 ip/url
namp -p1-1024 ip/url #端口范围 1-65535
nmap -p22,80 ip/url
[root@manager ~]# nmap -p80 baidu.com
Starting Nmap 6.40 ( http://nmap.org ) at 2020-01-14
09:29 CST
Nmap scan report for baidu.com (220.181.38.148)
Host is up (0.0088s latency).
Other addresses for baidu.com (not scanned):
39.156.69.79
PORT STATE SERVICE
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 0.21
seconds
模拟用户访问网站
[root@manager ~]# wget --spider www.oldbing.com
开启 Spider 模式。检查是否存在远程文件。
--2020-01-14 09:38:43-- http://www.oldbing.com/
正在解析主机 www.oldbing.com (www.oldbing.com)... 失败:
未知的名称或服务。
wget: 无法解析主机地址 “www.oldbing.com”
[root@manager ~]# echo $?
4
[root@manager ~]# wget -q(定向为空) --spider www.oldbing.com
[root@manager ~]# echo $?
4
面试题
1. 通过脚本传参的方式,检查Web网站URL是否正常
[root@m01 /scripts]# cat check_url.sh
#!/bin/bash
url=$1
if ping -c1 $url &>/dev/null;then
echo "$url is ok"
else
echo "$url is failed"
fi
2. 通过脚本传参的方式,检查Web网站URL是否正常
[root@m01 /scripts]# cat check_url2.sh
#!/bin/bash
url=$1
if [[ ! "$url" =~ ^[a-zA-Z.]*[a-zA-Z0-9]+\.(com|org|cn)$ ]]
then
echo "$url is not ok"
exit 1
fi
#wget url
wget -T 1 -q --spider $url
if [ $? -eq 0 ]
then
echo $url is ok
else
echo $url is failed
fi
3. 检查系统可用内存
企业案例:监控系统可用内存,小于100M就发送报警邮件 否则,提示内存充足,定时任务每3分钟1次
[root@manager ~]# cat /server/scripts/2.10.2-
chk_mem.sh
#!/bin/bash
#author:oldboy
mem=`free -m |awk 'NR==2{print $NF}'`
if [ $mem -lt 10000 ]
then
mail -s "mem is bugoule" 918391635@qq.com </etc/hosts
fi
[root@manager ~]# sh /server/scripts/2.10.2-chk_mem.sh
[root@manager ~]# crontab -l
#check mem by liyy at 20200202
*/3 * * * * /bin/sh /server/scripts/2.10.2-chk_mem.sh &>/dev/null
服务管理类脚本
1. 服务管理脚本书写
rsync
目标:书写 服务管理脚本
分步:
基础要求:
sh rsyncd.sh start
sh rsyncd.sh stop
sh rsyncd.sh restart
进阶:
rsync服务开机自启动
#rsync管理命令
### sh rsyncd.sh start === rsync --daemon
#rsyncd sshd crond
### sh rsyncd.sh stop === kill `cat
pidfile`
### sh rsyncd.sh restart === stop start
#准备 rsync的配置文件
#Rsync server
#created by oldboy 15:01 2009-6-5
##rsyncd.conf start##
uid = root
gid = root
use chroot = no
max connections = 2000
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
hosts allow = 10.0.0.0/24
hosts deny = 0.0.0.0/32
auth users = rsync_backup
secrets file = /etc/rsync.password
#####################################
[www]
comment = www by old0boy 14:18 2012-1-13
path = /oldboy
[root@oldboyedu-c6 ~]# rsync --daemon
[root@oldboyedu-c6 ~]# ss -lntup |grep 873
tcp LISTEN 0 5 :::873
:::* users:(("rsync",2364,5))
tcp LISTEN 0 5 *:873
*:* users:(("rsync",2364,3))
[root@oldboyedu-c6 ~]#
[root@oldboyedu-c6 ~]# kill `cat /var/run/rsyncd.pid`
[root@oldboyedu-c6 ~]# ss -lntup |grep 873
#服务管理脚本 基本形式
[root@oldboyedu-c6 /server/scripts]# vim rsyncd.sh
#!/bin/bash
choice=$1
if [ "$choice" = "start" ]
then
rsync --daemon
fi
if [ "$choice" = "stop" ]
then
kill `cat /var/run/rsyncd.pid`
fi
if [ "$choice" = "restart" ]
then
kill `cat /var/run/rsyncd.pid`
sleep 1
rsync --daemon
fi
"rsyncd.sh" [New] 20L, 254C written
[root@oldboyedu-c6 /server/scripts]#
[root@oldboyedu-c6 /server/scripts]# sh rsyncd.sh
[root@oldboyedu-c6 /server/scripts]# pkill rsyncd
[root@oldboyedu-c6 /server/scripts]# pkill rsync
[root@oldboyedu-c6 /server/scripts]# ss -lntup |grep
873
[root@oldboyedu-c6 /server/scripts]# sh rsyncd.sh
start
[root@oldboyedu-c6 /server/scripts]# ss -lntup |grep
873
tcp LISTEN 0 5 :::873
:::* users:(("rsync",3947,5))
tcp LISTEN 0 5 *:873
*:* users:(("rsync",3947,3))
让脚本(服务能开机自启动)或通过service管理
方法1 /etc/rc.local (centos 7 ) 需要加上 执行权限
方法2 通过chkconfig(c6) 管理 或 systemctl管理(c7)
chkconfig管理脚本要求
脚本必须放在 /etc/init.d/ 并且 有执行权限
脚本开头 必须要有chkconfig要求的格式
#chkconfig: 2345(运行级别) 99 98 99开机顺序 98关机顺序
添加到chkconfig管理 : chkconfig --add rsyncd.sh
CentOS 6.x 方法
#chkconfig 管理开机自启动
[root@oldboyedu-c6 /server/scripts]# chkconfig |grep ipt
iptables 0:off 1:off 2:on 3:on 4:on
5:on 6:off
[root@oldboyedu-c6 /server/scripts]# chkconfig
iptables off
[root@oldboyedu-c6 /server/scripts]#
[root@oldboyedu-c6 /server/scripts]# chkconfig |grep ipt
iptables 0:off 1:off 2:off 3:off 4:off
5:off 6:off
#chkconfig管理 服务脚本 实现开机自启动
###1. 脚本必须放在 /etc/init.d/ 并且 有执行权限
[root@oldboyedu-c6 /server/scripts]# mv rsyncd.sh
/etc/init.d/
[root@oldboyedu-c6 /server/scripts]# chmod +x
/etc/init.d/rsyncd.sh
[root@oldboyedu-c6 /server/scripts]# ll
/etc/init.d/rsyncd.sh
-rwxr-xr-x. 1 root root 342 Jan 14 15:28
/etc/init.d/rsyncd.sh
###2. 脚本开头 必须要有chkconfig要求的格式
[root@oldboyedu-c6 /server/scripts]# head -2
/etc/init.d/rsyncd.sh
#!/bin/bash
# chkconfig: 2345 99 98
###3. 添加到chkconfig管理 : `chkconfig --add rsyncd.sh
[root@oldboyedu-c6 /server/scripts]# chkconfig --add
rsyncd.sh
[root@oldboyedu-c6 /server/scripts]# chkconfig |grep
rsync
rsyncd.sh 0:off 1:off 2:on 3:on 4:on
5:on 6:off
CentOS 7.x 8.x systemctl 管理方法
#环境准备
[root@manager ~]# cat /etc/rsyncd.conf
#Rsync server
#created by oldboy 15:01 2009-6-5
##rsyncd.conf start##
uid = root
gid = root
use chroot = no
max connections = 2000
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
hosts allow = 10.0.0.0/24
hosts deny = 0.0.0.0/32
auth users = rsync_backup
secrets file = /etc/rsync.password
#####################################
[www]
comment = www by old0boy 14:18 2012-1-13
path = /oldboy
[root@manager ~]# systemctl disable rsyncd
[root@manager ~]# systemctl stop rsyncd
#准备管理脚本
[root@manager ~]# scp
10.0.0.202:/etc/init.d/rsyncd.sh /etc/init.d/
root@10.0.0.202's password:
rsyncd.sh
100% 384 321.1KB/s 00:00
[root@manager ~]# ss -lntup |grep 873
[root@manager ~]# uname -r
3.10.0-957.el7.x86_64
[root@manager ~]# /etc/init.d/rsyncd.sh start
[root@manager ~]# ss -lntup |grep 873
tcp LISTEN 0 5 *:873
*:* users:
(("rsync",pid=11087,fd=3))
tcp LISTEN 0 5 :::873
:::* users:
(("rsync",pid=11087,fd=5))
[root@manager ~]# /etc/init.d/rsyncd.sh stop
[root@manager ~]# ss -lntup |grep 873
[root@manager ~]# /etc/init.d/rsyncd.sh restart
[root@manager ~]#
[root@manager ~]#
[root@manager ~]# ss -lntup |grep 873
tcp LISTEN 0 5 *:873
*:* users:
(("rsync",pid=11097,fd=3))
tcp LISTEN 0 5 :::873
:::* users:
(("rsync",pid=11097,fd=5)
#书写systemctl配置
systemctl cat rsyncd
systemctl cat nginx
[root@manager ~]# systemctl cat nginx.service
# /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nsslookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
#Nginx will fail to start if /run/nginx.pid already
exists but has the wrong
#SELinux context. This might happen when running
`nginx -t` from the cmdline.
#https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID #nginx -s
reload
ExecStop=
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
systemctl 配置文件说明 | |
---|---|
[Unit] | 1. 说明信息 2. 依赖关系 After 在后面服务之后运行 |
[Service] | 1. 说明 start stop restart 对应的命令或脚本ExecStart ExecStop ExecReload 2. 类型 Type=forking 服务模式 |
[Install] | 运行级别(target) |
[root@manager ~]# cat
/usr/lib/systemd/system/rsyncd-new.service
[Unit]
After=network.target remote-fs.target
[Service]
Type=forking
ExecStart=/etc/init.d/rsyncd.sh start
ExecStop=/etc/init.d/rsyncd.sh stop
ExecReload=/etc/init.d/rsyncd.sh restart
[Install]
WantedBy=multi-user.target
[root@manager ~]# pkill rsync
[root@manager ~]# pkill rsync
[root@manager ~]# systemctl start rsyncd-new.service
[root@manager ~]# systemctl status rsyncd-new.service
● rsyncd-new.service
Loaded: loaded (/usr/lib/systemd/system/rsyncdnew.service; disabled; vendor preset: disabled)
Active: active (running) since 二 2020-01-14
16:10:58 CST; 9s ago
Process: 11339 ExecStart=/etc/init.d/rsyncd.sh start
(code=exited, status=0/SUCCESS)
Main PID: 11341 (rsync)
CGroup: /system.slice/rsyncd-new.service
└─11341 rsync --daemon
1月 14 16:10:58 manager systemd[1]: Starting rsyncdnew.service...
1月 14 16:10:58 manager systemd[1]: Started rsyncdnew.service.
[root@manager ~]#
[root@manager ~]# systemctl enable rsyncd-new.service
Created symlink from /etc/systemd/system/multiuser.target.wants/rsyncd-new.service to
/usr/lib/systemd/system/rsyncd-new.service.
[root@manager ~]#
[root@manager ~]#
[root@manager ~]# systemctl status rsyncd-new.service
● rsyncd-new.service
Loaded: loaded (/usr/lib/systemd/system/rsyncdnew.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2020-01-14
16:10:58 CST; 37s ago
Main PID: 11341 (rsync)
CGroup: /system.slice/rsyncd-new.service
└─11341 rsync --daemon
1月 14 16:10:58 manager systemd[1]: Starting rsyncdnew.service...
1月 14 16:10:58 manager systemd[1]: Started rsyncdnew.service.
小结
Linux各种服务软件 管理脚本
1. 找出 服务 start |stop|restart 对应的命令
2. 书写脚本 if
3. 服务开机自启动systemctl/chkconfig
case语句
分支结构 条件选择语句
应用场景: 服务管理脚本(start|stop|restart) 菜单功能
#格式
case "选择" in
条件1)
命令
;;
条件2)
命令
;;
*)
默认的内容
esac
#案例
[root@manager ~]# vim /server/scripts/2.12-1-case.sh
#!/bin/bash
#author: oldboy
choice=$1
case "$choice" in
start)
echo start
;;
stop)
echo stop
;;
restart)
echo restart
;;
*)
echo "Usages: $0 {start|stop|restart}"
exit 1
esac
sh与source(.)
含义 | 区别 | 应用 | |
---|---|---|---|
sh(bash) | 都可以运行脚本 | 运行的时候会创建1个子shell | 通用执行脚本方法 |
source(.) | 都可以运行脚本 | 是在当前shell环境运行 | 加载 /etc/init.d/functions 系统的函数库 source/etc/init.d/functions |
[root@manager /server/scripts]# cat 2.13-1-shsource.sh
#!/bin/bash
#author:oldboy
echo $OLDBOY
[root@manager /server/scripts]# OLDBOY=666
[root@manager /server/scripts]# sh 2.13-1-sh-source.sh
[root@manager /server/scripts]# . 2.13-1-sh-source.sh
666
函数
别名 :给命令或脚本设置别名 alias rm='echo oldboy’
函数:给一段代码设置1个名称 ,代码:函数体 名称:函数名字 (专业 规范)
函数的基础格式
#格式
##格式1
function 函数名() {
函数体(命令)
函数体(命令)
return
}
##格式2
function 函数名 {
函数体(命令)
函数体(命令)
return
}
##格式3 ※※※※※
函数名() {
函数体(命令)
函数体(命令)
return
}
函数传参
名称 | shell脚本 | 函数 |
---|---|---|
$1 $2 $数字 | 脚本的第1个 第2个 参数 | 函数的第1个 第2个 参数 |
$0 | 脚本名字 | 脚本名字 |
$# | 脚本参数个数 | 函数参数的个数 |
$* | 取出脚本所有的参数 | 取出函数所有的参数 |
$@ | 取出脚本所有的参数 | 取出函数所有的参数 |
[root@manager /server/scripts]# cat 2.14.2-rsyncd.sh
#!/bin/bash
# chkconfig: 2345 99 98
# author:oldboy
choice=$1
pidfile=/var/run/rsyncd.pid
start() {
[ -f $pidfile ] || rsync --daemon
}
stop() {
[ -f $pidfile ] && kill `cat
/var/run/rsyncd.pid`
}
restart() {
[ -f $pidfile ] && kill `cat
/var/run/rsyncd.pid`
sleep 1
rsync --daemon
}
case "$choice" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo "Usage $0 {start|stop|restart}"
exit 1
esac
循环语句
while当型循环 基础
for | 通用 |
---|---|
while 当型循环 | 死循环,读取文件的内容 |
#while 循环
while 条件
do
命令
done
[root@manager /server/scripts]# cat 2.15.1-
while.sh
#!/bin/bash
#author:oldboy
while true #死循环 true 条件永久成立
do
date
sleep 2
done
#eg: 使用while循环 输出1 2 3 … 10 类似 seq 10
[root@manager /server/scripts]# vim 2.15.2-seqwhile.sh
#!/bin/bash
#author:oldboy
i=0
while [ $i -lt 10 ]
do
((i++))
echo $i
done
#面试题: 计算1+2+3+4+5…+10 求总和
###方法1: while
[root@manager /server/scripts]# cat 2.15.3-sumwhile.sh
#!/bin/bash
#author:oldboy
i=1
sum=0
while [ $i -le 10 ]
do
((sum=sum+i))
((i++))
done
echo $sum
###方法2:
[root@manager /server/scripts]# echo $((`seq -s+ 10` ))
55
[root@manager /server/scripts]# seq -s+ 10
1+2+3+4+5+6+7+8+9+10
[root@manager /server/scripts]# seq -s+ 10 |bc
55
#脚本修改为函数 并且使用while 死循环
[root@manager /server/scripts]# cat 2.8-1-comp-readmulti-if.sh
#!/bin/bash
#author: oldboy
read -p "input num1 num2:" num1 num2
if [[ ! "$num1" =~ ^[0-9]+$ || ! "$num2" =~ ^[0-9]+$
]]
then
echo "Usage: Must have two number"
exit 2
fi
#compare
if [ $num1 -gt $num2 ]
then
echo "$num1 -gt $num2"
elif [ $num1 -lt $num2 ] #else if
then
echo "$num1 -lt $num2"
else
echo "$num1 -eq $num2"
fi
[root@manager /server/scripts]# cat 2.15.3-comp-readmulti-if.sh
#!/bin/bash
#author: oldboy
input() {
read -p "input num1 num2:" num1 num2
}
#number
#expr $num1 + $num2 + 1 &>/dev/null
#[ $? -ne 0 ] && {
check() {
if [[ ! "$num1" =~ ^[0-9]+$ || ! "$num2" =~ ^[0-9]+$
]]
then
echo "Usage: Must have two number"
continue
fi
}
#compare
compare() {
if [ $num1 -gt $num2 ]
then
echo "$num1 -gt $num2"
elif [ $num1 -lt $num2 ] #else if
then
echo "$num1 -lt $num2"
else
echo "$num1 -eq $num2"
fi
}
main() {
while true
do
input
check
compare
done
}
main
while 当型循环 读取文件
通过while read读取文件内容 ip 把ip通过iptables 封掉
#方式1:采用exec读取文件后,然后进入while循环处理
exec<FILE
while read line
do
cmd
done
#方式2:使用cat读取文件内容,然后通过管道进入while循环处理
cat FILE|while read line
do
cmd
done
#※※※※※※方式3:在while循环结尾done通过输入重定向指定读取的文件
while read line
do
cmd
done<FILE
#eg: while read line
[root@m01 /server/scripts]# cat stu.txt
01 oldbing 18
02 oldxia 19
03 oldlidao 19
04 oldguo 66
##通过while循环 求和 stu.txt第3列的内容
[root@manager /server/scripts]# cat 2.15.5-whileread-sum.sh
#!/bin/bash
#author:oldboy
file=/server/scripts/stu.txt
sum=0
while read line
do
num=`echo $line|awk '{print $3}'`
((sum+=num)) #sum=sum+num
done <$file
echo $sum
###企业案例:写一个Shell脚本解决类DDOS攻击的生产案例。请根据web日志或者或者系统网络连接数,监控当某个IP并发连接数,若短时内并发连接数达到100(阈值),即调用防火墙命令封掉对应的IP。防火墙命令为:iptables -I INPUT -s IP地址 -j DROP。
分析:
1.通过awk分析日志、连接数 每个ip的次数 结果存放在文件中
2.通过while read line 读取文件
判断次数如果大于100 并且 iptables -nL中没有这个ip 则封掉
DOS Denial of Service 拒绝式服务攻击
DDOS 分布式
系统网络连接数:ss -ant /netstat -ant
分析netstat.log找出每个ip的连接数量(出现次数)
如果次数大于100则通过iptables封掉
[root@m01 /scripts]# cat check_while.sh
#!/bin/bash
file=/root/netstat.log
tmp_file=/scripts/tmp.txt
awk -F'[ :]+' '/ESTABLISHED/ {print $6}' $file |sort |uniq -c |sort -n > $tmp_file
while read line;do
count=`echo $line |awk '{print $1}'`
ip=`echo $line |awk '{print $2}'`
if [ "$count" -gt 2 -a `iptables -nL |grep -wc $ip` -eq 0 ];then
iptables -I INPUT -s $ip -j DROP
fi
done <$tmp_file
[root@manager ~]# while read x y z
> do
> echo "x:"$x "y:"$y "z:$z"
> done </server/scripts/stu.txt
x:01 y:oldbing z:18
x:02 y:oldxia z:19
x:03 y:oldlidao z:19
x:04 y:oldguo z:66
[root@manager ~]# while read x y ; do echo "x:$x
y:$y"; done </server/scripts/stu.txt
x:01 y:oldbing 18
x:02 y:oldxia 19
x:03 y:oldlidao 19
x:04 y:oldguo 66
while小结
1. 死循环 while true ; do ;done while : ; do
;done
2. while读取文件的内容
直到型循环 until
until 话费是否充足
do
发短信
done
for型循环
通用
for n in 列表(名单)
do
命令
done
数字循环(C语言循环)
for((i=1;i<=10;i++))
do
命令
done
#生成随机字符 数字方法
##方法1 RANDOM
[root@manager ~]# echo $RANDOM
14966
[root@manager ~]#
[root@manager ~]#
[root@manager ~]# echo $((RANDOM + 100000))
125107
##方法2 date + md5sum
[root@manager ~]# date +%N |md5sum| cut -c 1-8
7d178a23
##方法3 tr + /dev/urandom
###/dev/urandom 字符文件、字符设备 不断输出字符
[root@manager ~]# tr -cd 'a-zA-Z0-9' </dev/urandom
|head -c8
for n in 1 2 3 4 {1..10} `seq 10` {1..10..2}
`seq 1 2 10`
do
echo $n
done
#批量创建文件
企业面试题2:
使用for循环在/oldboy目录下通过随机小写10个字母加固定字符串oldboy批量创建10个html文件
#!/bin/bash
[ -d /oldboy ] || mkdir /oldboy
for i in {1..10};do
name=`uuidgen |sed "s#[0-9-]##g" |head -c10`
touch /oldboy/${name}_oldboy.html
done
#!/bin/bash
#author:oldboy
dir=/oldboy
[ -d "$dir" ] || mkdir -p $dir
for n in {1..10}
do
name=`tr -cd 'a-zA-Z' </dev/urandom |head -c10`
touch $dir/${name}_oldboy.html
done
#批量重命名 把上面创建的文件名中 oldboy替换为 oldgirl
#!/bin/bash
cd /oldboy
for n in `ls *`;do
rename html txt *
done
#!/bin/bash
cd /oldboy
for n in `ls *`;do
mv $n ${n/oldgirl/oldboy}
done
#批量添加用户
企业面试题4:
##批量创建10个系统帐号oldboy01-oldboy10并设置密码(密码为随机8位字符串)
#!/bin/bash
for user in oldboy{01..10};do
useradd $user
num=`uuidgen |head -c 8`
echo $num |passwd --stdin $user
echo $user $num >> /scripts/tmp_user.txt
done
#!/bin/bash
for n in oldboy{01..10}
do
useradd $n
pass=`tr -cd 'a-zA-Z' </dev/urandom |head -c8`
echo "$pass" |passwd --stdin $n
echo $n $pass >>/root/pass.txt
done
流程控制语句
流程控制语句 | 含义 | 应用场景 |
---|---|---|
return | 函数中 在函数执行完成后 给函数返回值 | 函数中 在函数执行完成后 给函数返回值 |
exit | 直接退出脚本 返回值 | 书写在 脚本报错的时候 提示信息然后退出脚本 |
continue n | 控制循环 结束本次循环 进行下次循环 | 循环中跳过 |
break n | 跳过所有循环 |
checkpid() {
local i #设置局部变量i
for i in $* ; do #函数所有参数 循环
[ -d "/proc/$i" ] && return 0
done
return 1
}
函数checkpid
checkpid
如果这个pid存在 return 0
#continue 基本含义
[root@m01 ~]# for n in {1..5}; do [ $n -eq 3 ] &&continue ; echo $n ;done
1
2
4
5
for pid in $pids ; do
[ ! -e "/proc/$pid" ] && continue #如果pid目录不存在 则跳过本次循环 读取下1个pid目录
#break 基本含义
[root@manager ~]# for n in {1..10}; do [ $n -eq 5 ]&&break ; echo $n ;done
1
2
3
4
#continue break 扩展
#continue 2 结束当前循环跳到第2层循环 从第2层循环开始
for n in {A..E}
do
for m in {a..e}
do
for i in {1..5}
do
echo $n $m $i
done
done
done
for n in {A..E}
do
for m in {a..e}
do
for i in {1..5}
do
[ $i -eq 3 ] &&continue
echo $n $m $i
done
done
done
for n in {A..E}
do
for m in {a..e}
do
for i in {1..5}
do
[ $i -eq 3 ] &&continue 2
echo $n $m $i
done
done
done
#break 2
for n in {A..E}
do
for m in {a..e}
do
for i in {1..5}
do
[ $i -eq 4 ] &&break 2
echo $n $m $i
done
done
done
eg:乘法口诀表
精确
for i in {1..9}
do
for((j=1;j<=i;j++))
do
echo "$j*$i=$((i*j))"
done
done
精确加上格式
for i in {1..9}
do
for((j=1;j<=i;j++))
do
echo -n "$j*$i=$((i*j)) "
done
echo
done |column -t
Linux加上颜色与vimrc
颜色
Linux命令行给字体加颜色命令
[root@oldboy scripts]# echo -e "\E[1;31m红色字
oldboy\E[0m"
红色字oldboy
[root@oldboy scripts]# echo -e "\033[31m红色字oldboy
\033[0m"
在上述命令中:
echo -e可以识别转义字符,这里将识别特殊字符的含义,并输出。
\n \t
Linux下面回车是 \n
Windows下面回车是 \r\n
#巨坑: windows下面书写脚本或SQL语句 放入到linux执行 失败
#解决: dos2unix
\E也可以使用\033替代
[1数字1表示加粗显示(这个位置可以加不同的数字代表不同的意思,详细信息可man console_codes得)
31m表示为红色字体,这个位置可以换不同的数字,以代表不同的意思
“红色字oldboy”表示待设置的内容
[0m表示关闭所有属性,这个位置可以换不同的数字,以代表不同的意思
echo -e "\E[5;31m红色字oldboy\E[0m"
echo -e "\E[5;32m绿色字oldboy\E[0m"
echo -e "\E[5;33m棕色字oldboy\E[0m"
echo -e "\E[5;34m颜色字oldboy\E[0m"
echo -e "\E[5;35m紫色/红色oldboy\E[0m"
[root@manager ~]# echo -e "\E[1;31m红色字oldboy\E[0m"
红色字oldboy
[root@manager ~]# echo -e "\E[1;31;42m红色字绿色背景
oldboy\E[0m"
红色字绿色背景oldboy
[root@manager ~]# echo -e "\E[5;31;42m红色字绿色背景 闪烁
oldboy\E[0m"
红色字绿色背景 闪烁oldboy
案例
sh color.sh 执行脚本后 给 内容加上对应的颜色
1.input red 内容
2.input green 内容
3.input blue 内容
例子:选择1 oldboy
则oldboy显示为红色
[root@manager ~]# cat /server/scripts/2.18.1-color.sh
#!/bin/bash
#author:oldboy
RED="\E[1;31m"
GREEN="\E[1;32m"
BLUE="\E[1;34m"
END="\E[0m"
input() {
cat <<EOF
1.input red 内容
2.input green 内容
3.input blue 内容
EOF
read -p "input choice:" cho
read -p "内容:" text
}
choice() {
case "$cho" in
1)
echo -e "${RED} $text ${END}"
;;
2)
echo -e "${GREEN} $text ${END}"
;;
3)
echo -e "${BLUE} $text ${END}"
;;
*)
echo "Usage: input {1|2|3}"
exit 1
esac
}
main() {
input
choice
}
main
[root@m01 /scripts]# cat test.sh
#!/bin/bash
red="\e[1;31m"
green="\e[1;32m"
blue="\e[1;34m"
end="\e[0m"
while true;do
echo "1.input red 内容"
echo "2.input green 内容"
echo "3.input blue 内容"
read -p "please input number:" choice
if [ $choice -le 3 ];then
read -p "内容:" text
fi
case $choice in
1)
echo -e "${red}${text}${end}"
exit 1
;;
2)
echo -e "${green}${text}${end}"
exit 1
;;
3)
echo -e "${blue}${text}${end}"
exit 1
;;
*)
if [ $choice -gt 3 ];then
echo "请输入正确编号"
fi
esac
done
vimrc
通过vim编辑文件的配置文件
创建新文件 .sh 文件 自动加上版权说明
vim格式
##简易版本
#创建新文件 .sh 文件 自动加上版权说明
##/etc/vimrc 全局
##~/.vimrc 当前用户生效 √√√√√
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call
SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,
"#####################################################
#########")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: oldboy")
call setline(6, "# Organization:
www.oldboyedu.com")
call setline(7, "# Created Time :
".strftime("%F %T"))
call setline(8, "# Description:")
call setline(9,
"#####################################################
#########")
call setline(10, "")
endif
endfunc
##完整的配置
###vim 给光标所在行 加上提示 下划线
###tab键 修改为 4个空个长度
###自动 缩进 自动对齐
set nocompatible
set history=100
filetype on
filetype plugin on
filetype indent on
set autoread
set mouse=c
syntax enable
set cursorline
hi cursorline guibg=#00ff00
hi CursorColumn guibg=#00ff00
set foldenable
set foldmethod=manual
set foldcolumn=0
setlocal foldlevel=3
set foldclose=all
nnoremap <space> @=((foldclosed(line('.')) < 0) ? 'zc'
: 'zo')<CR>
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set smarttab
set ai
set si
set wrap
set sw=4
set wildmenu
set ruler
set cmdheight=1
set lz
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set magic
set noerrorbells
set novisualbell
set showmatch
set mat=4
set hlsearch
set ignorecase
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
set smartindent
set cin
set showmatch
set guioptions-=T
set guioptions-=m
set vb t_vb=
set laststatus=4
set pastetoggle=<F9>
set background=dark
highlight Search ctermbg=black ctermfg=white
guifg=white guibg=black
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call
SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1,"#!/bin/bash")
call setline(2,
"#####################################################
#########")
call setline(3, "# File Name: ".expand("%"))
call setline(4, "# Version: V1.0")
call setline(5, "# Author: oldboy")
call setline(6, "# Organization:
www.oldboyedu.com")
call setline(7, "# Created Time :
".strftime("%F %T"))
call setline(8, "# Description:")
call setline(9,
"#####################################################
#########")
call setline(10, "")
endif
endfunc
shell数组
ip1=10.0.0.7
ip2=10.0.0.8
ip3=192.168.1.20
echo $ip1 $ip2 $ip3
#存放或使用 没有太多规律的信息
#使用shell数组
#array[1]
#数组名称[下标] #数组名称[元素名称]
[root@manager ~]#
[root@manager ~]# array[1]=10.0.0.7
[root@manager ~]# array[2]=10.0.0.61
[root@manager ~]#
[root@manager ~]# echo ${array[1]}
10.0.0.7
[root@manager ~]# echo ${array[*]}
10.0.0.7 10.0.0.61
数组的赋值方式
#手动批量创建 数组
[root@manager ~]# lidao=(oldboy alex oldbing)
[root@manager ~]# echo ${lidao[1]}
alex
[root@manager ~]# echo ${lidao[0]}
oldboy
[root@manager ~]# echo ${lidao[1]}
alex
[root@manager ~]#
[root@manager ~]# echo ${lidao[*]}
oldboy alex oldbing
#通过文件创建 数组
[root@manager ~]# name=(`awk -F: '{print $1}'
/etc/passwd`)
[root@manager ~]# echo ${name[0]}
root
[root@manager ~]# echo ${name[*]}
root bin daemon adm lp sync shutdown halt mail
operator games ftp nobody systemd-network dbus polkitd
tss abrt sshd postfix chrony ntp oldboy nginx tcpdump
mysql oldboy01 oldboy02 oldboy03 oldboy04 oldboy05
oldboy06 oldboy07 oldboy08 oldboy09 oldboy10
[root@manager ~]# echo ${#name[*]}
36
eg:
环境
cat >/server/scripts/ip_list.txt<<EOF
10.0.0.61
10.0.0.71
10.0.0.81
10.0.0.202
EOF
#检查文件中 指定的ip是否存在(ping通)
#方法1
cat /server/scripts/2.19.1-chk-ip.sh
#!/bin/bash
ip_list=( `cat /server/scripts/ip_list.txt` )
check_ip() {
ping -c1 -i1 -W1 $ip &>/dev/null
if [ $? -eq 0 ];then
echo "$ip is ok"
else
echo "$ip is failed"
fi
}
main() {
for ip in ${ip_list[*]}
do
check_ip
done
}
main
#方法2
[root@manager ~]# ip_list=(`cat/server/scripts/ip_list.txt`)
[root@manager ~]# echo ${ip_list[*]}
10.0.0.61 10.0.0.71 10.0.0.81 10.0.0.202
[root@manager ~]# for((i=0;i<${#ip_list[*]};i++));do
echo ${ip_list[i]} ;done
10.0.0.61
10.0.0.71
10.0.0.81
10.0.0.202
[root@manager ~]# for ip in ${ip_list[*]}; do echo
$ip ;done
10.0.0.61
10.0.0.71
10.0.0.81
10.0.0.202
shell总结
# Log that something succeeded
success() {
[ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] &&
echo_success
return 0
}
action() {
local STRING rc #创建变量
STRING=$1 #函数第1个参数赋值给 STRING="ip is ok"
echo -n "$STRING " #显示 变量内容 不换行
shift #移动脚本或函数的参数 #执行后
$1是 /bin/true
"$@" && success $"$STRING" || failure $"$STRING"
#/bin/true && success || failure `
#success 显示 [OK] [确定]
rc=$? #命令执行结果
echo
return $rc
}
action "ip is ok" /bin/true
#屏幕输出
ip is ok [OK]
#补充
[root@manager ~]# set oldboy alex
[root@manager ~]# echo $1 $2
oldboy alex
[root@manager ~]# shift
[root@manager ~]# echo $1
alex
[root@manager ~]# echo $2
[root@manager ~]#
三剑客
sed
sed执行流程
sed N
[root@manager ~]# sed 'N;s#\n# #g' num.txt
1 2
3 4
5 6
7 8
9 10
[root@manager ~]# sed 'N;N;N;N;N;N;N;N;s#\n# #g'
num.txt
1 2 3 4 5 6 7 8 9
10
[root@manager ~]# sed 'N;N;N;N;N;N;N;N;N;s#\n# #g'
num.txt
1 2 3 4 5 6 7 8 9 10
#使用sed命令的中循环
#sed标签功能
[root@manager ~]# sed ':label ;N;s#\n# #g;t label'
num.txt
1 2 3 4 5 6 7 8 9 10
[root@manager ~]# tr '\n' ' ' <num.txt
1 2 3 4 5 6 7 8 9 10 [root@manager ~]#
[root@manager ~]# xargs <num.txt
1 2 3 4 5 6 7 8 9 10
[root@manager ~]# awk -vORS=" " '1' num.txt
1 2 3 4 5 6 7 8 9 10 [root@manager ~]#
sed功能
sed:功能:
增删改查
p(查) print
-n ‘3p’
-n ‘1,3p’
-n ‘/oldboy/p’
过滤日志: 时间范围 -n ‘/开始/,/结束/p’ access.log
d(删除) delete
cai (cia) c( replace 替换这一行的内容) a(append) i(insert)
s(替换) sub substitute
补充符号:
&
[root@manager ~]# seq 5 |sed '3c oldboyedu.com '
1
2
oldboyedu.com
4
5
[root@manager ~]# seq 5 |sed '3a oldboyedu.com '
1
2
3
oldboyedu.com
4
5
[root@manager ~]# seq 5 |sed '3i oldboyedu.com '
1
2
oldboyedu.com
3
4
5
#&
[root@manager ~]# echo {1..20} |sed -r 's#[0-9]+#
<&>#g'
<1> <2> <3> <4> <5> <6> <7> <8> <9> <10> <11> <12>
<13> <14> <15> <16> <17> <18> <19> <20>
[root@manager ~]# echo {1..20} |sed -r 's#[0-9]+#
<&>#g'
正则表达式
正则vs通配符
正则
man perlretut
#取出 id:右边的数字
echo 'id:1 id:999 id:12306 id:996 oldboy666
alex777 12580' >id.txt
[root@manager ~]# #取 xxxx右边/左边 的内容
[root@manager ~]# #取出的位置
[root@manager ~]# ##perl正则 零宽断言 lookaround
[root@manager ~]# ###lookahead 匹配左边
[root@manager ~]# ###lookbehind 批量右边
[root@manager ~]# echo 'by oldboy linux' |grep -P '(?
<=old)boy'
by oldboy linux
[root@manager ~]# echo 'by oldboy linux' |grep -Po
'(?<=old)boy'
boy
[root@manager ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:d9:30:f5 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.61/24 brd 10.0.0.255 scope global
noprefixroute eth0
valid_lft forever preferred_lft forever
inet6 fe80::a6c9:6aee:108b:2757/64 scope link
noprefixroute
valid_lft forever preferred_lft forever
[root@manager ~]# ip a s eth0 |grep -Po '[0-9.]+(?=/24)'
10.0.0.61
[root@m01 ~]# ip a s eth0 |grep -Po '(?<=inet )[0-9.]+'
10.0.0.61
awk
内容
awk格式
awk执行过程
行
列
内置变量
awk条件
比较表达式
正则
特殊 BEGIN和END
范围
if fork
awk数组
awk数组分析日志
格式与参数
awk 参数 ‘条件{动作}’ 文件 …
参数 | 含义 |
---|---|
-F | 指定分隔符 |
-v | 创建或修改awk变量 1次只能创建或修改1个变量 |
shell脚本中的变量 传递到awk中
[root@manager ~]# x=1
[root@manager ~]# y=21
[root@manager ~]# awk -vn1=1 -vn2=21 'BEGIN{print
n1/n2}'
0.047619
[root@manager ~]# awk -vn1=$x -vn2=$y 'BEGIN{print
n1/n2}'
0.047619
awk完整的执行过程
awk执行过程
1 读取文件内容之前执行awk命令行参数 -F或 -v执行BEGIN{}模块
2 正在读取文件读取文件的1行判断这一行是否满足条件满足 执行对应的动作不满足 读取下一行 直到文件结尾
3 读取文件后执行END{}里面的内容
行与列
名称 | 含义 |
---|---|
行 | record 记录 行 |
列 | field 字段 域 列 |
行
#取出第1行
[root@m01 ~]# awk 'NR==1' /etc/passwd
root:x:0:0:root:/root:/bin/bash
#取多行 取出 从第5行到最后1行
awk 'NR>=5' /etc/passwd
#取出2-5行的内容
[root@m01 ~]# awk 'NR>=2 && NR<=5' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
#过滤
[root@m01 ~]# awk '/oldboy/' /etc/passwd
oldboy01:x:1000:1000::/home/oldboy01:/bin/bash
oldboy02:x:1001:1001::/home/oldboy02:/bin/bash
oldboy03:x:1002:1002::/home/oldboy03:/bin/bash
oldboy04:x:1003:1003::/home/oldboy04:/bin/bash
oldboy05:x:1004:1004::/home/oldboy05:/bin/bash
oldboy06:x:1005:1005::/home/oldboy06:/bin/bash
oldboy07:x:1006:1006::/home/oldboy07:/bin/bash
oldboy08:x:1007:1007::/home/oldboy08:/bin/bash
oldboy09:x:1008:1008::/home/oldboy09:/bin/bash
oldboy10:x:1009:1009::/home/oldboy10:/bin/bash
#扩展
##awk只写条件 条件满足后 默认执行 {print $0}显示这一行的内容
[root@m01 ~]# awk '/oldboy/{print $0}' /etc/passwd
oldboy01:x:1000:1000::/home/oldboy01:/bin/bash
oldboy02:x:1001:1001::/home/oldboy02:/bin/bash
oldboy03:x:1002:1002::/home/oldboy03:/bin/bash
oldboy04:x:1003:1003::/home/oldboy04:/bin/bash
oldboy05:x:1004:1004::/home/oldboy05:/bin/bash
oldboy06:x:1005:1005::/home/oldboy06:/bin/bash
oldboy07:x:1006:1006::/home/oldboy07:/bin/bash
oldboy08:x:1007:1007::/home/oldboy08:/bin/bash
oldboy09:x:1008:1008::/home/oldboy09:/bin/bash
oldboy10:x:1009:1009::/home/oldboy10:/bin/bash
#RS 每一行结束标记 默认是回车
[root@m01 ~]# awk -vRS='/' '{print NR,$0}' /etc/passwd
[root@m01 ~]# seq 10|awk -vORS=' ' '{print $0}'
1 2 3 4 5 6 7 8 9 10 [root@m01 ~]#
# 创建行分隔符
列
[root@manager ~]# awk -F: '{print $1,$3}' /etc/passwd
#调换 /etc/passwd 第1列和最后一行 内容
[root@m01 ~]# sed -r 's#(^.*)(:x.*:)(.*)#\3\2\1#g' /etc/passwd
[root@m01 ~]# awk -F: -vOFS=: '{print $NF,$2,$3,$4,$5,$6,$1}' /etc/passwd
[root@m01 ~]# awk -F: -vOFS=: '{tmp=$1;$1=$NF;$NF=tmp;print }' /etc/passwd
内置变量
内置变量 | 说明 |
---|---|
NR | Number of Record 记录号 行号 |
RS | Record Separator 记录分隔符 记录着每一行的结束标记支持正则 |
ORS | Output Record Separator awk显示每一行的时候 每一行之间的分隔符 |
$数字 | 去列 |
---|---|
$0 | 表示一整行的内容 |
FS | -F: === -vFS=: Field Separator 字段分隔符 菜刀 |
OFS | Output Field Separator 输出字段分隔符 输出每一列的时候 每一列之间分隔符 默认是空格 OFS内容 相当于是 ,的内容 |
NF | Number of Field 每一行有多少列 |
awk条件
比较表达式
正则
BEGIN{} 和END{}
范围
比较
#取行
[root@manager ~]# awk 'NR>=5' /etc/passwd
#取出/etc/passwd 中第3列 大于0并且小于1000的行
[root@m01 ~]# awk -F: '$3>0 && $3<1000' /etc/passwd
#取出磁盘使用率高于20%的名字
[root@m01 ~]# df -h|awk -F'[ %]+' 'NR>1 && $5>2 {print $1,$5}'
/dev/sda1 3
#小坑预警:
##通过awk进行比较 如果某一列中有符号 awk会认为是字符串的对比 字符串的对比先比较第1位
[root@m01 ~]# df -h|awk -F'[ ]+' 'NR>1 && $5>20 {print $1,$5}'
/dev/sda1 3%
正则
符号 | 含义 |
---|---|
~ | 匹配 $3 ~ /^[01]/ |
!~ | 不匹配 排除 $3 !~ /^[01]/ |
# ^ 行开头 某一列的开头
# $ 行结尾 某一列的结尾
#取出 /etc/passwd中第3列 以数字1或0开头的行
[root@manager ~]# awk -F: '$3 ~ /^[01]/' /etc/passwd
#统计 access.log中 请求是.jpg或 .gif结尾的图 流量总和
##类型 $7
##流量 $10
##条件 : 找出第7列以.jpg或.gif结尾的 $7 ~ /.jpg$|.gif$/
##{动作}: {sum=sum+$10}
[root@m01 ~]# awk '$7~/.jpg$|.gif$/ {sum=sum+$10}END{print sum/1024^2}' access.log
90.7682
[root@m01 ~]# awk ' {sum=sum+$10}END{print sum/1024^2}' access.log
2363.68
BEGIN{} vs END{}
应用场景 | ||
---|---|---|
BEGIN{} | BEGIN里面的内容会在awk读取文件之前 运行 | 1. 用来进行测试 与计算2.BEGIN定义 awk内置变量3.显示某列的时候 提前显示的标题 |
END{} | END里面的内容 会在awk读取完文件后运行 | 1. 先进行计算 最后在END{}输出结果 |
[root@manager ~]# #awk -F: '$3 ~ /^[01]/' /etc/passwd
[root@manager ~]# #awk -vFS=: '$3 ~ /^[01]/' /etc/passwd
[root@manager ~]# #awk 'BEGIN{FS=":"}$3 ~ /^[01]/' /etc/passwd
[root@manager ~]# awk -F: 'BEGIN{print "用户名","UID"}{print $1,$3}' /etc/passwd |column -t
范围
[root@m01 ~]# awk 'NR==1,NR==5' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@manager ~]# awk '/root/,/nobody/' /etc/passwd
[root@m01 ~]# awk -F: '$3==0,$3==5' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
[root@m01 ~]# awk '$1~/root/,$1~/nobody/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
awk条件小结
名称 | 应用场景 |
---|---|
比较表达式 | 通过awk内置变量使用 NR>5 $3>=10 |
正则 | 配置某一列中 包含/不包含xxxx 日志过滤$3~/^[01]/ |
BEGIN{} 和END{} | END{}输出最后的结果;BEGIN{}计算 |
范围 | 过滤时间 /2015:11:02/,/2015:11:59/ |
if
#单分支 条件
if(条件)
print
[root@manager ~]# awk 'NR==3' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@manager ~]# awk '{if(NR==3) print $0}' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
#双分支
if(条件)
print
else
print
#企业面试题:请过滤range.log中在device: {}里面出现了多少次oldboy,过滤并统计出来
环境
[root@m01 ~]# cat range.log
oldboy is a linuxer.
device: {
oo
oldboy
no sql
this is log
niu niu
}
oldboy
device: {
oldboy
no sql
this is log
niu niu
}
oldboy
device: {
oldboy
no sql
this is log
niu niu
}
device: {
oldboy
no sql
this is log
niu niu
}
[root@m01 ~]# awk '/{/,/}/{if(/oldboy/) i++}END{print i}' range.log
4
awk '
/{/ , /}/{ #条件 匹配 {} 里面的内容
if(/oldboy/) #二次过滤 找出{}中 并且 还是oldboy的
i++ #计数
}
END{
print i #显示结果
}' range.log
for循环
c语言形式
专门用来给awk数组 循环
shell | awk |
---|---|
for((i=1;i<=10;i++));do echo $i; done | for(i=1;i<=10;i++) print i |
#显示 1…10 seq 10
[root@m01 ~]# awk 'BEGIN{for(i=1;i<=10;i++) print i }'
1
2
3
4
5
6
7
8
9
10
#计算 1+2+3…+10
[root@m01 ~]# awk 'BEGIN{for(i=1;i<=10;i++) sum+=i ;print sum }'
55
[root@m01 ~]# awk 'BEGIN{for(i=1;i<=10;i++) {sum+=i ;print sum} }'
1
3
6
10
15
21
28
36
45
55
#for配合NF
环境
cat chengji.txt
waiwai 90 98 98 96 96 92
xiaoyu 70 77 85 83 70 89
gege 85 92 78 94 88 91
xingxing 89 90 85 94 90 95
bingbing 84 88 80 92 84 82
dandan 64 80 60 60 61 62
#显示出姓名及每个人的平均数
[root@manager ~]# awk '{sum=$2+$3+$4+$5+$6+$7;print
$1,sum/6}' chengji.txt
waiwai 95
xiaoyu 79
gege 88
xingxing 90.5
bingbing 85
dandan 64.5
[root@manager ~]# awk '{sum=0;for(i=2;i<=NF;i++)
sum+=$i;print $1,sum/(NF-1)}' chengji.txt
waiwai 95
xiaoyu 79
gege 88
xingxing 90.5
bingbing 85
dandan 64.5
awk '{
sum=0;
for(i=2;i<=NF;i++)
sum+=$i;
print $1,sum/(NF-1)
}' chengji.txt