最近看了一下问题:

  1. df -h
  2. Filesystem Size Used Avail Use% Mounted on
  3. rootfs 271G 267G 2.2G 100% /

根分区满了,du 找不到占用这么大的文件。lsof查看delete文件,发现了罪魁祸首,

  1. lsof |grep -i delete |grep -i zxagent
  2. sleep 4500 root 2w REG 8,2 1459 7399418 /tmp/.zxagent.command.output.-218666128 (deleted)
  3. sleep 6081 root 2w REG 8,2 202907880341 7399434 /tmp/.zxagent.command.output.-218666128 (deleted)
  4. chk_usr_m 23846 root 2w REG 8,2 202907880341 7399434 /tmp/.zxagent.command.output.-218666128 (deleted)
  5. netif_inf 23871 root 2w REG 8,2 202907880341 7399434 /tmp/.zxagent.command.output.-218666128 (deleted)
  6. sleep 25497 root 2w REG 8,2 202907880341 7399434 /tmp/.zxagent.command.output.-218666128 (deleted)----200G
  7. sh 30440 root 2w REG 8,2 1459 7399418 /tmp/.zxagent.command.output.-218666128 (deleted)
  8. uss_jbodm 31946 root 2w REG 8,2 1459 7399418 /tmp/.zxagent.command.output.-218666128 (deleted)

