磁盘报警
线上磁盘报警,查看磁盘使用率:
[sage.wang@machine /home/www/web/logs]$ sudo df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda2 9.9G 1.5G 8.0G 16% /
tmpfs 3.9G 12K 3.9G 1% /dev/shm
/dev/vda1 194M 54M 131M 29% /boot
/dev/vda6 985M 111M 824M 12% /home
/dev/vda7 60G 45G 13G 78% /home/q
/dev/vda5 4.0G 354M 3.4G 10% /var
登机器查看大文件:
[sage.wang@machine /home/www/web]$ sudo du -sh * |grep G
39G logs
[sage.wang@machine /home/www/web/logs]$ sudo du -sh * |grep G
7.4G access..2018-08-12.log
4.5G cache.log
1.2G catalina.out
8.5G qta.log
由于日志打印不当或者压缩策略设置不当,导致有比较大的日志文件
删除大文件
[sage.wang@machine /home/www/web/logs]$ sudo rm access..2018-08-12.log sudo rm access..2018-08-12.log
删除之后再查看磁盘使用率,其实还是没变:
[sage.wang@machine /home/www/web]$ sudo df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda2 9.9G 1.5G 8.0G 16% /
tmpfs 3.9G 12K 3.9G 1% /dev/shm
/dev/vda1 194M 54M 131M 29% /boot
/dev/vda6 985M 111M 824M 12% /home
/dev/vda7 60G 45G 13G 79% /home/q
/dev/vda5 4.0G 354M 3.4G 10% /var
原因跟Linux下文件的存储机制和存储结构有关:
一个文件在文件系统中的存放分为两个部分:数据部分和指针(inode)部分,指针位于文件系统的meta-data中,数据被删除后,这个指针就从meta-data中清除了,而数据部分存储在磁盘中,数据对应的指针从meta-data中清除后,文件数据部分占用的空间就可以被覆盖并写入新的内容,之所以出现删除access_log文件后,空间还没释放,就是因为tomcat进程还在一直向这个文件写入内容,导致虽然删除了access_log文件,但文件对应的指针部分由于进程锁定,并未从meta-data中清除,而由于指针并未被删除,那么系统内核就认为文件并未被删除,因此通过df命令查询空间并未释放也就不足为奇了。
如何确认这一点呢?可以通过lsof -p pid的方式来查看文件传输的状态:
[sage.wang@machine /home/www/web]$ ps aux|grep java|grep Dcatalina
tomcat 18784 97.9 28.3 7733348 2283632 ? Sl Aug10 3381:52 /home/q/java/default/bin/java -Djava.util.logging.config.file=/home/www/web/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms3537216k -Xmx3537216k -XX:NewSize=1074560k -XX:TargetSurvivorRatio=65 -XX:SurvivorRatio=4 -server -XX:+TieredCompilation -XX:CICompilerCount=3 -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=60 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSScavengeBeforeRemark -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:-UseBiasedLocking -XX:+PreserveFramePointer -XX:+DisableExplicitGC -XX:MaxMetaspaceSize=256m -XX:+TraceClassUnloading -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution -verbose:gc -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintPromotionFailure -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC -XX:+PrintStringTableStatistics -XX:+PrintReferenceGC -XX:+PrintCommandLineFlags -XX:+PrintFlagsFinal -Xloggc:/home/www/web/logs/gc-201808101121.log -Dqunar.logs=/home/www/web/logs -Dqunar.cache=/home/www/web/cache -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -Djava.endorsed.dirs=/home/q/tomcat/endorsed -classpath /home/q/tomcat/bin/bootstrap.jar:/home/q/tomcat/bin/tomcat-juli.jar -Dcatalina.base=/home/www/web -Dcatalina.home=/home/q/tomcat -Djava.io.tmpdir=/home/www/web/temp org.apache.catalina.startup.Bootstrap start
[sage.wang@machine /home/www/web]$ sudo lsof -p 18784|grep deleted
java 18784 tomcat 8w REG 252,7 592867 1835029 /home/www/web/logs/catalina.2018-08-10.log (deleted)
java 18784 tomcat 9w REG 252,7 773 1835037 /home/www/web/logs/localhost.2018-08-10.log (deleted)
当linux打开一个文件的时候,Linux内核会为每个进程在/proc/ 『/proc/nnnn/fd/文件夹(nnnn为pid)』建立一个以其pid为名的文件夹用来保存进程的相关信息,而其子文件夹fd保存的是该进程打开的全部文件的fd(fd:file descriptor)。
进去看一下内容:
[sage.wang@machine /home/www/web]$ sudo ls -alh /proc/18784/fd/ |grep deleted
l-wx------ 1 tomcat tomcat 64 Aug 12 20:54 8 -> /home/www/web/logs/catalina.2018-08-10.log (deleted)
l-wx------ 1 tomcat tomcat 64 Aug 12 20:54 9 -> /home/www/web/logs/localhost.2018-08-10.log (deleted)
可以看到,这是被删除的文件,但实际上磁盘空间还是没有释放的
正确姿势
那么到底应该用什么姿势来解决问题呢?两种方式:
- 重启应用,即可释放相应的空间
- 在线清空这个文件的内容
重启应用很简单,若要在线清空文件,则不要使用rm命令,而是使用如下命令
cat /dev/null > file
#或者
echo > file
#或者
echo ' ' > file
再强调一遍,删除正在写的文件一般用 cat /dev/null > file或者echo > file,而不是直接rm(直接rm会造成文件删除空间不释放的问题)。
线上机器执行的时候会有权限的问题,比如:
[n-sage.wang@machine /home/www/web/logs]$ sudo echo > catalina.out
bash: catalina.out: Permission denied
这是因为重定向符号 “>” 也是 bash 的命令。sudo 只是让 echo 命令具有了 root 权限,但是没有让 “>” 命令也具有root 权限,所以 bash 会认为这个命令没有写入信息的权限。
解决方案有两种
当做一条命令执行:
sudo bash -c 'echo "hello" > f.txt'
或者使用tee命令:
echo "hello" | sudo tee f.txt # add -a for append (>>)
实测第一条命令还是会有点问题,也是没权限。但是第二种方式是work的。
参考文章:
https://blog.csdn.net/wangyage198801151103/article/details/51723759
https://www.cnblogs.com/mfryf/p/3334451.html
https://www.jb51.net/article/100462.htm
https://blog.csdn.net/tianyao_myc/article/details/52179668
http://blog.163.com/aprilthirty60@126/blog/static/88613578201282703952163/
https://blog.csdn.net/hejinjing_tom_com/article/details/7767127
https://askubuntu.com/questions/103643/cannot-echo-hello-x-txt-even-with-sudo