cannot create temp file for here-document: No space left on device

Đây là lỗi trên linux system khi hết dung lượng hoặc Inode. Trong bài viết này, ta tìm hiểu xem PHP có vấn đề gì với Inode và cách giải quyết nhé.

1. Inode là gì?

Inode là viết tắt của Index Node. Trong cấu trúc dữ liệu của Unix-style file system, Inode đại diện cho một file-system object như là thư mục hay file.

Trên lý thuyết thì ext4 file system có thể chứa đến 4 tỷ Inodes và không giới hạn số lượng thư mục con. Nhưng trên thực tế, để hệ thống có thể hoạt động ổn định và ít lỗi thì con số này đã bị giới hạn. Bạn nào dùng hosting unlimited space như của Hostgator hay Godaddy sẽ thấy “thân quen” bởi họ tuy không giới hạn dung lượng nhưng lại giới hạn số lượng node.

PHP session và Inode 2

Giới hạn Inode trên Hostgator

Tuy vậy số lượng Inode vẫn quá dư giả để xài với một web server bình thường. Cho nên khi hệ thống hết Inode thì 99% đó là lỗi và cần phải được fix/tối ưu.

2. Tại sao các site PHP có vấn đề với Inode?

Các site PHP bao gồm cả WordPress có cơ chế ghi session file vào trong thư mục temp. Các hệ thống thống lớn thì không ghi vào file mà dùng Memcached, Shared Memory và Redis. Ta có thể hiểu là mỗi khi có session mới thì nó sẽ tạo file/record tùy vào cấu hình. Khi session này expired thì file/record đó sẽ được xóa đi. Ngoài ra, thư mục temp còn được dùng để lưu tạm thời những file được upload/giải nén.

Thư mục lưu trữ session của PHP thường là /tmp hoặc /home/username/tmp tùy cấu hình. Nếu hệ thống hoạt động bình thường thì bạn chẳng cần phải lo gì cả, những file tạm này sẽ được xóa tự động bởi cronjob nằm trong /etc/cron.d/. Còn trường hợp bất thường tôi sẽ nói tiếp ở phần dưới ?

3. Kiểm tra vấn đề

Bây giờ giả định chúng ta đang gặp lỗi “No space left on device”, các “triệu chứng” của bệnh này là website không upload được file, session thì chập chờn, SSH vào server thì không TAB được vì mỗi lần nhấn sẽ báo lỗi.

Giờ ta SSH vào server và thực hiện lần lượt các bước sau:

1. Kiểm tra dung lượng

$ df -h
PHP session và Inode 3

Kết quả của lệnh df -h

Ta chỉ chú ý đến dòng được Mounted vào / thôi nhé. Trong kết quả trên thì mới dùng hết 47% nên ta sang bước tiếp theo. Trường hợp bị full dung lượng do content thì ta phải nâng cấp ổ đĩa. Chú ý có trường hợp file log không được rotate đúng cách nên lên đến vài chục GB.

2. Kiểm tra IUsed

$ df -i
PHP session và Inode 4

Kết quả của lệnh df -i

Ở đây tuy kết quả là 15% nhưng ta cứ giả dụ nó là 100% nhé ?

3. Kiểm tra vùng nào đang chiếm phần lớn Inode:

Để kiểm tra thư mục nào đang xài bao nhiêu Inode ta dùng lệnh sau:

$ find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n

Lệnh trên hiển thị IUsed của từng thư mục và sắp xếp theo thứ tự tăng dần. Có nghĩa là dòng cuối cùng của kết quả chính là thư mục con đang chiếm nhiều Inode nhất:

PHP session và Inode 5

Trên máy tôi thì Google Chrome cache đang chiếm nhiều Node nhất

Dựa vào kết quả trên ta dùng kinh nghiệm để phán đoán xem vấn đề đến từ đâu.

4. Khắc phục vấn đề

1. Khắc phục tạm thời

Nhanh nhất là xóa thư mục đó luôn ?

// thay /target/dir bằng thư mục của bạn
$ rm -rf /target/dir

⚠ Chú ý: Bạn phải biết mình đang làm gì, nếu không chắc thì đừng xóa bất cứ thứ gì trên server. Bản thân administrator phải biết thư mục nào được xóa và thư mục nào không. Dưới đây là một số thư mục thường gặp:

  • /tmp – không nên xóa, vì nó chứa temp file của toàn bộ hệ thống. Trong trường hợp này ta nên khởi động lại server vì nó sẽ tự clean thư mục.
  • /home/username/tmp – có thể xóa và tạo lại bằng mkdir
  • Thư mục chứa từ tmp hay temp
  • Thư mục chứa từ cache

Những thư mục bạn không được tự tiện xóa:

  • /* – bất kỳ thư mục con nào của root
  • /home/* – thư mục của users
  • /home/username/web/* – thư mục web VestaCP
  • /home/username/public_html/* – thư mục web cPanel
  • /var/www/html/* – thư mục web default của Apache/Nginx
  • /var/spool/*/* – liên quan đến system queue
  • Bất cứ thư mục nào có thể chứa mã nguồn hoặc database của project.

Sau khi bạn xóa thư mục chiếm IUsed thì lỗi sẽ biến mất như một phép màu, tuy nhiên nó sẽ quay trở lại nếu không được giải quyết triệt để. Ở phần dưới, tôi chỉ nói đến cách xử lý với PHP session vì bài đã dài và không thể cover hết được.

2. Khắc phục kiểu lười

Tới phần này, bạn đã tìm ra thư mục chiếm nhiều Inode và nó chứa đầy các file sess_*. Giờ ta chạy thử lệnh này bằng quyền root xem có lỗi gì không:

// dấu # tượng trưng cho quyền root, $ tượng trưng cho quyền user
# /usr/lib/php/sessionclean

Nếu không có lỗi gì và Iused vẫn là 100% thì các file sess_* đang được tạo nhanh hơn số file được xóa đi, nó giống như một quả bom nổ chậm vậy.

Nếu server của bạn chứa những site không quan trọng và bạn lại lười vcc (như tôi) thì ta có thể áp dụng cách xóa hết session file vào một thời điểm trong ngày. Ta mở crontab lên bằng lệnh crontab -e và thêm dòng sau vào cuối file:

// 0 0 * * * có nghĩa là 0 giờ 0 phút tất cả các ngày
// nhớ thay /target/dir bằng thư mục chứa PHP session
0 0 * * * rm -f /target/dir/sess_*

3. Khắc phục kiểu pro

  • Giảm số website trên server: Hàng trăm site trên một server không chỉ tạo ra Inode issue mà còn dẫn đến nghẽn cổ chai như “too many connections”, high CPU load và high RAM load. Đã đến lúc bảo khách hàng của bạn đầu tư thêm server mới. Nhân tiện ta thu phí setup luôn ?
  • Tinh chỉnh PHP configuration: Giảm gc_maxlifetime chẳng hạn.
  • Dùng Redis để lưu session.
  • Đưa upload files lên Cloud (Storage Service).
  • Áp dụng tất cả các cách trên.

Nếu bạn đã gặp vấn đề này rồi và bạn có cách hay để xử lý thì hãy để lại comment bên dưới nhé!

Tham khảo:

  • https://en.wikipedia.org/wiki/Inode
  • https://kernelnewbies.org/Ext4
  • https://serverfault.com/questions/104986/what-is-the-maximum-number-of-files-a-file-system-can-contain
  • https://stackoverflow.com/questions/653096/how-to-free-inode-usage
  • https://stackoverflow.com/questions/654310/cleanup-php-session-files
0 0 votes
Article Rating