这个200G,不一定多落盘了,但根据周期性落盘来推算,这个占空间大肯定是没跑了,查看对应的fd,

  1. ls -alrt /proc/23846/fd/*
  2. lrwx------ 1 root root 64 Apr 30 19:20 /proc/23846/fd/4 -> socket:[451533622]
  3. lr-x------ 1 root root 64 Apr 30 19:20 /proc/23846/fd/255 -> /home/zxcdn/ottcache/bin/chk_usr_mem.sh
  4. l-wx------ 1 root root 64 Apr 30 19:20 /proc/23846/fd/2 -> /tmp/.zxagent.command.output.-218666128 (deleted)
  5. l-wx------ 1 root root 64 Apr 30 19:20 /proc/23846/fd/1 -> /dev/null
  6. lr-x------ 1 root root 64 Apr 30 19:20 /proc/23846/fd/0 -> /dev/null

对应的fd是2,查看一下里面什么内容:

  1. more /proc/23846/fd/2
  2. chmod 777 start.sh
  3. ./start.sh
  4. dos2unix: converting file /home/iTool/UPDATE_20190415164111/2/update/start_ott.sh to UNIX format ...
  5. dos2unix: converting file /home/iTool/UPDATE_20190415164111/2/update/start.sh to UNIX format ...
  6. dos2unix: converting file /home/iTool/UPDATE_20190415164111/2/update/start_zmss.sh to UNIX format ...
  7. ###start /home/zxcdn/ottcache/superinit.sh &#################
  8. Add execute right to script...

看起来是一些错误日志。

  1. tail -f /proc/23846/fd/2
  2. 2019-05-05 18:06:54 Watching proccess[/ZMSS/ZMSSComAgent]<3622> was abnormal exited, restart it.
  3. 2019-05-05 18:06:54 Proccess [/ZMSS/ZMSSComAgent]<3623> normal exiting, exit code[1]
  4. 2019-05-05 18:06:54 Watching proccess[/ZMSS/ZMSSComAgent]<3623> was abnormal exited, restart it.
  5. 2019-05-05 18Could not read configuration file [/ZMSS/etc/ZMSSComAgent/etc_memlog/log4cxx.conf].
  6. Ignoring configuration file [/ZMSS/etc/ZMSSComAgent/etc_memlog/log4cxx.conf].
  7. Use uss_badchunkget.
  8. Use uss_tiermode_query.
  9. Use DFS File System Interface.
  10. log4cxx_SetThreshold <3><ERROR>
  11. Cannot change owner of /var/ZMSS to root:root, err<-1>!

从时间点看,案发当时还在打印错误日志。

如果只是这么看,那么就不记录这个问题了。问题是,我脑抽地想通过内核模块查看这个文件,会报错。

如果使用vmtouch去查看这个文件占用内存的大小,会发现报错,报文件不存在,所以写了一个内核模块去查看它的缓存页数:

  1. 21081455 /tmp/.zxagent.command.output.-218666128

结果显示,这个文件有21081455 个页缓存在内存中,这个大概是84个G,文件本身大小为200G,所以是部分缓存了,

那如果不通过fd查看,怎么查看这个文件的内容呢,要查看这个内容,内核中通过如下方式来读取和写文件:

  1. 打开文件
  2.  
  3. struct file *filp_open(const char *filename, int flags, int mode)
  4.  
  5. 读文件
  6.  
  7. ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
  8.  
  9. 写文件
  10.  
  11. ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
  12.  
  13. 关闭文件
  14.  
  15. int filp_close(struct file *filp, fl_owner_t id)

但要注意的是,需要

  1. file_caq = filp_open("/tmp/.zxagent.command.output.1246", O_RDWR | O_CREAT | O_TRUNC, 0644);
  2. if ( !file )
  3. {
  4. printk("file open(%s) failed!\n", "/tmp/.zxagent.command.output.1246");
  5. filp_close(file, NULL);
  6. return -1;
  7. }
  8. else
  9. {
  10. printk("open /tmp/.zxagent.command.output.1246 success\r\n");
  11. }
  12.  
  13. ret = file_caq->f_op->read(file, (char *)buf, 512, &pos);
  14. printk("read /tmp/.zxagent.command.output.1246 ret=%d,read=%p\r\n",ret,file_caq->f_op->aio_read);

打印如下:

  1. [12833325.784972] pages_total = 21081455(82349M),HZ=250
  2. [12833325.785019] open /tmp/.zxagent.command.output.1246 success
  3. [12833325.785022] read /tmp/.zxagent.command.output.1246 ret=-14,read=ffffffff810fd420

看来是read失败了,这个主要是因为权限检查,然后修改为如下:

  1. old_fs = get_fs();
  2. set_fs(KERNEL_DS);
  3. ret = vfs_read(file_caq, (char *)buf_caq, 511, &pos);
  4. set_fs(old_fs);

发现不再报错,但是读取的数据为空,也就是read返回0。

然后再手工ls一下这个文件,发现确实创建了一个新的文件,为空,文件名是 /tmp/.zxagent.command.output.1246,当然inode号和之前delete 的文件名不一样。

那就把 对应文件的打开的时候的O_CREAT给去掉,干脆全部改成O_READONLY

  1. file_caq = filp_open("/tmp/.zxagent.command.output.1246", O_RDWR | O_CREAT | O_TRUNC, 0644);
  2.  
  3. 这行修改为
  4. file_caq = filp_open("/tmp/.zxagent.command.output.1246", O_RDONLY, 0644);

结果crash了,打印的crash提示为:

  1. BUG: unable to handle kernel NULL pointer dereference at 0000000000000026

经过反汇编查看,发现因为file_caq虽然不为NULL,但是返回的是-2,所以导致 :

  1. if ( !file )这个判断失效了,导致打印了open success
  1. ret = file_caq->f_op->read(file, (char *)buf, 512, &pos);

这行出现crash了,因为 file_caq的值为-2,加上f_op是偏移,一开始为了这个26的偏移还看了一会,后来才想通是因为-2 + 0x28 才等于0x26。

所以把NULL的判断改为 if (IS_ERR(file_caq)),再进行测试,发现文件打开失败,返回的错误是-2.

那么返回-2就是说,文件不存在,因为我去掉了create标志,自然报错了。所以标记为delete的文件,如果使用file_open去打开也是不行的,会报文件不存在的。

那么要获取这个文件,只能在内核态从inode入手,找到对应的address_space,然后再把radix_tree中的page 拷贝出来了,此为后话。

绕了半圈,费了劲,没什么收获。不过顺便确定了下lsof看到的deleted,并不是lsof实现的,而是内核在打印

path_with_deleted 的时候,append进去的,判断标准就是对应path的dentry是否被hashed。
  1. 2 ffff882b9020ad00 ffff882cd153f680 ffff882f79b0f5f0 CHR /dev/pts/26
  2. 3 ffff8859f47ac700 ffff885f79a69380 ffff882dee933d48 REG /home/caq/caq.txt-----------这个是测试用的deleted的文件
  3. crash> dentry.d_hash ffff885f79a69380
  4. d_hash = {
  5. next = 0x0,
  6. pprev = 0x0
  7. }
  8. crash> dentry.d_hash ffff882cd153f680
  9. d_hash = {
  10. next = 0x0,
  11. pprev = 0xffffc9000ff81f60
  12. }

判断方式:

  1. static inline int hlist_bl_unhashed(const struct hlist_bl_node *h)
  2. {
  3. return !h->pprev;
  4. }
  5.  
  6. static inline int d_unhashed(struct dentry *dentry)
  7. {
  8. return hlist_bl_unhashed(&dentry->d_hash);
  9. }
  10.  
  11. static int path_with_deleted(const struct path *path,
  12. const struct path *root,
  13. char **buf, int *buflen)
  14. {
  15. prepend(buf, buflen, "\0", 1);
  16. if (d_unlinked(path->dentry)) {------判断是否增加deleted
  17. int error = prepend(buf, buflen, " (deleted)", 10);
  18. if (error)
  19. return error;
  20. }

df空间满,du找不到文件的问题的更多相关文章

  1. du 命令,对文件和目录磁盘使用的空间的查看

    Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 1.命令格式: du [选项][文件] 2.命令功能 ...

  2. 诡异的磁盘空间100%报警分析得出df -h与du -sh的根本性差别

    前言:早晨磁盘报警刚清空完tomcat和nginx日志,使用的命令是类似echo "" > show_web-error.log或者> show_web-debug.l ...

  3. ORA-03113 通信通道的文件结尾(ORA-19804 ORA-16038-归档空间满的处理方法)

    1.数据库启动报错SQL> startupORACLE 例程已经启动. Total System Global Area 1887350784 bytesFixed Size 2176848 b ...

  4. No space left on device 解决Linux系统磁盘空间满的办法

    最近Linux电脑在执行mvn时候总是报错: No space left on device   原因是磁盘空间满了,我马上加了20G的硬盘容量,但是还是报错,上网查了一下,发现了解决方法,我用了其中 ...

  5. linux磁盘空间满的处理

    Java中运行SQL插入数据时报错: linux磁盘空间满处理: 1.df -h  查看磁盘空间占用,实际上是查看磁盘块占用的文件(block) 2.分别查看输入以下命令 (面对磁盘满了,通过下列命令 ...

  6. 云服务器 ECS Linux 磁盘空间满(含 innode 满)问题排查方法

    问题描述 在云服务器 ECS Linux 系统内创建文件时,出现类似如下空间不足提示: No space left on device … 问题原因 导致该问题的可能原因包括: 磁盘分区空间使用率达到 ...

  7. df命令,du命令,磁盘分区

    df 命令 功能:用来检查linux的文件系统的磁盘空间占用情况 1. df -h 2. 以innode节点数量显示磁盘空间占用情况 df -ih 3. 列出文件系统类型 df -Th du 命令 功 ...

  8. 呵呵哒,LNMP下通过fread方式下载文件时,中文名称文件找不到文件

    哎,整整折腾一个下午. 本来好好的,thinkphp 自动的uniq方式保存的文件名,非要使用原文件名,真心蛋疼~~ 然后就只好写个脚本 把原来的所有文件都重新命名一下 - - 然后把数据库对应字段也 ...

  9. linux磁盘空间满?

    磁盘空间满啦 找到项目的logs文件夹 进入logs文件夹,会看到很多access.log*文件. 在Xshell里,输入命令cd 到项目节点的logs文件夹 可能还需要清空下回收站.

随机推荐

  1. Java_选择结构

    if单选择结构 if(布拉尔表达式){ //如果布拉尔表达式为true将执行的语句 } if双选择结构 if(布拉尔表达式){ //如果布拉尔表达式的值为true }else{ //如果布拉尔表达式的 ...

  2. Dubbo3 源码系列 Dubbo“纠葛”(入门篇)

    日期 更新说明 2022年5月28日 spring xml部分解读 2022年6月3日 spring annotation部分解读 人生不相见, 动如参与商. 今夕复何夕, 共此灯烛光. 少壮能几时, ...

  3. Java内存分析——JavaSE基础

    内存分析 堆:存放new的对象和数组,可以被所有线程共享,不会存放别的对象引用 栈 存放基本变量类型(会包含这个基本类型的具体数值) 引用对象的变量(会存放这个引用在堆里的具体地址) 方法区(属于堆的 ...

  4. 《C Primer Plus》第六版笔记--1~3章

    目录 第一章 初识C语言 1 使用C语言的7个步骤 1.1 定义程序目标 1.2 设计程序(功能实现) 1.3 编写代码 1.4 编译 1.5 运行程序 1.6 测试和调试程序 1.7 维护和修改代码 ...

  5. .NET C#基础(2):方法修饰符 - 给方法叠buff

    0. 文章目的   本文面向有一定.NET C#基础知识的学习者,介绍C#中的方法修饰符的含义和使用以及注意事项.   1. 阅读基础   理解C#基本语法(如方法声明)   理解OOP基本概念(如多 ...

  6. VSCode 安装以及初步使用教程

    老样子先介绍一下VSCode(是什么?干什么?有什么用?好处是什么?等) VisualStudioCode(简称VSCode)是Microsoft开发的代码编辑器,它支持Windows,Linux和m ...

  7. np.r_、np.c_、np.concatenate和np.append

    np.r_是按行连接两个矩阵,就是把两矩阵上下相加,要求列数相等,最终结果的行数为两个矩阵行数和. np.c_是按列连接两个矩阵,就是把两矩阵左右相加,要求行数相等,最终结果的列数等于两矩阵的列数和. ...

  8. Keytool配置 Tomcat的HTTPS双向认证

    Keytool配置 Tomcat的HTTPS双向认证 证书生成 keytool 简介 Keytool是一个Java数据证书的管理工具, Keytool将密钥(key)和证书(certificates) ...

  9. 使用 content-visibility 优化渲染性能

    最近在业务中实际使用 content-visibility 进了一些渲染性能的优化. 这是一个比较新且有强大功能的属性.本文将带领大家深入理解一番. 何为 content-visibility? co ...

  10. Caller 服务调用 - Dapr

    前言 上一篇我们讲了使用HttpClient的方式调用,那么如果我们现在需要更换为通过dapr实现服务调用,我们需要做哪些事情呢? Caller.Dapr 入门 如果我们的项目原本使用的是Caller ...