Linux系统提示"No space left on device"解决方法
在Linux环境上创建、拷贝文件或者vi编辑文件保存时经常会遇到系统提示"No space left on device"提示空间不足的问题。这种问题通常是由于磁盘空间不足或者inodes节点不足导致。解决办法也很简单就是删除不需要的文件进行磁盘空间或者inode节点释放。本文主要描述出现该问题时的分析方法和删除文件方法,包括:
(1)"No space left on device"问题分析,通过df -h查看是否磁盘空间不足,df -i查看是否inode节点不足。
(2)如何快速查找磁盘空间不足对应文件系统中的超大文件并进行删除。
(3)介绍使用find指令或者脚本快速删除无用文件。
问题现象
在创建文件或者vi编辑保存文件时linux系统提示"No space left on device"。
问题分析
出现"No space left on device"提示信息导致操作失败的原因通常有3种:
(1)文件系统中文件占用空间总量即将或超过100%。通过df -h可以查看是否有文件系统空间使用率快达到100%或已达到100%。
(2)文件已经删除但是存在占用文件的进程导致空间未释放。可以通过df和lsof指令查看。df查看文件系统空间充足,lsof查看存在已删除文件占用的进程。
(3)inodes节点不足导致。这种情况通常是系统上有非常多的单个文件占用空间很小但是数量很多导致。常见于linux服务器上安装有oracle数据库的场景。oracle数据库会生成很多的日志文件。
问题解决
(1)文件系统中文件占用空间总量即将或超过100%问题解决
Step1、利用df命令确定将磁盘空间即将耗尽的文件系统对应的目录。
linux~ # df
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/sda2 146294492 28244432 110498708 21% /
/dev/sda1 1019208 62360 904240 7% /boot
tmpfs 1032204 0 1032204 0% /dev/shm
/dev/sdb1 2884284108 2884284108 0 100% /home
根据上述结果可知,/dev/sdb1磁盘空间即将达到100%,对应的挂载点为/home目录。进入/home目录进行查找删除操作即可 。
Step2、利用du命令逐级查找占用磁盘空间较大的文件或者文件夹。
linux~ # du -sm /home
Step3、删除查找到的无用的安装包、备份包文件或者长期未清理的debug日志。如果查找确认之后发现并无占用较大空间的文件,需确认该文件系统挂载点/home目录下是否已被使用并且存在占用空间较大的文件。使用umout /home卸载挂载点查看。具体查找删除文件方法可以查看FAQ。
Step4、重新执行df命令查看/dev/sdb1磁盘空间使用率是否降低。如果磁盘空间释放大小与已删除文件大小不一致,参考"df与du显示磁盘空间不一致问题解决"
2、df与du显示磁盘空间不一致问题解决
使用df命令查看文件系统空(/home)间不足,删除大文件后执行df重新查看,文件系统空间却并未增加。可能是删除文件时仍有进程在使用,删除时只是对删除文件做deleted标记并未真正释放。空间未释放。
分析解决方法如下:
Step1、du -sm /home查看对应文件系统文件占用大小。发现文件占用空间远远小于df查看占用的空间。
Step2、使用lsof指令查看被标记deleted但未真正释放的文件
linux~ # lsof /home | grep 'deleted'
或者
linux~ # ls -ald /proc/*/fd/* | grep 'deleted' | grep -v 'pts'
根据上述结果发现确实有进程占用刚删除的大文件。
Step3、kill掉占用删除文件的进程
linux~ # lsof /home | grep 'deleted' | grep -v grep | awk '{print $2}' | sort|xargs kill -9
或者手工获取占用文件的进程ID,执行kill -9 ${ID}
Step4、重新执行df查看,问题解决。
3、df -i显示inodes使用率即将100%
Step1、df -i查看inodes使用率即将达到100%。获取对应的文件系统挂载目录。如/home
Step2、使用find命令查找文件,删除不需要使用的文件。通常为业务日志文件、oracle数据库日志文件、审计文件等等。大文件很少会出现这种情况,因为有大量大文件的话,首先应该是会把磁盘空间占满。具体查找删除文件方法可以参考FAQ。
Step3、删除文件,重新执行df -i查看,问题解决。
4、FAQs
1、如何实现自动删除服务器垃圾文件?
需求描述
(1)假设业务运行产生的日志文件生成路径位于$HOME/log目录下,文件名为'用户名_[debug|run|warn].log'或者'用户名_[debug|run|warn].log.n',n为数字,常为备份名。
(2)假设业务运行产生的临时文件生成路径位于$HOME/temp目录,文件名为'用户名_[debug|run|warn].tmp'或者'用户名_[debug|run|warn].tmp.n',n为数字,常为备份名。
(3)查找Linux服务器超过指定大小(如100M)的安装包、备份包文件,供用户人工判断是否可以删除。
(4)不能误删系统文件,特别是oracle用户的重做日志文件(redoN.log)。
代码实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/bin/bash #******************************************************** #*** Author : lion #*** Create Date : 2017/09/18 #*** Modify Date : NA #*** Function : Delete the server logs and temp files #******************************************************** function Usage() { echo "NAME" echo " clearlogs.sh" echo "SYNOPSIS" echo " clearlogs.sh" echo "DESCRIPTION" echo " clear the server logs and temp files" exit 0 } function writelog() { local logfile=$1 local debug_level=$2 local messages=$3 echo "[$(date '+%Y-%m-%d %H:%M:%S')] [${debug_level}] ${messages}" echo "[$(date '+%Y-%m-%d %H:%M:%S')] [${debug_level}] ${messages}" >> ${logfile} } function find_logs() { local user=$1 local user_home=$2 if [ -d ${user_home}/log ];then find ${user_home}/log -maxdepth 2 -type f -name "${user}*.log*" -mtime +${KEEP_DAYS} -print >> "${DELETE_LOGS_LIST}" fi if [ -d ${user_home}/temp ];then find ${user_home}/temp -maxdepth 2 -type f -name "${user}*.tmp*" -mtime +${KEEP_DAYS} -print >> "${DELETE_LOGS_LIST}" fi } if [ "X$1" == "X--help" ];then Usage fi if [ $(whoami) != 'root' ];then printf "Please use root to execute\n" exit 1 fi ##global Var CURRENT_PATH=$(pwd) CURRENT_DATE=$(date '+%Y%m%d') SCRIPT_NAME="clearlogs" CLEARLOGS_DIR="${CURRENT_PATH}/${SCRIPT_NAME}_${CURRENT_DATE}" SEARCH_FILE_SIZE='100M' LOG_FILE="${CLEARLOGS_DIR}/${SCRIPT_NAME}.log" DELETE_LOGS_LIST="${CLEARLOGS_DIR}/${SCRIPT_NAME}_delete_files.log" USER_LIST="${CLEARLOGS_DIR}/user.lst" BIG_FILES_LIST="${CLEARLOGS_DIR}/${SCRIPT_NAME}_bigfile.lst" KEEP_DAYS=3 if [ ! -d ${CLEARLOGS_DIR} ];then mkdir ${CLEARLOGS_DIR} fi rm "${DELETE_LOGS_LIST}" "${USER_LIST}" "${BIG_FILES_LIST}" &> /dev/null touch "${DELETE_LOGS_LIST}" "${USER_LIST}" "${BIG_FILES_LIST}" awk -F':' '{if($0 !~ /var/)print $1,$6}' /etc/passwd > "${USER_LIST}" writelog "${LOG_FILE}" "INFO" "Begin find logs and temp files,wait a moment....." while read user user_home do find_logs ${user} ${user_home} & done < "${USER_LIST}" wait writelog "${LOG_FILE}" "INFO" "End find logs and temp files" writelog "${LOG_FILE}" "INFO" "Begin delete logs and temp files at ${DELETE_LOGS_LIST}" while read line do if [ -f ${line} ];then rm ${line} &> /dev/null if [ $? -eq 0 ];then writelog "${LOG_FILE}" "INFO" "File[ ${line} ] delete success" else writelog "${LOG_FILE}" "INFO" "File[ ${line} ] delete failed" fi fi done < "${DELETE_LOGS_LIST}" writelog "${LOG_FILE}" "INFO" "End delete logs and temp files at ${DELETE_LOGS_LIST}" writelog "${LOG_FILE}" "INFO" "Begin find larger than ${SEARCH_FILE_SIZE} files,wait a moment....." find / \( -path '/proc' -o -path '/var' \) -prune -o -type f -size "+${SEARCH_FILE_SIZE}" -print > "${BIG_FILES_LIST}" writelog "${LOG_FILE}" "INFO" "End find larger than ${SEARCH_FILE_SIZE} files" writelog "${LOG_FILE}" "INFO" "The files at [ ${BIG_FILES_LIST} ] are larger than ${SEARCH_FILE_SIZE},please check and delete by manual"
使用方法
(1)上述代码已上传至github,下载路径:clearlogs.sh,上传到root用户目录下,任意目录。
(2)执行chmod +x clearlogs.sh赋可执行权限。
(3)执行./clearlogs.sh。查看相关日志即可。
说明:1、脚本可以根据实际情况进行修改以适用当前产品;2、脚本多次运行测试正常后可配置定时任务进行定期清理删除。
2、Linux下如何快速查找占磁盘空间大的文件
需求背景
清理服务器文件系统空间时经常需要查找大文件以进行分析删除,从而释放空间。
设计思路
快速查找服务器上所有超过指定大小的文件并显示。第一列显示文件大小,第二列显示文件绝对路径。通常可以直接如下命令进行查找:
find / -type f -size +100M -print
考虑加快查找速度,分成多个目录在后台并发查找并显示。获取目录方法如下
find / -maxdepth 2 \( -path '/proc' -o -path '/var' \) -prune -o -type d -print | grep '^/.*/'
假设文件名为linux.tar.gz,第一列显示文件大小,第二列显示文件路径如下:
awk -v filename="linux.tar.gz" -v filesize=$(stat -c %s "linux.tar.gz" ) 'BEGIN{print filesize/1024/1024"M",filename}'
代码实现
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#!/bin/bash SEARCH_DIR_LIST="search_directory.txt" SEARCH_TEMP_FILES="search_temp_files.txt" SEARCH_FILES="search_files.txt" file_size="100M" if [ $(whoami) != 'root' ];then printf "Please Use root to execute\n" exit 1 fi rm "${SEARCH_DIR_LIST}" "${SEARCH_TEMP_FILES}" "${SEARCH_FILES}" &> /dev/null find / -maxdepth 2 \( -path '/proc' -o -path '/var' \) -prune -o -type d -print | grep '^/.*/'> "${SEARCH_DIR_LIST}" printf "Begin search larger than ${file_size}M files,wait a moment....\n" while read line do ( find ${line} -type f -size +${file_size} -print >> "${SEARCH_TEMP_FILES}" ) & done < "${SEARCH_DIR_LIST}" wait printf "End search larger than ${file_size}M files.\n" printf "Begin Compute each files detail size,please wait...\n" while read line do awk -v filename=${line} -v filesize=$(stat -c %s ${line}) 'BEGIN{print filesize/1024/1024"M",filename}' >> ${SEARCH_FILES} done < "${SEARCH_TEMP_FILES}" wait printf "End Compute each files detail size.\n" printf "Please Check below files..\n" cat ${SEARCH_FILES} | sort -rn rm "${SEARCH_DIR_LIST}" "${SEARCH_TEMP_FILES}" printf "Script execute end!\n"