{"id":17,"date":"2015-01-12T18:40:41","date_gmt":"2015-01-12T17:40:41","guid":{"rendered":"http:\/\/www.contentecontent.com\/blog\/?p=17"},"modified":"2015-06-03T17:48:38","modified_gmt":"2015-06-03T16:48:38","slug":"when-the-server-ran-out-of-inodes","status":"publish","type":"post","link":"https:\/\/www.contentecontent.com\/blog\/2015\/01\/when-the-server-ran-out-of-inodes\/","title":{"rendered":"When the server ran out of inodes"},"content":{"rendered":"<p>A while ago I couldn&#8217;t add any files to a Debian server I control. It was pretty odd, as there was plenty of free disk space available (<code>df -h<\/code> will show that).<\/p>\n<p>After I deleted a number of web cache files, I could add new files again. But soon the problem would return, leaving me wondering what was wrong.<\/p>\n<p><!--more--><\/p>\n<p>Then I ran <code>df -i<\/code>, which showed that the server had run out of inodes. From <a href=\"https:\/\/en.wikipedia.org\/wiki\/Inode\">Wikipedia<\/a>:<\/p>\n<blockquote>\n<p>Each inode stores the attributes and disk block location(s) of the filesystem object&#8217;s data.<\/p>\n<\/blockquote>\n<p>Now, where were all those files that ate my inodes? After much searching I found that <code>\/var\/lib\/php5<\/code> contained millions of files. It is where PHP stores its session files. Obviously there was something wrong with the server&#8217;s PHP garbage collection, as session files are supposed to be removed after a while.<\/p>\n<p>Session removal is handled by a cron job in <code>\/etc\/cron.d\/php5<\/code>, which runs every 30 minutes. It calls two scripts in <code>\/usr\/lib\/php5<\/code> : <code>maxlifetime<\/code> and <code>sessionclean<\/code>. I tried to run them from the command line, but they failed and reported a deprecated entry in one of the server&#8217;s <code>php.ini<\/code> files.<\/p>\n<p>The entry (I can&#8217;t recall exactly which one it was) had become deprecated with the upgrade from PHP 5.3 to 5.4. I may or may not have read about it, but as PHP (Apache and cli) worked fine after the upgrade I probably just didn&#8217;t bother. My mistake.<\/p>\n<h2>Removing the files<\/h2>\n<p>I fixed the php.ini file, restarted Apache and started to remove the session files. That turned out to be easier said than done. Simply running <code>rm \/var\/lib\/php5\/sess*<\/code> would more or less bring the server to a halt. I stopped the cron job in <code>\/etc\/cron.d\/php5<\/code> to prevent an enormous CPU spike.<\/p>\n<p>Here are a couple of commands I found useful for handling large numbers of files in loops. Use at own risk.<\/p>\n<p>The session files have names like <code>sess_51c6b3a6e5620d59c3c13cfdc739b1aa<\/code>. To find out how many files there are with names starting with for example <code>sess_5<\/code>, run<\/p>\n<pre><code>n=0; for i in \/var\/lib\/php5\/sess_5*; do n=$((n+1)); done; echo $n\n<\/code><\/pre>\n<p>Multiply the output by 16 and you have an estimated total number of files. If there are millions of files in the directory, you may need to use a more specific file name pattern (like <code>sess_51c<\/code>). Actually, it&#8217;s smart to start with a more specific pattern and loosen it step by step to find out what the server can handle.<\/p>\n<p>Show the modification dates of a set of files:<\/p>\n<pre><code>for i in \/var\/lib\/php5\/sess_5*; do echo $(date -r $i); done\n<\/code><\/pre>\n<p>To remove a set of files that are over one day old:<\/p>\n<pre><code>now=$(date +%s); time for i in \/var\/lib\/php5\/sess_5*; do if ((($(stat \"$i\" -c '%Z') + (86400 )) &lt; $now)); then rm -fv $i; fi; done\n<\/code><\/pre>\n<p><code>-f<\/code> makes it only remove files (you never know&#8230;), <code>-v<\/code> makes it verbose, so you can see what&#8217;s going on. <code>time<\/code> makes it show script execution duration when it finishes.<\/p>\n<p>Faster, doesn&#8217;t care how old the files are, i.e. kills current sessions:<\/p>\n<pre><code>for i in \/var\/lib\/php5\/sess_5*; do rm -fv $i; done\n<\/code><\/pre>\n<p>It took me at least a day to get rid of the files and have the server operate normally again.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A while ago I couldn&#8217;t add any files to a Debian server I control. It was pretty odd, as there was plenty of free disk space available (df -h will show that). After I deleted a number of web cache files, I could add new files again. But soon the problem would return, leaving me &hellip; <a href=\"https:\/\/www.contentecontent.com\/blog\/2015\/01\/when-the-server-ran-out-of-inodes\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">When the server ran out of inodes<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[2,7],"class_list":["post-17","post","type-post","status-publish","format-standard","hentry","category-server-admin","tag-debian","tag-php"],"_links":{"self":[{"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":8,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":58,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/posts\/17\/revisions\/58"}],"wp:attachment":[{"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.contentecontent.com\/blog\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}