Bir Harfi Fazla Yazmak ve PHP5 Oturum Çöp Toplayıcısı

1778_large

Bugün, MeeGo Türkiye’ye göz attığımda bir gariplik fark ettim. Forum başlıklarının tasarımı bozuk görünüyordu. Tabii bu durumda ilk suçlayacağınız muhtemelen tarayıcıdır. Önce bir CTRL + F5, sonra da iPhone ‘dan girdiğimde tasarımdaki aynı sıkıntı hala önümde duruyordu.

Bu noktada yönetici hesabıma giriş yaptım. Daha iyisi, ben giriş yapar yapmaz sağ barın kaybolduğu gibi sayfalar da bozuldu. İşte buradan sonra o can sıkıcı yarım saati okuyorsunuz:

İlk önce Drupal ‘in Cache temizleyicisini denedim. Birkaç dakikalığına işe yaradı da, sonra yeniden bozuldu. Daha sonra Drupal ‘in tüm hataları ve olayları kaydettiği DBLOG ‘a (Yakın zamanlı kayıtlar) ‘a girdim. DBLOG ‘un avantajı, sunucunuza giriş yapıp logları elle kontrol etmeden, buradan PHP hata kayıtlarını görebiliyor oluşunuz. Burada kolaylıkla dikkat çeken PHP hatalarından birine tıkladığımda ise:


taxonomy.module dosyası 21 satırında Can't create/write to file '/tmp/#sql_36a_0.MYD' (Errcode: 28)


OSS projelerinin ve genel anlamda Linux ‘un mızmızlanma şekillerine alışıksanız, “Can’t write” ile başlayan bir hata cümlesinin ne olduğuna dair fikriniz hemen oluşur. Büyük ihtimalle ya bir izin hatası yaşıyorsunuz, ya da dosya sisteminde bir sıkıntınız var, mesela disk alanı yetersiz veya salt-okunur bağlanmış olabilir.

Buradan sonrası için, sunucuma SSH ile bağlandım. Giriş yaptıktan sonra, ilk denediğim dosya sisteminin yazılabilir olup olmadığı oldu, bunu basit  bir “touch deneme” komutuyla denemeniz mümkün. Diskte boş yer kalmadığına dair ikazı aldıktan sonra, sorumun cevabını almış oldum.

Diskte boş alan kalmadıysa genelde şüpheliler ya /home/ klasörü altındadır ya da /var/log ‘un içerisinde. Düzgün bir log rotasyonu ayarlanmadıysa /var/log kısa sürede şişip, sunucudaki tüm boş alanı bitirebilir. İlk buralara baktıysam da dişe dokunur bir sonuç alamadım.

Bunun üzerine basitçe bir iki gereksiz log dosyasını silip diskte yaklaşık 100M kadar bir alanı açtım. Bu alan Drupal ‘in çalışması için fazlasıyla yeterli, daha sonra da Drupal ‘in önbelleğini tekrar temizlediğimde, site mükemmel şekilde çalışmaya geri döndü.

Tabii sorunun asıl kaynağı hala yerli yerinde duruyor olmalıydı. Diskte bu kadar alanı kaplayanın ne olduğunu bulmak için NCDU adında harika, curses kullanarak grafik arayüzlü bir CLI uygulamasından faydalandım. NCDU, diskte genel bir tarama yapıp, her şeyi kolaylıkla anlaşılabilir şekilde önünüze döküyor. Bir web sunucusunu taraması 1 dakikadan fazla sürmüyor. (Üstteki resimdeki uygulama NCDU)

Dikkatimi çeken en büyük kullanım /var/lib/php5 altındaydı. Neredeyse diskin tamamını kullanan bu klasör, belli ki en sonunda diski tamamen doldurmuş, boş alan bulamayan MySQL veritabanına yazamayınca, Drupal de çalışmaz olmuş.

Bu klasörün altında 4KB ‘lık on binlerce dosyayla karşılaşmak ise sorunun kaynağını ortaya çıkardı. Hepsi sess_* şeklinde başlayan bu dosyalar, normalde PHP ‘nin oturum dosyaları ve her kullanıcı oturumu için bir tane oluşturulması doğal. Ancak işi bittikten sonra silinmemiş olması hiç doğal değil.

Ubuntu/Debian ‘da bu oturum dosyaları, yarım saatte bir çalıştırılan bir CRON işi ile siliniyor. Her 30 dakikada bir, /usr/lib/php5/maxlifetime dosyası çalıştırılıyor, çalışmanın sonucunda elde edilen değerden daha eski dosyalar ise siliniyor.

Bu sefer ilk baktığım bu dosyanın gerçekten var olup olmadığı (ki vardı) ve çalıştırılabilir olup olmadığıydı (ki çalıştırılabiliyordu). Ben de çalıştırdım, sonuçta aldığım cevap:

<code>PHP Fatal error:  Allowed memory size of 262144 bytes exhausted (tried to allocate 523800 bytes) in Unknown on line 0
</code>

Nasıl yahu? Her betiğe 256 Megabyte bellek kullanımı vermemiş miydim? Belli ki verememişim, Maxlifetime ‘ın çağırdığı konfigürasyon dosyasına baktığımda, koşarak bir duvara kafa atmamak çok zordu. memory_limit = 256MB  satırında, isteğimi kendimce güzellikle belirtmişim, oysa oradaki B fazlaydı, ve bu yüzden bellek limiti artmamıştı. Bu satırı 256M yapıp kaydettikten sonra ise, yarım saat sonraki ilk CRON çalıştırmasında tüm gereksiz oturum dosyaları silinmişti bile.

Sonuçta, memory_limit ‘i tanımlarken koyduğum fazladan bir B, Maxlifetime betiğinin çalıştırılmasına engel olmuş, tüm işi ekrana “24” yazmak olan bu betiğin çalışamaması CRON ‘un yarım saatte bir çöp oturumları silmesine engel olmuş, biriken gereksiz oturumlar aylar sonunda diski doldurmuş, en sonunda MySQL ‘i yazılamaz hale getirip siteyi de bozmuş, ve yaz tatilimin ortasında beni bozuk bir Drupal sitesiyle baş başa bırakmıştı. Evet, bunların hepsi bir kelebek etkisi, bir “B” nin fazla yazılmış olmasının sonuçları.

Bu sorunu çözdüğümde başta çok önemsememiştim, ancak sonradan sorunun çıktığı noktayı ve tespit edip çözmekteki pek çok fazladan adımı düşününce; insanın gerçekten bastığı her bir harfe dikkat etmesi gerekiyor, özellikle de bir sunucuyu siz yönetiyorsanız.

Yorum Yazın