1. 程式人生 > >Linux伺服器出現:No space left on device的解決方法

Linux伺服器出現:No space left on device的解決方法

 

 

報錯資訊:

2016-06-02 23:56:26 [com.thinkive.server.logger.TradeLogger]-[ERROR]

java.io.IOException: No space left on device

at java.io.FileOutputStream.writeBytes(Native Method)

at java.io.FileOutputStream.write(FileOutputStream.java:282)

at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)

at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)

at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)

at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)

at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)

at com.thinkive.server.logger.TradeLogger$LoggerThread.flushLogFile(TradeLogger.java:404)

at com.thinkive.server.logger.TradeLogger$LoggerThread.run(TradeLogger.java:322)

 

伺服器磁碟不足,df -h 一下,var下正常,還有剩餘,發現問題沒有,到後來顯示大量的No space left on device:

/var明明還有很大的空間,為什麼就提示“沒有足夠的空間”了呢?結果用到了df -i命令檢視磁碟的節點發現如下圖:

節點100%了.

這個時候使用者可以先看下日誌檔案是否太多,如果是日誌檔案佔用大量的inodes可以臨時釋放清理下過期的日誌。

以下是檢查inodes滿的某一種情況,僅供參考:

檢視原來是crontab裡面定時執行的句子裡沒有加 > /dev/null 2>&1,系統中cron執行的程式有輸出內容,輸出內容會以郵件形式發給cron的使用者,而sendmail沒有啟動所以就產生了很大零碎的檔案:

 

cd /var/spool/clientmqueue/  進入這個目錄,刪掉這些沒用的檔案,用ls 檢視一下,結果是沒有反應,檔案太多,於是就用到了這個命令:ls |xargs rm -rf 可以分批的處理刪除檔案

操作到該步驟,可以根據較大目錄的檔案佔用情況,臨時轉移部分檔案到佔用磁碟較小的目錄中。

 

 

最近這兩天登陸伺服器,發現用 wget 下載檔案的時候提示“No space left on device”,而且連使用 tab 鍵進行補全時也會提示該錯誤。

之前遇到過一次這種問題,是由於磁碟空間被佔滿了,導致無法建立新檔案。正常情況下,刪除一些檔案來釋放空間,即可解決該問題。

當我使用 df 命令檢視分割槽情況時,結果如下:

?

1

2

3

4

5

6

7

# df -h

Filesystem Size Used Avail Use% Mounted on

/dev/vda1 29G 29G 0 100% /

udev  10M 0 10M 0% /dev

tmpfs  101M 232K 100M 1% /run

tmpfs  5.0M 0 5.0M 0% /run/lock

tmpfs  405M 0 405M 0% /run/shm

看到這裡,我以為磁碟真的被 100% 佔用了,於是就查看了各目錄的佔用情況:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

# du -sh /*

8.8M /bin

30M /boot

0 /dev

5.3M /etc

24K /home

0 /initrd.img

205M /lib

4.0K /lib64

16K /lost+found

8.0K /media

4.0K /mnt

4.0K /opt

0 /proc

2.5G /root

232K /run

5.2M /sbin

8.0K /srv

0 /sys

4.0K /tmp

2.6G /usr

1.8G /var

0 /vmlinuz

很明顯,總共的磁碟佔用完全不到 10G,磁碟理論上並未被佔滿。

這種情況下,很可能是小檔案過多,導致 inode 急劇增加,消耗完 inode 區域的空間。

如果真是如此,那麼即使磁碟空間有剩餘,但由於無法建立新的 inode 來儲存檔案的元資訊,也就無法建立新檔案。

因此,我用 df 命令進行驗證:

?

1

2

3

4

5

6

7

# df -ih

Filesystem Inodes IUsed IFree IUse% Mounted on

/dev/vda1 1.9M 299K 1.6M 17% /

udev  123K 299 123K 1% /dev

tmpfs  126K 249 125K 1% /run

tmpfs  126K 4 126K 1% /run/lock

tmpfs  126K 2 126K 1% /run/shm

可以看到,inode 區域只被佔用了一小部分,還有大量的空間未使用,所以也不是 inode 區域被佔滿的問題。

到了這裡,我的內心是非常鬱悶的。這個問題直接導致了Apache、MySql以及其它的一些服務均無法啟動,伺服器已經基本沒法使用了,然而原因卻撲朔迷離。

最後,伺服器提供商告訴我另一種可能的情況,就是有些檔案刪除時還被其它程序佔用,此時檔案並未真正刪除,只是標記為 deleted,只有程序結束後才會將檔案真正從磁碟中清除。

於是我通過 lsop 命令查看了被程序佔用中的檔案:

?

1

2

3

4

5

6

7

8

# lsof | grep deleted

mysqld 1952 2982 mysql 5u REG  254,1  0 127 /tmp/ibzMEe4z (deleted)

mysqld 1952 2982 mysql 6u REG  254,1  0 146 /tmp/ibq6ZFge (deleted)

mysqld 1952 2982 mysql 10u REG  254,1  0 150 /tmp/ibyNHH8y (deleted)

apache2 2869  root 9u REG  254,1  0 168 /tmp/.ZendSem.2w14iv (deleted)

apache2 2869  root 10w REG  0,16  0 11077 /run/lock/apache2/rewrite-map.2869 (deleted)

...

python 3102  root 1w REG  254,1 22412342132 264070 /var/log/nohup.out (deleted)

終於找到了罪魁禍首,原來是在後臺執行的 Python 指令碼,源源不斷地將輸出儲存到 /var/log/nohup.out 檔案中,檔案大小居然達到了20G+!

前階段在後臺執行指令碼之後,就沒再管過它。估計是我在 Python 執行過程中刪掉了 nothup.out 檔案,由於該檔案被佔用,所以只能先標記為 deleted,而未真正刪除,最後導致磁碟爆滿。

這次的教訓提醒了我,不能將任務簡單放到後臺就放任不管,特別是使用 nohup 命令時,所有的輸出都會被不斷地新增到同一個檔案中,如果該程序不會自己終止,就可能導致輸出檔案佔滿整個磁碟。