关于git的一些谜
话说五一前去了趟省中心开会,主要讲应急预案文档。开完会之后,那边的技术对接人提到一个类似金钟罩防护的东西,想下班之后锁死静态网页目录下所有文件,啥人啥操作都不能改(不查不知道,原来“金钟罩”是个中国传统武术中的一种武术功能,突然发现很多技术人员都自带各种诗情画意。。。),叫我查下市面上有没有这种产品,然后最后他提到linux上好像有命令能锁死,具体他不知道叫什么(我当然知道他说什么了),回到公司就准备试试chattr,那会最担心的是对所有文件上锁会不会特别久,解锁也是。实测,很快!
第1天的时候,我在线上一台有公网的服务器上,把前几天静态网页目录备份文件拷过来(压缩备份的时候我是排除.git备份的,因为奇大无比),所以测试非常成功。参考了这篇文章:https://www.cnblogs.com/kevingrace/p/8277820.html
for A in `ls -l /data/test/|grep -v total|awk '{print $9}'`;do /usr/bin/chattr +ai /data/test/${A}
他这条命令有点问题,或者说我的测试环境不适合。只能对 /data/test 下的第一层目录进行上锁,但是目录下递归到的文件,全部没有起效!
我的改良版变成这样,成功把子目录下的所有文件都上锁了,包括隐藏文件。
find . -name "[!.]*" 这句好像没用的
find $PWD | find . -name "[!.]*" | xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr +ai
然后我就充满信心地,第二天拿备机去模拟生产(对了,当天的日志,我提到我做的测试工作,老板都有点害怕,评论叫我多测几次才上生产),确实,发现很多问题。。。
第二天用备机测试,假设静态目录叫status_ljy,整个目录连.git,共16G,.git目录有6.7G。(主服务器更大,30G,.git目录20G,这个是后话哈~~~)
为了更真实地模拟生产环境,我把主服务器的防篡改监控脚本拎了过来:运行git status命令,看是否有“nothing to commit”字样,有就代表线上没被人改过东西,否则就要查下具体是什么原因了(大家可以结合该文一起看:【网站防篡改内容监控】https://www.cnblogs.com/windysai/p/14354460.html)
写好加锁脚本:addchattr.sh
1 #!/bin/bash 2 3 gitDir='/home/hahah/data/html/status_ljy' 4 DATE=`date +%F_%H:%M` 5 recordfile='/tmp/addchattr.log' 6 >${recordfile} 7 8 echo "脚本功能:给文件特殊权限,不能作任何修改" >> ${recordfile} 9 echo "开始运行脚本时间为: $DATE" >> ${recordfile} 10 11 cd $gitDir 12 ## 1、去掉隐藏文件, 筛选第9列文件名,然后递归文件上锁 ——》 .git 目录下还是会加锁 13 find $PWD | find . -name "[!.]*" | xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr +ai 14 15 #改良(好像有bug) 16 #find $PWD | find . -name "[!.]*" | grep -v .git |grep -v .gitignore |xargs ls -ld | grep -v total|awk '{print $9}' 17 | xargs chattr +ai 18 19 20 ## 2、去掉.git目录的加锁 21 #cd $gitDir/.git 22 #find $PWD | xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr -ai 23 #cd $gitDir 24 #chattr -ai .git 25 26 echo "############################" >> ${recordfile} 27 echo "" >> ${recordfile} 28 DATE1=`date +%F_%H:%M` 29 echo "结束运行脚本时间为: $DATE1" >> ${recordfile}
敲黑板!!!一开始我是跑这条的,没有放后台跑,直接sh -x /root/scripts/addchattr.sh
find $PWD | find . -name "[!.]*" | xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr +ai
然后就静静地看着git status定时脚本监控的结果,竟然报警了,
核心命令如下:
git status > ${gd_gitstatus} cat ${gd_gitstatus} |grep "nothing to commit" status=`echo $?` if [ $status -ne 0 ]; then curl 报警 fi
原来这个文件为空了,导致误报,而且另一个终端屏开着个top -c 看着服务器负载
负载很高,我都怕了,虽然测试的是网站备用服务器,但却是另外一个项目的正式服务器来的,当时交付过来的机器不太够,所以两个项目就装一块去了。
我马上干掉git status 的脚本,然后停了这个监控,手动测试下。确实一运行git staus服务器负载就飙高,我特意测下究竟跑一轮有返回结果的git status需要多长时间(是的,真的是铤而走险了,别的项目的正式服务器哦)
我印象中git status 没有这么慢的,所以这是第一个谜。说来也奇怪,第二次运行,会快很多。当时我在想是不是.git目录过大导致的,还是因为我对整个.git 目录也上锁导致的。脚本上这条命令是没用的,隐藏目录下的文件照样上锁。
find . -name "[!.]*"
我就想着验证下猜想,给.git 目录解锁重测,实际上有没有对.git目录加锁,只要对静态目录status_ljy 里面的文件加锁了,第一次运行git status 返回的结果都很慢!
然后就有了上面的改良命令
find $PWD | find . -name "[!.]*" | grep -v .git |grep -v .gitignore |xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr +ai
当然旧的那条命令还用的话也行,换成:“2、去掉.git目录的加锁” 就可以了。
###### 2021-05-11
第二个谜,这个真是有点莫名其妙。如果有热心小伙伴知道是什么原因,欢迎交流 ^___^
话说测试git status返回时间的时候,我一直在status_ljy路径下。当时不想开那么多终端屏,所以直接放后台运行脚本加锁:nohup sh /root/scripts/addchattr.sh &
不查不知道,这条命令会在当前目录下产生一个nohup_out 日志文件的。解锁之后就试着删除(不删除的话,git status肯定会报错,防修改测试就无法继续下去了),连root都删除不了!但可以追加,lsattr 查看文件正常,没有ia的上锁标记。
解锁核心命令就两条,无论我运行多少次 chattr -ai nohup.out,然后再rm -rf nohup.out 都会报错“Permission denied”
cd ${gitDir} find $PWD | find . -name "[!.]*" | xargs ls -ld | grep -v total|awk '{print $9}' | xargs chattr -ai
当时我就想最有可能的是git的本地暂存区上,果然:
然后各种查资料,用 git clean 去删除git库中untracked files(未监控)的文件;先git add 再commit,然后git rm -r --cached ;甚至添加到.gitignore隐藏文件,忽略这些untracked files,然后再删。统统都无法解决。
当我绝望之际,就想改个名,叫status_ljy_bad(mv staus_ljy status_ljy_bad),这样我还能重新建个status_ljy,git去初始化,让nginx去代理这个目录,这个后缀bad目录就放着吧。
神奇的事情发生了,进去后发现里面的东西没了,只剩一个html/calc 的目录(初时还以为服务器被入侵,因为打开的文件内容看着比较奇葩),里面有隐藏的 .svn 目录,lsattr .svn 也是看不出带有 ai 标志,但其实都是已经上锁了的,所以需要把每层.svn去ai操作(chattr -ai .svn),然后逐级目录删才行。
细心的读者其实可以看出加锁命令是没有针对 .svn 分类讨论的,当时我也没想过项目里面有隐藏的 .svn,跟开发沟通过,说以前这个系统就是用.svn,也真的发现内网服务器也有,通过gitlab同步到线上的,开发说能删除所有.svn。
至此,算是告一段落了~~~ 这个谜等到时自己知识储备充足再回头看可能会有点眉目,先记下。。。。