为什么要学习shell
安装操作系统(1,手动安装;2,工具自动化安装(kickstart cobbler);3,网络安装)
系统优化 关闭SElinux
Firewalld(防火墙工作中必须开启的对外场景),SSH优化,加大文件描述符,内核参数优化,yum源,安装常用的软件,ntp时间同步,字符集调整
安装服务
Nginx,apache(yum insyall httpd),PHP,MySQL,keepalived,Zabbix,SErsync,NFS,Redis,Mongo,Memcache,KVM,Docker,K8S,ELK 使用脚本安装
修改配置文件,启动服务(systemctl start stop reload restart status)
日志监控,日志切割,脚本+定时任务(rsync+sersync),脚本+定时任务,ELK
日志统计 使用三剑客+命令 做日志分析
数据备份 数据库备份(存三份)
Zabbix(常用) Nagios(交换路由,大型公司,宽带运营商使用) Cacti(监控流量),脚本把数据统计起来,使用zabbix进行监控
学习shell所需的知识
xshell CRT
常用基础命令
vim编辑器
三剑客 gep sed awk
如何学好shell编程
环境变量,条件表达式,if判断,for循环,while循环,case语句,数组,条件控制语句,continue,break,exit
针对脚本进行修改,添加各种语句判断
脚本相同可套用
shell入门
什么是shell 命令解释器,负责翻译我们输入的命令,执行成功返回给用户
linux默认的shell是bash
交互式:用户输入命令,bash负责把我们的命令翻译成内核可识别的语言返回结果到屏幕
非交互式:不与用户进行交互,执行文本里的内容,执行到文件的末尾结束
什么是shell脚本
命令的集合 很多可执行命令放在文本中称为shell脚本(包含条件表达式,判断语句,数组等等)
shell脚本规范(为自动化准备)
必须放在统一的目录
脚本必须以.sh结尾,脚本开头有注释(#!/bin/sh)必须第一行,以外的都是注释
脚本的注释信息
建议注释使用英文
成对的符号和语法一次性书写完毕
脚本名称的命名最好见名知其意
环境变量
右边一堆内容,使用一个名字来代替称为环境变量
环境变量分类
全局变量 普通变量
按照生命周期分类
永久的 需要在环境变量文件中配置 /etc/profile
临时的 使用export声明即可,重启失效
test=lizhenya 只对当前的bash生效
export test=lizhenya 对当前所有的bash生效
写入/etc/profile 针对所有用户和bash生效
变量值的定义
数值的定义
name_age=1231231 必须连续的数字
字符串的定义
name="oldboy" 字符串须加双引号解析变量,单引号所见即所得不解析变量
命令的定义
time=`date` 反引号解析命令
time=()解析命令
注意命令的定义,是把结果赋值给了变量,如果想改变结果再次赋值
shell特殊位置变量
$0 代表脚本的名称,如果全路径执行,则脚本名称带全路径
$n 脚本的第n个参数,从1开始,$9后面的参数需要加{}
$# 获取脚本传参的总数,控制脚本的传参个数
$* 获取脚本所有参数,不加引号和$@相同,加上双引号则把参数视为一个参数
$@ 获取脚本所有的参数,不加双引号和#相同,加上双引号则把参数视为独立的参数
$和? 获取上一条命令的返回结果 0为成功,非0为失败
$$ 获取脚本的PID
$! 获取上一个在后台运行脚本PID
$_ 获取命令行最后一个参数
字符串的删除和替换
$ url=www.sina.com.cn
vip821 21:46:15 ~/test
$ echo $url
www.sina.com.cn
vip821 21:46:23 ~/test
$ echo ${url#*>}
www.sina.com.cn
vip821 21:47:55 ~/test
$ echo ${url#*.}
sina.com.cn
vip821 21:48:04 ~/test
$ echo ${url#*.*.}
com.cn
vip821 21:48:27 ~/test
$ echo ${url#*.*.*.}
cn
vip821 21:48:42 ~/test
$ echo ${url##*.}
cn
vip821 21:48:57 ~/test
$ echo $url
www.sina.com.cn
vip821 21:53:02 ~/test
$ echo ${url%.*}
www.sina.com
vip821 21:53:15 ~/test
$ echo ${url%.*.*}
www.sina
vip821 21:53:31 ~/test
$ echo ${url%%.*}
www
vip821 21:53:46 ~/test
$ echo $url
www.sina.com.cn
vip821 21:55:59 ~/test
$ echo ${url/w/a}
aww.sina.com.cn
vip821 21:56:18 ~/test
$ echo ${url//w/a}
aaa.sina.com.cn
vip821 21:56:39 ~/test
条件表达式
文件测试
-e 存在则为真
-f 是否为文件
-d 是否为目录
-x 是否可执行
-r 是否可读
-w 是否可写
数值比较
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于
正则比对,需要使用[[]]
添加默认路由
route add default gw 10.0.0.254
route del default gw 10.0.0.254
ip route add 0/0 via 10.0.0.254
ip route del 0/0 via 10.0.0.254
网卡添加多个IP地址
ip addr add 10.0.0.100/24 dev eth0
for i in {10..200};do ip addr add 10.0.0.$i/24 dev eth0;done
查看策略路由 ip ro list
策略路由表 cat /etc/iproute2/rt_tables
添加一个表,给这个表设置一个路由
ip route add 0/0 via 10.0.0.254 table test
ip rule add from 10.0.0.1 table test
for循环
for i in [取值列表]
do
循环体
done
if判断
if [表达式]
then
fi
菜单的使用方法
case语句
case 变量 in
模式1
命令
;;
jumpserver案例
1,需要的连接服务器的IP地址
2,需要和服务器之间做免秘钥
3,如何登入服务器
4,使用case语句控制
while循环
while [条件表达式]
do
done
shell内置命令
exit 结束循环
continue 继续执行
break 跳出循环体,执行循环体外的命令
数组
整数数组 只能使用整数作为数组索引
关联数组 可以使用字符串作为数组索引
awk数组 将需要统计的某个字段作为数组的索引,然后对索引进行遍历
统计/etc/passwd中各种类型shell的数量
vim array.sh
#!/bin/sh
declare -A array
while read line
do
N=`echo $line | awk -F: '{print $NF}'`
let array[$N]++
done < /etc/passwd
for i in ${!array[*]}
do
echo $i ${array[$i]}
done
awk -F: '{array[$NF]++} END {for (i in array) {print i, array[i]}}' /etc/passwd
站访问状态统计
ss -an | awk '/:80/{tcp[$2]++} END {for (i in tcp) {print i, tcp[i]}}'
统计当前访问的每个IP的数量<当前实时状态netstat,ss>
ss -an | awk -F ':' '/:80/{ips[$(NF-1)]++} END {for (i in ips) {print i, ips[i]} {print sum}}' log.bjstack.log
统计2018年01月25日当天的PV量
grep "25/Jan/2018" log.bjstack.log | wc -l
awk "/25/Jan/2018/" log.bjstack.log | wc -l
awk '/25/Jan/2018/ {ips[$1]++} END {for (i in ips) {sum+=ips[i]}}'
统计15-19点的PV量
awk '$4>="[25/Jan2018:15:00:00" && $4<="[25/Jan/2018:19:00:00 {print $0}"' log.bjstack.log | wc -l
统计2018年1月25日一天访问次数最多的10个IP
awk '/25/Jan/2018 {ips[$1]++} END {for (i in ips){print ips[i], i}}' log.bjstack.log | sort -rn | head
统计15-19点访问次数最多的10个IP
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/jan/2018:19:00:00"' log.bjstack.log | awk '{ips[$1]++} END {for (i in ips){print ips[i], i}}' | sort -rn | head
统计2018年1月25日,访问大于100次的IP
awk '\25/Jan/2018/ {ips[$1]++} END {for (i in ips){if(ips[i]>10){print i, ips[i]}}' log.bjstack.log
统计2018年1月25日访问最多的10个页面
awk '/25/Jan/2018/{request[$7]++} END {for (i in request){print request[i], i}}' log.bjstack.log | sort -rn | head
统计2018年1月25日每个URL访问内容总大小
awk '/25/Jan/2018/ {request[$7]++;size[$7]+=$10} END {for (i in request) {print request[i], i, size[i]}}' log.bjstack.log | sort -rn | head
统计2018年1月25日每个IP访问状态码数量
awk '{ip_code[$1 " " $9]++} END {for (i in ip_code){print ip_code[i], i}}' log.bjstack.log | sort -rn | head
统计2018年1月25日访问状态码为404及出现的次数
grep "4.4" log.bjstack.log | wc -l
awk '{if($9=="404") code[$9]++} END {for (i in code){print i, code[i]}}' log.bjstack.log
统计2018年1月25日8:30-9:00访问状态码是404
awk '$4>="[25/Jan/2018:15:00:00" && $4<="[25/Jan/2018:19:00:00" && $9=="404" {code[9=="404" {code[$9]++} END {for (i in code){print i, code[i]}}' log.bjstack.log
统计2018年1月25日各种状态码数量,统计状态码出现的次数
awk '{code [$9]++} END {for (i in code){print i, code[i]}}' log.bjstack.log
awk '{if ($9>=100 && $9<200) {i++}}'
awk的处理数据的方式
进行逐行扫描文件,从第一行到最后一行
寻找匹配的特定模式的行,在行上进行操作
如果没有指定处理动作,则把匹配的行显示到标准输出
如果没有指定模式,则所有被操作的行都被处理
BEGIN发生在读文件之前
awk 'BEGIN{print 1/2}'
BEGIN在行处理前,修改字段分隔符
awk 'BEGIN{FS=":"} {PRINT $1}' /etc/passwd
BEGIN在处理前,修改字段读入和输出分隔符
awk 'BEGIN{FS=":";OFS="---"} {PRINT 2}' /etc/passwd
awk 'BEGIN{print 1/2} {print "ok"} END {print "Game Over"}' /etc/hosts
匹配
awk '/root/' /etc/passwd
处理动作
awk -F: '{print $1}' /etc/passwd
匹配+处理动作
awk -F ':' '/root/ {print $1, $3}' /etc/passwd
awk 'BEGIN{FS=":"} /root/ {print $1, $3}' /etc/passwd
判断大于多少则输出什么内容
df | awk '//$/ {if ($3>500000) print $4}'
保存当前记录的内容
awk '{print $0}' /etc/passwd
记录输入总的编号(行号)
awk '{print NR, $0}' /etc/passwd
awk 'NR<=3' /etc/passwd
当前输入文件的编号(行号)
awk '{print NR,$0}' /etc/passwd /etc/hosts
awk '{print FNR,$0}' /etc/passwd /etc/hosts
保存行的最后一列
awk -F ":" '{print NF,$NF}' /etc/passwd /etc/hosts
指定字段分割符,默认是空格
awk -F: '/root/{print $1,$3}' /etc/passwd
awk 'BEGIN{FS=":"} {print $1, $3}' /etc/passwd
awk -F '[ :\t]' '{print $1, $2, $3}' /etc/passwd
指定输出字段分隔符
awk -F: '/root/{print $1, $2, $3, $4}' /etc/passwd
awk 'BEGIN{FS=":";OFS="+++"} /root/{print $1, $2}' /etc/passwd
输入记录分隔符,默认为换行符
awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts
将文件以空格为分割每一行合并为一行
awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts
print格式化输出函数
date | awk '{print $2, "5月份""\n", $NF, "今年"}'
awk -F: '{print "用户是:" $1 "\t 用户 uid:" $3 "\t用户gid:" $4}' /etc/passwd
printf函数
awk -F: '{printf "%-15s %-10s %-15s\n", $1, $2, $3}' /etc/passwd
匹配记录(整行)
awk '/^root/' /etc/passwd
awk '$0~/^root/' /etc/passwd
匹配字段,匹配操作符
awk '$1~/^root/' /etc/passwd
awk '$NF !~/bash$/' /etc/passwd
比较表达式
比较表达式采用对文本进行比较,只有当条件为真才执行指定的动作
比较表达式使用关系运算符,用于比较数字与字符串
uid为0的列出来
awk -F ":" '$3==0' /etc/passwd
uid小于10的全部列出来
awk -F: '$3<10' /etc/passwd
用户登入的shell等于/bin/bash
awk -F: '$7=="/bin/bash"' /etc/passwd
第一列为alice的列出来
awk -F: '$1=="alice"' /etc/passwd
为alice的用户列出来
awk -F:'$1~/alice/' /etc/passwd
awk -F: '$1!~/alice/' /etc/passwd
磁盘使用率大于多少则打印可用的值
df | awk '//$/' | awk '$3>1000000 {print $4}'
条件表达式
awk -F: '$3>300 {print $0}' /etc/passwd
awk -F: '{if($#>300) print $0}' /etc/passwd
awk -F: '{if($3>5555){print $3} else {print $1}}' /etc/passwd
运算表达式
awk -F: '$310>5000000' /etc/passwd
awk -F: 'BEGIN{OFS="--"}{if($310>5000000) {print $1,$3}} END {print "打印ok"}' /etc/passwd
awk '/southem/{print $5 + 10}' datafile
awk '/southem/{print $5 + 10.56}' datafile
awk '/southem/{print $8 - 10}' datafile
awk '/southem/{print $8 / 2}' datafile
awk '/southem/{print $8 * 2}' datafile
awk '/southem/{print $8 % 2}' datafile
逻辑操作符和复合模式
匹配用户名为root并且打印uid小于15的行
awk -F: '$1~/root/ && $3<=15' /etc/passwd
匹配用户名为root或uid大于5000
awk -F: '$1~/root/ || $3>=5000' /etc/passwd
vim b.txt
lzy lizhenya:is a:good boy!
awk '{print NF}' b.txt
awk -F ':' '{print NF}' b.txt
awk -F "[ :]" '{print NF}' b.txt
打印当前管理员用户名称
awk -F: '{if($3==0){print $1 "is adminisitrator"}}' /etc/passwd
统计系统用户数量
awk -F: '{if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
统计普通用户数量
awk -F: '{if($3>1000){i++}} END {print i}' /etc/passwd
if...else语句格式
awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd
awk -F: '{if($3==0){count++} else {i++}}' /etc/passwd
awk -F: '{if($3==0){count++} else {i++}} END {print "管理员个数:" count; print "系统用户数:" i}' /etc/passwd
if...else...if...else语句格式
awk -F: '{if($3==0){i++} else if ($3>0 && $3<1000){j++} else if ($3>1000) {k++}} END {print i;print j;print k}' /etc/passwd
awk -F: '{if($3==0){i++} else if ($3>0 && $3<1000){j++} else if ($3>1000){k++}} END {print "管理员个数" i;print "系统用户个数" j;print "系统用户个数"}' /etc/passwd
while循环
awk 'BEGIN{i=1;while(i<=10){print i;i++}}'
awk -F: '{i=1;while(i<=NF){print $i;i++}}' /etc/passwd
awk -F: '{i=1;while(i<=10){print $0;i++}}' /etc/passwd
vim b.txt
111 222
333 444 555
666 777 888 999
awk '{i=1;while(i<=NF){print $i;i++}}' b.txt
for 循环
awk 'BEGIN{for(i=1;i<=5;i++){print i}}'
awk -F: '{for (i=1;i<=10;i++){print $0}}' passwd
awk -F: '{for (i=1;i<=nf;i++){print $i}}' passwd
正则表达式描述
\ 转义符,将特殊字符进行转义,忽略其特殊意义
^ 匹配行首,awk中,^是匹配字符串的开始
$ 匹配行尾,awk中,$是匹配字符串的结尾
^$ 表示空行
. 匹配除换行符\n之外的任意单个字符
.* 匹配所有
[ ] 匹配包含在[字符]之中的任意一个字符
[^ ] 匹配[^字符]之外的任意一个字符
[ - ] 匹配[]中指定范围内的任意一个字符
? 匹配之前的项1次或者0次
+ 匹配之前的项1次或者多次
* 匹配之前的项0次或者多次
() 匹配表达式,创建一个用于匹配的子串
{ n } 匹配之前的项n次,n是可以为0的正整数
{n,} 之前的项至少需要匹配n次
{n,m} 指定之前的项至少匹配n次,最多匹配m次,n<=m
| 交替匹配|两边的任意一项ab(c|d)匹配abc或abd
特定字符
>[[:space:]] 空格
[[:digit:]] [0-9]
[[:lower:]] [a-z]
[[:upper:]] [A-Z]
[[:alpha:]] [a-Z]
grep参数
-a 二进制以文本方式搜索数据
-c 计算找到的搜索字符串总行数
-o 仅显示出匹配到的内容,统计文件中出现的次数
-i 不区分大小写
-v 反向选择 显示没有 收到字符串的那一行
-E 扩展的grep即egrep
-clolr=auto 以特定颜色高亮显示匹配关键字
-B 除显示匹配一行之外,并显示该行之前的num行
-A 除显示匹配一行之外,并显示该行之后的num行
-C 除了显示匹配的行外,并显示该行之前后的各num行
-w 按单词搜索,相当于\b
-r 递归查找目录下所包含的内容
过滤以m开头的行
grep "^m" test.txt
过滤以m结尾的行
grep "$m" test.txt
排除空行,并打印行号
grep -vn "^$" lizhenya.txt
匹配任意一个字符,不包括空行
grep "." lizhenya.txt
匹配所有
grep ".*" lizhenya.txt
匹配单个任意字符
grep "lizhen.a" lizhenya.txt
以点结尾的
grep "\.$" lizhenya.txt
精确匹配到
grep -o "8*" lizhenya.txt
匹配有abc的行
grep "[abc]" lizhenya.txt
匹配数字所在的行"[0-9]"
grep "[0-9]" lizhenya.txt
匹配所有小写字母
grep "[a-z]" lizhenya.txt
重复8三次
grep -E "8{3}" lizhenya.txt
grep "8\{3\}" lizhenya.txt
重复数字8 3-5次
grep "8\{3,5\}" test.txt
8至少1次或1次以上
grep "8\{1,\}" test.txt
sed选项参数
-e 允许多项编辑
-n 取消默认的输出
-i 直接修改对应文件
-r 支持扩展元字符
sed内置命令参数
a 在当前行后添加一行或多行
c 在当前行进行替换修改
d 在当前行进行删除操作
i 在当前行之前插入文本
p 打印匹配的行或指定行
n 读入下一输入行,从下一条命令进行处理
! 对所选行以外的所有行应用命令
h 把模式空间里的内容重定向到暂存缓冲区
H 把模式空间里的内容追加到暂存缓冲区
g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容
G 取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后面
先删除行,然后管道给后面的sed进行替换
sed '1,9d' passwd | sed 's#root#alex#g'
使用-e进行多次编辑修改操作
sed -e '1,9d' -e 's#root#alex#g' passwd
打印匹配halt的行
sed -n '/halt/p' passwd
打印第二行的内容
sed -n '2p' passwd
打印最后一行
sed -n '$p' passwd
给3行添加配置\t tab键(需要转义)\n 换行符
sed -i '30a listen 80:' passwd
指定某行进行内容替换
sed -i '7c SELINUX=Disabled' /etc/selinux/config
正则匹配对应内容,然后进行替换
sed -i '/^SELINUX=/c SELINUX=Disabled' /etc/selinux/config
非交互式修改指定配置文件
sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config
sed -ri '/GSSAPIAuthentication/c#GSSAPIAuthentication no' /etc/ssh/sshd_config
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
指定删除第三行,但不会改变文件内容
sed '3d' passwd
sed '3{d}' passwd
从第三行删除到最后一行
sed '3,$d' passwd
删除最后一行
sed '$d' passwd
删除所有的行
sed '1,$d' passwd
匹配正则进行该行删除
sed /maild/d passwd
在文件的某一行上面添加内容
sed -i '30i listen 80;' passwd
将匹配到的行写入到新文件中
sed -n '/root/w newfile' passwd
将passwd文件的第二行写入到newfile中
sed -n '2w newfile' passwd
匹配root的行,删除root行的下一行
sed '/root/{n;d}' passwd
替换匹配root行的下一行
sed '/root/{n;s/bin/test/}' passwd
将第一行的写入到暂存区,替换最后一行的内容
sed '1h;$g' /etc/hosts
将第一行的写入到暂存区,在最后一行调用暂存区内容追加至于尾部
sed '1h;$G' /etc/hosts
将第一行的内容删除但保留至暂存区,在最后一行调用暂存区内容追加至于尾部
sed -r '1{h;d};$G' /etc/hosts
将第一行的内容写入至暂存区,从第二行开始进行重定向替换
sed -r '1h;2,$g' /etc/hosts
将第一行重定向至暂存区,2-3行追加至暂存区,最后追加调用暂存区的内容
sed -r '1h;2,3H;$G' /etc/hosts
除了第三行,其他全部删除
sed -r '3!d' /etc/hosts
替换每行出现的第一个root
sed 's/root/alice/' passwd
替换以root开头的行
sed 's/^root/alice' passwd
查找匹配到的行,在匹配的行后面添加内容
sed -r 's/[0-9][0-9]$/& .5/' passwd
匹配包含有root的行进行替换
sed -r 's/root/alice/g' passwd
匹配包含有root的进行替换,忽略大小写
sed -r 's/root/alice/gi' /etc/passwd
后向引用
sed -r 's#(Roo)#\1-alice#g' passwd
ifconfig eth0 | sed -n '2p' | sed -r 's#(^.et) (.*) (net.$)#\2#g'
vim a.txt
/etc/abc/456
etc
删除文本中的内容,需要转义
sed -r '/etc/abc/456/d' a.txt
如过碰到/符号,建议使用#符替换
sed -r 's#/etc/abc/456#/dev/mull#g' a.txt
sed -r 's@/etc/abc/456@/dev/null@' a.txt
删除配置文件中#号开头的注释行,如果碰到tab或空格是无法删除
sed '/^#/d' file
删除配置文件中含有tab键的注释行
sed -r '/^[ \t]*#/d' file
删除无内容的空行
sed -r '/^[ \t]*$/d' file
删除注释行及空行
sed -r '/^[ \t]#d;/^[ \t]*$/d' /etc/vsftpd/vsftpd.conf
sed -r '/^[ \t]# | ^[ \t]*$d' /etc/vsftpd/vsftpd.conf
sed -r '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf
将第二行到第六行加上注释信息
sed '2,6s/^/#/' passwd
将第二行到第六行最前面添加注释符
sed -r '2,6s/.*/#&/' passwd
位置参数
$0 获取脚本的名字,包含路径
$n $n(n为任意数字),代表脚本在命令行的第几个参数
$# 获取脚本参数的个数
$* 获取当前shell脚本所有传参的参数,如果不加引号作用同"则表示将所有的参数视为单个字符串,相当于"$1$2$3"
$@ 获取当前shell脚本所有传参的参数,不加引号同$相同,加上双引号则表示把所有的参数视为不同的独立的字符串
特殊变量
$? 获取执行上一个指令执行状态返回值,0为成功,非0失败
$$ 获取当前shell脚本的进程号PID
$! 获取上一个在后台工作脚本进程的进程号PID
字母比较符 -eq -ne -gt -ge -lt -le
特殊变量扩展
${oldboy} 输出变量的内容,对变量有保护作用
${#oldboy} 输出变量的长度
${url#*.} 从前往后删除匹配最短的任意开头的字符到.的内容
${url##*.} 从前往后删除匹配最长的任意开头的字符到.的内容
${url%.*} 从后往前删除匹配最短的结尾时.开头的内容
${url%%.*} 从后往前删除匹配最长的结尾是.开头的内容
数值的整数和小数运算有哪几种方式
小数 awk bc
整数 expr [] let
写出下面条件测试的含义
[ -e dir|file ] 存在则为真
[ -d dir ] 目录是否存在
[ -f file ] 文件是否存在
[ -r file ] 文件是否有读权限
[ -x file ] 文件是否有执行权限
[ -w file ] 文件是否有写权限
写一个判断语句,如果/tmp/oldboy.txt文件不存在则进行创建
[ -f /tmp/oldboy.txt ] || touch /tmp/oldboy.txt
如何定义环境变量
临时的 export declare -x
永久放入 /etc/profile /etc/bashrc
定义变量内容,不加引号,单引号,双引号,反向引号结果有什么不同?
不加引号 一般纯数字,简单连续的字符串也可以
单引号 所见即所得,看见什么就输出什么
双引号 默认是双引号,连续的字符串数字混合在一起,解析变量
反引号 解析命令
写出普通数组和关联数组定义的两种方式
普通数组 只能使用整数,作为数组索引
关联数组 可以使用字符串,作为数组索引
array = (1 2 3)
array = (1 2 3 "test"[10]=oldboy)
declare -A array
如何查看数组array元素的索引和元素总个数
echo ${!array[]}
echo ${#array[]}
写一个数组脚本统计/var/log/nginx.log里IP访问次数
awk '{h[$1]++} END {for (police in h) print police, h[police]}' /var/log/nginx.log
输入两个整数计算两个整数的相加,相减,相乘,相除,求余的结果
#!/bin/bash
read -p "请你输入两个整数:" A B
expr $A + $B &>/dev/null
if [ $? -ne 0 ]
then
echo "刚才都输入了两个整数"
exit
fi
expr $A + $B
expr $A - $B
expr $A \* $B
expr $A / $B
expr $A % $B
把一个文本文档的前五行中包含字母的行删除掉,同时把6到10行中的全部字母删除掉
#!/bin/bash
sed -n '1,5p' 111.txt | sed '/[a-Z]/d' >123.txt
for i in `eq 6 10`
do
l = `sed -n ${i}p 111.txt`
echo $l | sed "s#[a-Z]##g" >>123.txt
done
re -f 111.txt
mv 123.txt 111.txt
打印下面这句话中字母数小于5的单词 I am Hzhenya teacher I am 18
#!/bin/bash
for i in I am lizhenya teacher I am 48
do
if [ ${#i} -lt 5 ]
then
echo $i
fi
done
写个shell,看看你的linux系统中是否有自定义用户(普通用户),若是有,一共有几个?
#!/bin/bash
N = `awk -F ":" '{if($3>=1000 && $3<=6000) print $0}' /etc/passwd | wc -l`
if [ $N -ne 0 ]
then
echo "yes user:$N"
fi
写一个shell脚本来看看你使用最多的命令是哪些,列出你最常用的命令top10
#!/bin/bash
sort /root/.bash_history | unique -c | sort -nr | head
编写一个脚本,计算100以内所有能被3整除数字的和
#!/bin/bash
for i in `seq 3 3 100`
do
sum = $[$sum+$i]
done
echo $sum
查看磁盘/当前使用状态,如果使用率超过80%则把结果输出到/var/log/disk.err
#!/bin/bash
Disk_Use = $(df -h | grep '/$' | awk '{print $5}' | awk -F % '{print $1}')
if [ $Disk_Use -ge 80]
then
echo "Disk Is use ${Disk_Use}%" >/tmp/log/disk.err
fi
脚本批量创建10个用户,密码统一为123,需要对用户输入是否为数字和输入的名字是否为空做判断
#!/bin/bash
read -p "请输入创建用户个数" num
if [[ !$sum=~^[0-9]+$ ]]
then
echo "Please Input 数字"
exit 1
fi
read -p "请输入用户名前缀" prefix
if [[ -z $prefix ]]
then
echo "Please Input 前缀"
exit 2
fi
for in `seq "$num"`
do
User = $prefix$i
useradd $USER
echo "123" | passwd --stdin $USER &>/dev/null
if [ $0 -eq 0 ];then
echo "$USER s create ok"
fi
done
猜数字游戏,随机输入一个1-100的数字,要求用户输入数字(数字处加判断),如果比随机数小则提示比随机数小了,大则提示比随机数大了,正确则退出。错误则继续死循环,最后统计猜了多少次
#!/bin/bash
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 次"
打印一个菜单如下,然后用case语句输出用户输入菜单选项的结果
h 显示命令帮助
f 显示登陆信息
d 显示磁盘信息
m 查看内容使用
u 查看系统负载
q 退出程序
#!/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
用case语句写出nginx启动脚本
#!/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/ngiinx -s reload
te
}
status(){
Ngx status=$(ps aux | grep "[n]ginx" | grep master | awk '{print $2}')
Nginx_Status_Port=$(nestat-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
sleep1
start
;;
reload)
reload
;;
status)
status
;;
*)
echo "*Usage:$0{start | stop | status | restart | reload |}"
esac
写一个脚本探测10.0.0.1-254之间存活的主机,输出到ip.txt
#!/usr/bin/bash
for n in {1..254}
do
ping 10.0.0.$n -c 1 >/dev/null
if [ $? -eq 0 ]
then
echo "10.0.0.$n is alive"
echo "10.0.0.$n" >>/ip.txt
done
抓阄项目
#!/bin/bash
>/tmp/pass
suss(){
echo "你们3个人去吧"
cat /tmp/pass | sort -rk2 | head -n 3
exit 0
}
while true
do
read -p "输入你的名字全拼:" name
num = `mkpasswd -d 2 -s 0 | sed 's#[a-Z]##g'`
while [ `grep $num /tmp/pass | wc -l` -ne 1 ]
do
read -p "输入你的名字全拼:" name
if [[ ! "$name" =~ [a-Z] ]]
then
echo "别瞎搞,全拼"
break 1
fi
if [ "$name"="exit" ]
then
suess
fi
if [ `grep $name /tmp/pass | wc -l` -eq 1 ]
then
echo "有人跟你重名,可以在名字后加上s"
break 1
fi
echo "你的数字:$num"
echo -e "$name\t$num" >>/tmp/pass
done
done
网友评论