Yazılar · PHP · Hostinger · Formlar
Formu dolduran kullanıcı 'oturum zaman aşımı' alıyor: Hostinger'da PHP oturum ömrü tuzağı
Hostinger paylaşımlı hesapta session.gc_maxlifetime varsayılanı 1440 saniye, yani 24 dakika; oturum dosyaları bütün uygulamaların paylaştığı ortak bir dizinde tutuluyor ve çöp toplamayı başka bir uygulamanın isteği de tetikliyor. Yalnız ömrü uzatmak bu yüzden yetmez. Çözüm web kökünün dışında kendi oturum dizinini kurup session_save_path ile oraya geçmek ve ömrü altı saate çıkarmak.
Bir ön kayıt formunda üç gerçek aday kaydolamadı. Biri aynı akşam dört kez denemiş, dördünde de "oturumun zaman aşımına uğramış" hatası almıştı. Kurtarma katmanı verilerini tuttuğu için kaybolmadılar ama kayıtlı da değillerdi. Form doğruydu, sunucu doğruydu, jeton üretimi doğruydu. Sorun, formu telefonda açıp yarım saat sonra gönderen insanın gerçek hayatıydı ve paylaşımlı sunucunun o gerçek hayata göre ayarlanmamış oturum ömrüydü.
Önce ölç, tahmin etme
php -r 'echo ini_get("session.gc_maxlifetime"), " ", ini_get("session.save_path");'
# 1440 /opt/alt/php83/var/lib/php/session
Komut satırı ile web isteği farklı ayar taşıyabilir; kesin ölçüm için public_html'e geçici bir probe.php koyup aynı değerleri web bağlamında yazdırdım ve dosyayı sildim. Ölçüm anında ortak oturum dizininde 362 dosya vardı; hesaptaki bütün PHP uygulamalarının oturumları yan yana duruyordu.
Neden ömrü uzatmak yetmiyor
PHP'nin oturum çöp toplaması dizin bazında çalışır ve her isteğin küçük bir olasılıkla tetiklenir. Ortak dizinde bu, başka bir uygulamanın isteğinin senin oturum dosyanı da silebileceği anlamına gelir; o uygulamanın kendi ömür ayarıyla. Kendi kodunda ini_set('session.gc_maxlifetime', …) yazman tek başına anlamsızdır, dosya yine komşunun çöp toplamasıyla uçar. Asıl koruma kendi dizinindir.
Çözüm
$oturumDizini = dirname(__DIR__) . '/oturumlar'; // web kökünün DIŞINDA
if (!is_dir($oturumDizini)) { @mkdir($oturumDizini, 0700, true); }
if (is_dir($oturumDizini) && is_writable($oturumDizini)) {
ini_set('session.gc_maxlifetime', '21600'); // 6 saat
session_save_path($oturumDizini); // ŞART: kendi dizinimiz
}
session_start();
Çerez ömrünü bilerek sıfırda bıraktım, yani tarayıcı kapanana kadar; sayı vermek işi kısaltır. Dizin uygulama kökünün altında, web'den 404 dönüyor ve izni 700. Doğrulama üç adım: yeni oturum dosyaları yeni dizine düşüyor mu, dizin dışarıdan gerçekten 404 mü, jeton al ve yarım saat sonra gönder senaryosunda "zaman aşımı" çıkmıyor mu.
Bir yan etki var: save_path değiştiği an mevcut bütün oturumlar düşer; yönetici çıkış yapar, açık formların jetonu ölür. Bunu trafiğin düşük olduğu saatte yap.
Yanlış teşhisin anatomisi
İlk hipotezim "LiteSpeed sayfayı önbellekliyor, bayat jeton servis ediliyor" idi. Ölçünce yanlış çıktı: jetonlar her istekte tazeydi ve sayfa no-store ile geliyordu. Daha kötüsü, ilk ölçümüm bozuktu. grep -P Windows'taki Git Bash'te yerel ayar hatasıyla iki jetonu da boş döndürdü ve ben iki boş dizeyi "aynı jeton, demek ki önbellek" diye okudum. Ölçüm aracının kendisi bozuksa bulgu da bozuktur; boş ya da tuhaf bir çıktıyı sonuç sayma, önce aracı doğrula.
Bu yazı neye dayanıyor
25 ve 26 Ağustos 2026, iki ayrı ön kayıt sitesi. Kaybolan üç aday kurtarma katmanından elle kaydedildi; çözüm iki siteye de uygulandı ve o günden beri zaman aşımı kaynaklı düşme olmadı.
Yazılım ve sistem mimarı, AlgowAI'da COO. Bu yazıdaki her şey canlı bir sistemde ölçülerek yaşandı; tahmin yok. Sorun sende de varsa yaz, bakarım.