1、有两个文件 a.txt 和 b.txt,把 a.txt 中有的但 b.txt 中没有的行找出来,并写入列 c.txt,然后计算 c 的行数;
注释:比较两个文件两个文件不同,可以用的方法:diff md5sum grep -vf $1 $2(这个命令匹配$1中没有的,$2中有的)
diff: 比较两个文件内容的不同,没有不同则不输出内容; diff $1 $2
当 $1 内容多,则显示 < 内容; 当 $2 内容多,则显示 > 内容;
[root@localhost_002 shell100]# diff 1.txt 2.txt #两个文件内容相同; #比较两个文件,当1.txt文件内容多了,会显示在下面: < yhh [root@localhost_002 shell100]# diff 1.txt 2.txt #1.txt文件内容多出yhh; 6d5 < yhh #比较两个文件,当2.txt文件内容多了,会显示在下面: < yuanhaohao [root@localhost_002 shell100]# diff 1.txt 2.txt #2.txt文件内容多出yhhaohao; 4a5 > yuanhaohao
md5sum :通过文件会返回 一个值; md5sum 1.txt 当内容相同,则返回的字符串会相等;此处不是适用;
[root@localhost_002 shell100]# md5sum 1.txt 620dcc1ed298c34ff730989cbd4e7b06 1.txt [root@localhost_002 shell100]# md5sum 2.txt 620dcc1ed298c34ff730989cbd4e7b06 2.txt
grep -f:会检索两个文件相同的内容部分; grep -f b.txt a.txt 匹配a.txt 中有的, b.txt中没有的;
[root@localhost_002 shell100]# cat a.txt #a.txt 文件内容; aaa bbb ccc [root@localhost_002 shell100]# cat b.txt #b.txt 文件内容; bbb aaa [root@localhost_002 shell100]# grep -f b.txt a.txt #判断 a.txt 和 b.txt 共同有的内容; aaa bbb [root@localhost_002 shell100]# grep -vf b.txt a.txt|wc -l #a.txt为准,判断a.txt中有,b.txt不存在的内容; 1
注释:grep -vf b.txt a.txt|wc -l 表示取反,打印出a.txt中存在,b.txt不存在的文件内容;
或者用while 循环遍历 a.txt ,诼行进行匹配,如果这一行在b.txt中没有,就直接重定向到c.txt;
注释:在使用 if 判断时 grep "^$line$" 才能更精确去匹配整行的内容;
grep -vf b.txt a.txt 这样得到的结果是 a.txt 和 b.txt 中都有的行,而要的结果是 a.txt中有, b.txt 中没有的的行,原来的基础上加上 -v 选项即可实现效果;
2、把当前用户下含有所有进程名字中含有"httpd"的进程关闭;
注释:当前用户: $USER
[root@localhost_002 shell100]# echo $USER root [root@localhost_002 shell100]# ps -u $USER
注释:ps -u user 指定用户名 可以查看该用户下的有进程;
使用awk的 $NF 即最后一列的值匹配'httpd'关键字的行,再打印第一列 即目标pid,把这些 pid kill掉就可以了;
ps -u $USER|awk '$NF ~ /httpd/ {print $1}'|xargs kill
[root@localhost_002 shell100]# ps aux |grep httpd root 1697 0.6 1.0 261744 10992 ? Ss 20:41 0:00 /usr/local/apapche2.4/bin/httpd -k restart daemon 1698 0.0 1.0 548572 10180 ? Sl 20:41 0:00 /usr/local/apapche2.4/bin/httpd -k restart daemon 1699 0.0 1.0 548572 10180 ? Sl 20:41 0:00 /usr/local/apapche2.4/bin/httpd -k restart daemon 1700 0.0 1.0 548572 10180 ? Sl 20:41 0:00 /usr/local/apapche2.4/bin/httpd -k restart root 1783 0.0 0.0 112720 972 pts/0 R+ 20:41 0:00 grep --color=auto httpd [root@localhost_002 shell100]# cat 62.sh #!/bin/bash #这个脚本用来批量杀死某个进程的脚本 #日期: 2019-01-20 #作者: yuanhh ps -u $USER|awk '$NF ~ /httpd/ {print $1}'|xargs kill 执行脚本: [root@localhost_002 shell100]# sh -x 62.sh + awk '$NF ~ /httpd/ {print $1}' + xargs kill + ps -u root [root@localhost_002 shell100]# ps aux |grep httpd root 1886 0.0 0.0 112720 972 pts/0 R+ 20:41 0:00 grep --color=auto httpd
注释:如上httpd 的进程以及被杀死了;
3、用 shell 脚本,以并发进程的形式将 mysql 数据库所有的表备份到当前目录,并把所有的表压缩到一个压缩包里面;
假如数据库为 mysql ,用户名是 yuanhh , 密码为 nihao123!;
那么如何实现 并发进程了 : shell 中加上 & 可以将命令丢到后台,实现多条命令达到并发的效果;(不过要控制并发数,不然表数量大,服务资源支撑不了);
备份 表的命令: mysqldump -uroot -pnihao123! mysql tbname > taname.sql
解析:首先定义一个并发值变量N;使用mysql -uroot -pnihao123! mysql -e "show tables"|sed '1'd > table.txt 然后把mysql 下的表过滤出来(需要用sed 把第一行删除)并写入到临时文件;
然后wc -l 计算一下table 有多少行;用awk '{print $1}'过滤出行数;
下面那如何一次性去备份所有表,因为并发值设定的 5 ,每次只备份5个表,把表均分成5个表,保存到一个临时文件,然后用for 循环一个一个来备份;
那么如何把表均分成每个五份??? 通过wc 列出的行数$n除以 $N并发值 5 则得到临时文件的行数,然后通过split -l 5 来平均分割(xaa xab xac xad xae);
还要考虑到一个问题,如果表的总数小于 5 了,就没必要再分一个组了;可以使用四舍五入的函数来做;
可以写一个四舍五入的函数来定义;
div(){ n=`echo "scale=1;$1/$2"|bc` n1=`echo "scale=1;$n+0.5"|bc` echo $n1|cut -d . -f1 } #######n1=$[$n/$N] n1=`div $n $N`
备份;写一个函数(使用for循环来cat $1(xaa xab xac xad xae)那个文件,然后逐行导出到 $t.txt);因为逐行,所以需要时间;
myd(){ for t in `cat $1`;do mysqldump -uroot -pnihao123\! mysql $t > $t.txt
在用一个for 循环依次把这五个文件循环备份; for f in xaa xab xac xad xae;do myd $f &;done #这个并发的,因为是5个一起执行;
wait :因为运行以上命令需要时间,所以此处使用 wait 命令(当后台的所有进程执行完成后,wait才会释放);否则则处于等待状态;
[root@localhost_002 shell100]# sleep 10 & [2] 2250 [root@localhost_002 shell100]# wait [2]- 完成 sleep 10
脚本如下:
[root@localhost_002 shell100]# cat 63.sh #!/bin/bash #这个脚本用来并发备份数据库 #日期: 2019-01-20 #作者: yuanhh #定义并发值为5 N=5 mysql -uroot -pnihao123! mysql -e "show tables"|sed '1'd > /tmp/table.txt n=`wc -l /tmp/table.txt|awk '{print $1}'` div(){ n=`echo "scale=1;$1/$2"|bc` n1=`echo "scale=1;$n+0.5"|bc` echo $n1|cut -d . -f1 } #n1=$[$n/$N] n1=`div $n $N` split -l $n1 /tmp/table.txt #备份函数; $1是一个文件名; myd(){ for t in `cat $1` do mysqldump -uroot -pnihao123\! mysql $t > $t.sql 2>/dev/null done } for f in xaa xab xac xad xae do myd $f & done #wait 表示等待后台进程运行完后,才会释放; wait tar czf mydb.tar.gz *.sql rm -fr *.sql 执行脚本: [root@localhost_002 shell100]# sh 63.sh [root@localhost_002 shell100]# ls -ld mydb.tar.gz -rw-r--r-- 1 root root 181145 1月 20 22:34 mydb.tar.gz
注释:如上,有一条命令执行时会显示警告细信息; mysql -uroot -pnihao123! mysql -e "show tables"|sed '1'd|head -n3
[root@localhost_002 ~]# mysql -uroot -pnihao123! mysql -e "show tables"|sed '1'd|head -n3 Warning: Using a password on the command line interface can be insecure. columns_priv db event
其实这个 waring 并不会影响脚本的正常运行,但是让人看着很不爽,不过可以去掉的了; 使用 mylogin.cnf
mysql_config_editor set --user=root --host=127.0.0.1 --port=3306 --passwd
[root@localhost_002 ~]# mysql_config_editor set --user=root --password Enter password: [root@localhost_002 ~]# ls -ld .mylogin.cnf -rw------- 1 root root 100 1月 21 14:48 .mylogin.cnf
然后在当前目录下会生成一个文件 mylogin.cnf,然后再次执行时则mysql 后面跟要执行的命令即可;不会出现警告信息;
[root@localhost_002 ~]# mysql mysql -e "show tables"|sed '1'd|head -n3 columns_priv db event
4、假设一个网站使用cdn,全国各地有十多个cdn节点,需要你写一个监控脚本,监控这些节点是否正常;
网址:www.baidu.com/index.php 源站IP 为 61.135.169.125
网站通过CDN网络在全国分别部署多个节点,让用户就近来访问,提高用户感知;可以通过比较源站和各个节点的文件
思路:首先会把各个节点的IP地址都收集到一个ip.list的文件中; /tmp/ip.list
然后通过curl -x代理IP:port 网址 去访问这个网站的首页;并把信息保存到/tmp/source.txt curl -x 61.135.169.125:80 www.baidu.com/index.php
通过 for 循环 ip.list,然后用curl 命令来输出网站首页信息并保存在/tmp/ip.txt
再通过 diff 命令来比较这两个文件是否相等,并写入/tmp/$ip.diff; 或者用 md5sum grep -f 也可以;
diff 1.txt 2.txt 如果这两个文件相等,则不会任何输出,否则则输出不相等的内容;
再通过 wc -l /tmp/$ip.diff|awk '{print $1}' 判断其行行数;
通过一个 if 来判断,如果大于 0 ,则节点有异常; #因为默认是不会有任何输出的;
[root@localhost_002 shell100]# cat /tmp/ip.list 61.135.169.125 [root@localhost_002 shell100]# cat 64.sh #!/bin/bash #这个脚本用来监控网站的CDN节点是否正常 #日期: 2019-01-21 #作者: yuanhh s_ip=61.135.169.125 url=www.baidu.com/index.php ipf=/tmp/ip.list curl -x$s_ip:80 $url 2>/dev/null > /tmp/source.txt for ip in `cat $ipf` do curl -x$ip:80 $url 2>/dev/null >/tmp/$ip.txt diff /tmp/source.txt /tmp/$ip.txt > /tmp/$ip.diff n=`wc -l /tmp/$ip.diff|awk '{print $1}'` if [ $n -gt 0 ] then echo "节点$ip有异常" fi done #执行命令:无输出则表示节点正常; [root@localhost_002 shell100]# sh 64.sh #此时手动添加一个ip地址; [root@localhost_002 shell100]# cat /tmp/ip.list 61.135.169.125 127.0.0.1 [root@localhost_002 shell100]# sh 64.sh 节点127.0.0.1有异常 #有输出,则表示节点有问题;
注释:如上脚本,如果 cdn 节点有问题,则会有输出,如果没问题,则不会有任何输出;
5、破解字符串,已知下面的字符串时通过 RADOM 随机数 md5sum|cut -c 1-8 截取后的结果,请破解这些字符串对应的 md5sum 前用RANDOM 对应数字;
RANDOM 对应字符串:21029299 00205d1c a3da1677 1f6d12dd 890684ba
RANDOM 是一个数字,通过 md5sum 加密成字符串,然后截取前 8 个字符串;
[root@localhost_002 shell100]# echo $RANDOM 8451 [root@localhost_002 shell100]# echo $RANDOM|md5sum e7d303858c4ffc981a2d9c20850c8ec7 - [root@localhost_002 shell100]# echo $RANDOM|md5sum|cut -c 1-8 8d5ce504
思路:$RANDOM 的范围值时 0-32767,要解这个题,需要遍历0-32767所有数字,逐一和题目中给出的数字来匹配;
因为本地需要匹配5个字符串,所以需要逐一遍历,那么就有如下两种方案:
以 0-32767 为主,每遍历一个数字,再遍历五个字符串; #总共 32768 次; 每次 五个字符串;
以 5 个字符串为主,每遍历一个字符串,再遍历32768个数字; #总共 5 * 32768 = 163840 次;5个字符串,每个字符串遍历 32768 次;
由于要遍历 32768 次,很耗时,所以选择第一种方案,用 md5sum 每计算一个值,则和题目中的5个字符串对比;
方法一:首先用到了 for 来 遍历 0 - 32767;然后分别打印出 每个数字 md5sum 值; 定义变量 $n;
然后嵌入 for 来循环 这 五个字符串,定义变量 $c ;
然后用 if 判断 "$n" == "$c" 如果等于则打印出来;
脚本如下:
[root@localhost_002 shell100]# cat 65.sh #!/bin/bash #这个脚本用来破解字符串 #日期: 2019-01-21 #作者: yuanhh #for n in {0..32767} 也可以写成这样,同下面的用法相同; for n in `seq 0 32767` do md5=`echo $n|md5sum|cut -c 1-8` for c in 21029299 00205d1c a3da1677 1f6d12dd 890684ba do if [ "$md5" == "$c" ] then echo $n $c fi done done #执行:比较耗费资源; [root@localhost_002 shell100]# sh 65.sh 1346 00205d1c 7041 1f6d12dd 10082 890684ba 25345 a3da1677 25667 21029299
注释:for n in {0..32767} ====== for n in `seq 0 32767` 用法是一样子的;
方法二:先用 for 来遍历 0-32767 个数字,然后计算每个数字 md5sum 值前 8 位,并赋予变量 $m,然后把数字 echo $i $m 保存到/tmp/md5.txt里;
然后嵌入文档 EOF 字符串的内容保存到 当前目录下 c.txt, 然后使用 grep -f 参数来比较;
注释:因为 grep -f 参数会打印相同的部分,用在这里最合适了;
[root@localhost_002 shell100]# cat 65.1.sh #!/bin/bash for i in `seq 0 32767` do m=`echo $i|md5sum|cut -c 1-8` echo $i $m done > /tmp/md5.txt cat > c.txt >>EOF 21029299 00205d1c a3da1677 1f6d12dd 890684ba EOF grep -f c.txt /tmp/md5.txt #执行脚本: 占用系统资源多; [root@localhost_002 shell100]# sh 65.sh 1346 00205d1c 7041 1f6d12dd 10082 890684ba 25345 a3da1677 25667 21029299
注释:嵌入文档 EOF 格式:会在当前的脚本里在做写入操作; 以 >>EOF 开头,以 EOF 结尾;注意格式;
cat > c.txt >>EOF 21029299 00205d1c a3da1677 1f6d12dd 890684ba EOF