less Komutu ile Büyük Log Dosyalarını Sayfalayarak Okuma

Web sunucusu yönetirken en çok ihtiyaç duyduğun şeylerden biri büyük log dosyalarını terminali dondurmadan okuyabilmek. less komutu tam da bu iş için var ve cat’ten çok daha güçlü. Bu yazıda less’i sysadmin gözüyle ele alıyoruz.

Gece 2’de production sunucusu alarm verdi, SSH’a bağlandın, /var/log/nginx/error.log dosyasına bakmak istiyorsun. İlk refleks olarak cat /var/log/nginx/error.log yazıyorsun ve terminal binlerce satırı sana fırlatıyor. Ekran kayıyor, bir şey göremiyorsun, history’de kaybolup gidiyorsun. Tanıdık geldi mi? İşte bu yazı tam da o anın çaresi için.

less komutu, büyük dosyaları terminal oturumunu mahvetmeden, kontrollü biçimde okumanı sağlayan bir sayfalayıcı. Aslında adındaki felsefeyi seviyorum: “less is more” — yani less, more komutunun geliştirilmiş hali ve gerçekten de daha fazlasını yapıyor. Hadi her şeyi sıfırdan konuşalım.

less Nedir, Neden cat Kullanmamalısın?

cat komutu dosyayı baştan sona stdout’a basar ve çıkar. 50 MB’lık bir Nginx access log için bu tam bir felakettir. Terminal buffer’ın taşar, scroll yapmak işkenceye döner, arama yapamazsın. more komutu biraz daha iyidir ama sadece aşağı gidebilirsin — yani geri dönemezsin.

less ise dosyayı bellekte tamamen açmaz. Sadece görüntülediğin kısmı okur, bu yüzden 2 GB’lık bir log dosyasını bile anında açar. Hem yukarı hem aşağı gidebilirsin, içinde arama yapabilirsin, birden fazla dosyayı sırayla gezebilirsin. Web sunucusu yönetiminde bu araç neredeyse her gün işine yarar.

Temel Kullanım

En basit kullanım şekli dosya adını argüman olarak vermek. Birkaç yaygın senaryoya bakalım:

# Tek bir dosyayı aç
less /var/log/nginx/error.log

# Apache access log
less /var/log/apache2/access.log

# Syslog'u oku
less /var/log/syslog

# Bir config dosyasını incele
less /etc/nginx/nginx.conf

# Birden fazla dosyayı sırayla aç
less /var/log/nginx/error.log /var/log/nginx/access.log

Dosyayı açtıktan sonra sağ altta dosya adını ve yüzde kaçında olduğunu görürsün. Birden fazla dosya açtığında kaçıncı dosyada olduğun da gösterilir. Basit ama çok işe yarayan bir ayrıntı.

Bilmen Gereken Klavye Kısayolları

less’in gücü kısayollarında yatıyor. Bunları bir kere ezberleyince terminalde çok daha hızlı hareket edersin. En sık kullandıklarımı tabloda derledim:

Kısayolİşlev
Space veya PgDnBir sayfa aşağı git
b veya PgUpBir sayfa yukarı git
j veya Asagi OkBir satır aşağı git
k veya Yukari OkBir satır yukarı git
gDosyanın en başına git
GDosyanın en sonuna git
/kelimeAşağı doğru ara
?kelimeYukarı doğru ara
nSonraki arama sonucuna git
NÖnceki arama sonucuna git
qÇık
hYardım ekranını aç
:nSonraki dosyaya geç (çoklu dosyada)
:pÖnceki dosyaya geç (çoklu dosyada)
FDosyayı canlı takip et (tail -f gibi)

Özellikle F kısayoluna dikkat et. less içinde F tuşuna basarsan dosya gerçek zamanlı güncellenmeye başlar, tıpkı tail -f gibi. Üstelik istediğin zaman Ctrl+C ile canlı takipten çıkıp yine normal okuma moduna geçebilirsin. Bu, tail -f’e göre büyük avantaj çünkü geçmişe dönüp bakabiliyorsun.

Satır Numarası ile Çalışmak

Bir hata mesajında “line 342” gibi bir referans gördüğünde doğrudan o satıra atlamak isteyebilirsin. Bunun için birkaç yöntem var:

# Dosyayı satır numaralarıyla aç
less -N /var/log/nginx/error.log

# less içinde satır numaralarını aç/kapat
# less'i açtıktan sonra -N yazıp Enter'a bas

# Belirli bir satıra atla: less içinde 342g yaz
# ya da komut satırından direkt aç
less +342 /etc/nginx/nginx.conf

# İlk açılışta belirli bir kelimeyi ara
less +/"upstream" /etc/nginx/nginx.conf

Ipucu: less içinde 342g yazarsan (yani sayı + g) direkt o satıra atlar. Büyük config dosyalarında çok işine yarar, özellikle birinin sana “677. satıra bak” dediği durumlarda.

Pipe ile Kullanım — Asıl Güç Burada

less’i sadece doğrudan dosya açmak için kullanmak israfı olur. Asıl gücünü pipe’larla birleştirdiğinde ortaya çıkar. Web sunucusu senaryolarında en çok şöyle kullanıyorum:

# grep çıktısını sayfalayarak görüntüle
grep "500" /var/log/nginx/access.log | less

# Son 500 satırı oku ama sayfalayarak
tail -500 /var/log/nginx/error.log | less

# Birden fazla grep filtresi uygulayıp sayfalama
grep "POST" /var/log/apache2/access.log | grep "404" | less

# journalctl çıktısını sayfalayarak oku
journalctl -u nginx --since "2024-01-01" | less

# ps çıktısını sayfalayarak incele
ps aux | less

# Uzun bir komutun yardım çıktısını oku
nginx -T | less

nginx -T komutu tüm nginx konfigürasyonunu birleştirilmiş olarak döker. Bu çıktı bazen yüzlerce satır olabiliyor. Direkt terminale basmak yerine less’e pipe etmek hayat kurtarır.

Renk ve Çıktı Formatını Koruma

Bir sorunla karşılaşmış olabilirsin: bazı komutların renkli çıktısını less’e pipe ettiğinde renkler kayboluyor. Bu, ANSI renk kodlarının pipe üzerinden geçerken bazı araçlar tarafından ezilmesinden kaynaklanıyor. Bunu çözmek için:

# ANSI renk kodlarını koru (-R bayrağı)
grep --color=always "error" /var/log/syslog | less -R

# Kalıcı olarak ayarlamak için .bashrc veya .zshrc'ye ekle
export LESS="-R"

# Ya da alias tanımla
alias less='less -R'

# git log çıktısını renkli sayfalama
git log --oneline --color=always | less -R

# journalctl çıktısını renkli oku
journalctl -u php8.1-fpm --output=short-precise --no-pager | less -R

Ipucu: LESS ortam değişkenini .bashrc’ye eklersen her seferinde -R yazmak zorunda kalmazsın. Özellikle renkli grep çıktılarını sık kullanıyorsan bu ayarı bir kere yap ve unut.

Gerçek Dünya Senaryosu: Nginx 502 Hatalarını Araştırma

Diyelim ki bir web uygulamasında kullanıcılar intermittent 502 hatası aldığını bildiriyor. İşte bu durumda less’i nasıl kullanırdım:

# Önce son birkaç saatin error loguna bak
tail -2000 /var/log/nginx/error.log | less

# less içindeyken /502 yazarak 502 hatalarını ara
# n tuşuyla sonraki, N ile önceki hataya atla

# Daha hedefli: sadece 502 içerenleri filtrele
grep "502" /var/log/nginx/error.log | less

# Zaman damgasıyla birlikte incele
grep "2024/01" /var/log/nginx/error.log | grep "502" | less

# upstream bağlantı hatalarını ara
grep --color=always "upstream" /var/log/nginx/error.log | less -R

# PHP-FPM logunu da incele (502'nin kaynağı orası olabilir)
less /var/log/php8.1-fpm.log
# less içinde /error veya /fatal yazarak kritik hataları bul

Bu iş akışı sayesinde terminali boğmadan, spesifik hataları hızlıca bulabiliyorsun. Özellikle gece saatlerinde stres altında çalışırken bu tür sistematik bir yaklaşım çok değerli.

Gerçek Dünya Senaryosu: Büyük Config Dosyasını Güvenle İnceleme

Devir aldığın bir sunucuda Nginx konfigürasyonunu anlamaya çalışıyorsun. Dosya 800 satır, içinde upstream blokları, server blokları, location direktifleri iç içe geçmiş. İşte böyle bir durumda:

# Tüm nginx config'i birleştirilmiş halde oku
nginx -T 2>/dev/null | less

# less içinde /server_name yazarak virtual host'ları bul
# /upstream yazarak backend tanımlarını bul
# /ssl_certificate yazarak SSL ayarlarını bul

# Sadece nginx.conf'u satır numarasıyla aç
less -N /etc/nginx/nginx.conf

# Tüm site config'lerini sırayla incele
less /etc/nginx/sites-enabled/*
# :n ile sonrakine, :p ile öncekine geç

# Apache için .htaccess dosyalarını bul ve oku
find /var/www -name ".htaccess" | xargs less

Uyari: find + xargs + less kombinasyonunu kullanırken çok sayıda .htaccess dosyası bulunabilir. Her birine :n ile geçmek yerine önce find ile listeyi görüp, tek tek ilgilendiğin dosyaları açman daha pratik olabilir.

Sıkıştırılmış Log Dosyalarını Okuma

Linux log rotasyon sistemleri eski logları genellikle .gz formatında sıkıştırır. error.log.2.gz gibi dosyaları okumak için less’in özel bir kardeşi var: zless. Ama aslında modern less sürümleri bunu otomatik halleder.

# Sıkıştırılmış log dosyasını oku (zless)
zless /var/log/nginx/error.log.2.gz

# Ya da modern less ile doğrudan (lesspipe etkinse)
less /var/log/nginx/error.log.2.gz

# lesspipe'ı etkinleştirme (.bashrc'ye ekle)
eval "$(lesspipe)"

# Birden fazla sıkıştırılmış dosyayı sırayla oku
zless /var/log/nginx/error.log.1.gz /var/log/nginx/error.log.2.gz

# Sıkıştırılmış log içinde grep yap, çıktıyı say
zcat /var/log/nginx/access.log.1.gz | grep "404" | wc -l

Eski tarihlerdeki olayları araştırırken sıkıştırılmış logları açmak zorunda kalmak gereksiz disk kullanımı yaratır. zless veya lesspipe entegrasyonu bu sorunu tamamen ortadan kaldırır.

Yatay Kaydırma ve Uzun Satırlar

Access log dosyalarında satırlar bazen terminal genişliğini aşar. Varsayılan davranışta less bu satırları keser ve devamını görmezsin. Bunu kontrol etmek için:

# Satır kesmeden aç (yatay scroll ile)
less -S /var/log/nginx/access.log

# less içinde yatay kaydırma: Sol/Sag ok tuslari
# ya da Alt+( ve Alt+) ile kaydır

# Kombinasyon: satır numarası + satır kesme yok
less -SN /var/log/nginx/access.log

# JSON log formatındaki access loglar için özellikle kullanışlı
less -S /var/log/nginx/access.json

# Çok uzun satırlı dosyada belirli kolonu arama
less -S /var/log/nginx/access.log
# less içinde /"POST /api" yazarak API isteklerini bul

JSON formatında log tutan Nginx veya uygulama sunucularında -S bayrağı özellikle değerli. Her satır ayrı bir JSON objesi oluyor ve kesmeden görmek veri bütünlüğünü korur.

Faydalı less Bayrakları Özeti

  • -N: Satır numaralarını göster
  • -S: Uzun satırları kırpma, yatay kaydırmaya izin ver
  • -R: ANSI renk kodlarını işle, renkli çıktı göster
  • -i: Arama yaparken büyük/küçük harf farkını gözetme
  • -F: Dosya tek ekrana sığıyorsa less açmadan direkt göster, çık
  • -X: Çıkışta ekranı temizleme (çıktı terminalde kalsın)
  • -e: Dosya sonuna iki kez ulaşınca otomatik çık
  • +F: Açılışta direkt canlı takip (tail -f) modunda başla
  • -p kelime: Açılışta direkt belirtilen kelimeyi ara ve ona atla

Alias ve Konfigürasyon Önerileri

Günlük iş akışını hızlandırmak için birkaç alias ve ortam değişkeni tanımlamak işini çok kolaylaştırır. Ben .bashrc’me şunları ekledim ve artık düşünmeden kullanıyorum:

# .bashrc veya .zshrc'ye eklenecekler

# Varsayılan less bayrakları: renk + büyük/küçük harf duyarsız arama
export LESS="-R -i"

# lesspipe etkinleştir (sıkıştırılmış dosyalar için)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# Nginx logları için kısayollar
alias nginx-error='less /var/log/nginx/error.log'
alias nginx-access='less -S /var/log/nginx/access.log'
alias apache-error='less /var/log/apache2/error.log'

# Canlı takip kısayolları
alias nginx-live='less +F /var/log/nginx/error.log'

# Syslog takibi
alias syslog='less +F /var/log/syslog'

# .bashrc'yi yeniden yükle
source ~/.bashrc

Ipucu: LESS ortam değişkeni less’in her çalışmasında otomatik uygulanır. Bu yüzden sık kullandığın bayrakları buraya taşıyabilirsin. -i bayrağı özellikle log araştırırken çok işine yarar çünkü büyük/küçük harf farkı olmadan Error, ERROR, error hepsini bulur.

less ile more Karşılaştırması

Özelliklessmore
Geri gitme (yukarı scroll)EvetHayir
Arama yapmaEvet (/ ve ?)Sinirli (sadece /)
Canlı takip moduEvet (F tusu)Hayir
Birden fazla dosyaEvet (:n ve :p)Kismi
ANSI renk desteğiEvet (-R ile)Hayir
Satır numarasıEvet (-N ile)Hayir
Sıkıştırılmış dosyaEvet (zless/lesspipe)Hayir

Tablodan da anlaşılacağı gibi more’u kullanmak için gerçekten özel bir sebep yok. Bazı çok eski veya minimal sistemlerde less bulunmayabilir, o zaman more’a mecbur kalabilirsin. Ama eğer seçme şansın varsa her zaman less kullan.

Sonraki Adımlar

less komutunu artık temel düzeyde iyi kullanabiliyorsun. Buradan sonra şu yönlere gidebilirsin:

  • grep + less kombinasyonu: grep’in -A, -B, -C bayraklarını less ile birleştirerek hata etrafındaki bağlamı görmek çok güçlü bir yöntem. Örneğin hata satırının öncesi ve sonrasını birlikte analiz edebilirsin.
  • multitail: Birden fazla log dosyasını aynı anda, ekranı bölerek takip etmek istiyorsan multitail aracına bak. Özellikle birden fazla servis birlikte debug edilirken çok kullanışlı.
  • lnav: Log dosyaları için geliştirilmiş, renkli ve yapısal analiz yapabilen bir sayfalayıcı. JSON loglarını otomatik parse ediyor, SQL benzeri sorgular bile yazabiliyorsun.
  • gzip log rotasyonu: logrotate konfigürasyonunu öğrenmek, eski logların düzgün sıkıştırılıp yönetilmesi için çok önemli. zless ile de pekiştirdiğin bilgiyle eski logları rahatlıkla okuyabilirsin.
  • lesskey: less’in kendi konfigürasyon dosyası olan lesskey ile kişisel kısayollar tanımlayabilirsin. Çok ileri düzey bir ihtiyaç ama varoluşundan haberdar olmak iyi.

less bir terminal aracı olarak sade görünebilir ama doğru kullandığında log analizi ve dosya inceleme süreçlerini ciddi ölçüde hızlandırır. Özellikle web sunucusu yönetiminde günde onlarca kez kullandığın bir araç haline gelecek. Kısayolları ezberledikçe ve pipe kombinasyonlarına alıştıkça terminalde gerçekten uçtuğunu hissedersin.

echo Komutu: Terminal Çıktısı ve Değişken Kullanımı — Sysadmin Rehberi

echo komutu ilk bakışta çok basit görünür ama web sunucusu yönetiminde scriptlerin bel kemiğini oluşturur. Değişkenlerden log yazmaya, config dosyası üretmeye kadar echo’nun tüm inceliklerini bu yazıda bulacaksın.

echo komutunu ilk öğrendiğinde muhtemelen şöyle düşündün: “Bu kadar mı? Ekrana bir şey yazdırıyor, tamam.” Ben de öyle düşünmüştüm. Ama yıllarca web sunucusu yönetirken fark ettim ki echo, scriptlerin en sık kullanılan ve en çok küçümsenen komutu. Nginx config’i otomatik üretmek, Apache virtual host dosyası oluşturmak, deploy scriptlerine durum mesajı eklemek… Bunların hepsinde echo var. Hadi sıfırdan, ama bu sefer doğru şekilde öğrenelim.

echo Nedir ve Nerede Çalışır?

echo, kendisine verdiğin argümanları standart çıktıya (stdout) yazan bir komuttur. Linux’ta hem bir shell built-in komutu olarak hem de /bin/echo veya /usr/bin/echo yolunda bağımsız bir binary olarak bulunur. Bu fark önemsiz gibi görünse de scriptlerde taşınabilirlik açısından kritik hale gelebilir.

Bash’in kendi içindeki echo ile sistemdeki /bin/echo arasında davranış farkları var. Özellikle -e ve -n gibi flag’lerde bu fark kendini gösteriyor. Hangi echo’yu kullandığını anlamak için şunu çalıştır:

# Hangi echo kullaniliyor?
type echo

# Sistemdeki echo binary yolu
which echo

# Bash built-in olarak mu cagiriliyor?
type -a echo

Genel kural şu: eğer taşınabilir script yazıyorsan ve kaçış karakterleri kullanman gerekiyorsa, echo yerine printf kullanmayı düşün. Ama web sunucusu ortamında Bash scriptleri yazarken echo gayet yeterli.

Temel Kullanım ve Bayraklar

echo’nun üç temel bayrağı var ve bunları ezberlemen gerekiyor:

  • -n: Satır sonu karakterini bastırma, yani çıktının sonuna newline ekleme
  • -e: Kaçış karakterlerini yorumla ( , , vb.)
  • -E: Kaçış karakterlerini yorumlama (bazı sistemlerde varsayılan değil, açıkça belirtmek gerekir)
# Temel kullanim
echo "Merhaba, Dunya"

# Satir sonu olmadan yaz (-n)
echo -n "Sunucu durumu kontrol ediliyor: "
echo "OK"

# Kacis karakterleriyle (-e)
echo -e "Satir 1
Satir 2
Satir 3"

# Tab karakteri
echo -e "Kolon1	Kolon2	Kolon3"

# Renk kodlariyla terminal ciktisi (ANSI)
echo -e "\e[32mBasarili\e[0m: Nginx yeniden baslatildi"
echo -e "\e[31mHata\e[0m: Port 80 kullanimda"

Renk kodlarına gelince: web sunucusu deploy scriptlerinde yeşil/kırmızı renk kullanmak, script çıktısını izleyen birinin durumu anında anlamasını sağlar. Küçük bir detay ama production deploy sırasında gerçekten fark yaratıyor.

Değişken Kullanımı

echo’nun asıl gücü değişkenlerle birleştiğinde ortaya çıkıyor. Web sunucusu scriptlerinde sürekli değişken değerlerini ekrana basmak, log dosyalarına yazmak ya da config dosyalarına aktarmak gerekir. Burada tırnak işaretlerinin nasıl davrandığını anlamak şart.

Kural basit: çift tırnak içinde değişkenler expand edilir, tek tırnak içinde edilmez. Bu fark seni ciddi baş ağrısından kurtarır.

# Degisken tanimlama
SITE_NAME="mywebsite.com"
WEB_ROOT="/var/www/html"
PHP_VERSION="8.2"
SERVER_IP=$(hostname -I | awk '{print $1}')

# Cift tirnak: degisken expand edilir
echo "Site adi: $SITE_NAME"
echo "Web root: $WEB_ROOT"
echo "PHP versiyonu: $PHP_VERSION"
echo "Sunucu IP: $SERVER_IP"

# Tek tirnak: degisken oldugu gibi yazilir
echo 'Degisken: $SITE_NAME'
# Cikti: Degisken: $SITE_NAME

# Karma kullanim
echo "Domain: ${SITE_NAME}, Root: ${WEB_ROOT}/"

# Komut ciktisini degiskene atayip echo ile goster
DISK_USAGE=$(df -h / | awk 'NR==2 {print $5}')
echo "Disk kullanimi: $DISK_USAGE"

# Array degiskenlerini gosterme
declare -a SITES=("site1.com" "site2.com" "site3.com")
echo "Birinci site: ${SITES[0]}"
echo "Tum siteler: ${SITES[@]}"

Ipucu: Değişkenleri kullanırken ${DEGISKEN} formatını alışkanlık haline getir. $DEGISKEN da çalışır ama süslü parantez, değişken adının nerede bittiğini kesin olarak belirtir. Özellikle ${SITE_NAME}.conf gibi kullanımlarda süslü parantez olmadan hata alırsın.

Web Sunucusu Senaryolarında echo Kullanımı

Şimdi gerçek hayata gelelim. Web sunucusu yönetirken echo’yu en çok şu üç senaryoda kullanıyorum: config dosyası üretmek, deploy scriptlerine durum mesajı eklemek ve hızlı diagnostic çıktısı almak.

Nginx Virtual Host Config Üretmek

Bir müşteri için yeni bir domain kuruyorsun diyelim. Her seferinde aynı Nginx config’i elle yazmak yerine, parametreleri değişkene atayıp echo ile dosyayı üretebilirsin. Bu, hem hata riskini azaltır hem de süreci hızlandırır.

#!/bin/bash
# nginx_vhost_create.sh — Otomatik Nginx virtual host olusturucu

DOMAIN="$1"
WEB_ROOT="/var/www/${DOMAIN}"
NGINX_CONF="/etc/nginx/sites-available/${DOMAIN}.conf"
PHP_SOCK="/run/php/php8.2-fpm.sock"

if [ -z "$DOMAIN" ]; then
    echo "Kullanim: $0 "
    exit 1
fi

echo "[INFO] $DOMAIN icin Nginx config olusturuluyor..."

# Web dizinini olustur
mkdir -p "${WEB_ROOT}/public"
echo "[OK] Dizin olusturuldu: ${WEB_ROOT}"

# Config dosyasini yaz
cat > "${NGINX_CONF}" << EOF
server {
    listen 80;
    server_name ${DOMAIN} www.${DOMAIN};
    root ${WEB_ROOT}/public;
    index index.php index.html;

    access_log /var/log/nginx/${DOMAIN}_access.log;
    error_log  /var/log/nginx/${DOMAIN}_error.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:${PHP_SOCK};
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
EOF

echo "[OK] Nginx config yazildi: ${NGINX_CONF}"
echo "[INFO] Sites-enabled sembolik link olusturuluyor..."
ln -sf "${NGINX_CONF}" "/etc/nginx/sites-enabled/${DOMAIN}.conf"
echo "[OK] Sembolik link olusturuldu"
echo "[INFO] Nginx test ediliyor..."
nginx -t && echo "[OK] Nginx config gecerli" || echo "[HATA] Nginx config hatali!"

Bu scriptte hem cat heredoc hem de echo birlikte kullanılıyor. echo durum mesajları için, cat ise çok satırlı config bloğu için daha uygun. İkisini karıştırmak yerine amaca göre seçmek önemli.

Deploy Script’inde Durum Çıktısı

Canlı ortama deploy yaparken her adımın ne durumda olduğunu bilmek istiyorsun. echo ile renkli ve yapılandırılmış çıktı üretmek, deploy sürecini takip etmeyi çok kolaylaştırır.

#!/bin/bash
# deploy.sh — Web uygulamasi deploy scripti

# Renk tanimlari
GREEN="\e[32m"
RED="\e[31m"
YELLOW="\e[33m"
BLUE="\e[34m"
RESET="\e[0m"

APP_DIR="/var/www/myapp"
GIT_BRANCH="main"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

log_info()    { echo -e "${BLUE}[INFO]${RESET} $1"; }
log_success() { echo -e "${GREEN}[OK]${RESET} $1"; }
log_warning() { echo -e "${YELLOW}[UYARI]${RESET} $1"; }
log_error()   { echo -e "${RED}[HATA]${RESET} $1"; }

echo -e "
${BLUE}================================================${RESET}"
echo -e "${BLUE} Deploy Basladi: ${TIMESTAMP}${RESET}"
echo -e "${BLUE}================================================${RESET}
"

log_info "Proje dizinine geciliyor: ${APP_DIR}"
cd "${APP_DIR}" || { log_error "Dizin bulunamadi: ${APP_DIR}"; exit 1; }

log_info "Git pull islemi: origin/${GIT_BRANCH}"
git pull origin "${GIT_BRANCH}" && log_success "Kod guncellendi" || { log_error "Git pull basarisiz"; exit 1; }

log_info "Composer bagimliliklar yukleniyor..."
composer install --no-dev --optimize-autoloader 
    && log_success "Composer tamamlandi" 
    || { log_error "Composer basarisiz"; exit 1; }

log_info "Cache temizleniyor..."
php artisan cache:clear && log_success "Cache temizlendi"

log_info "Nginx yeniden yukleniyor..."
systemctl reload nginx && log_success "Nginx reload edildi" || log_error "Nginx reload basarisiz"

echo -e "
${GREEN}================================================${RESET}"
echo -e "${GREEN} Deploy Tamamlandi: $(date '+%Y-%m-%d %H:%M:%S')${RESET}"
echo -e "${GREEN}================================================${RESET}
"

echo ile Dosyaya Yazmak

echo’yu yönlendirme operatörleriyle kullanmak, web sunucusu yönetiminde en sık başvurulan tekniklerden biri. Yeni bir dosya oluşturmak için > kullanırsın, mevcut dosyaya eklemek için >> kullanırsın. Bu farkı unutursan ciddi sorunlarla karşılaşabilirsin.

Uyari: > operatörü dosyanın mevcut içeriğini tamamen siler ve üzerine yazar. /etc/nginx/nginx.conf gibi kritik bir dosyada > ile echo kullanıyorsan, önce yedeğini al. Bu hatayı production’da bir kez yaşarsan, bir daha yaşamazsın.

# Yeni dosya olusturma (veya ustune yazma)
echo "ServerName mywebsite.com" > /tmp/apache_test.conf

# Dosyaya ekleme (append)
echo "DocumentRoot /var/www/html" >> /tmp/apache_test.conf
echo "ErrorLog /var/log/apache2/error.log" >> /tmp/apache_test.conf

# Log dosyasina tarihli kayit ekleme
LOG_FILE="/var/log/deploy.log"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Deploy baslatildi: $(whoami)" >> "${LOG_FILE}"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Git commit: $(git rev-parse --short HEAD)" >> "${LOG_FILE}"

# Basit bir durum dosyasi olusturma
echo "OK" > /var/www/html/health.txt
echo "Last-Updated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> /var/www/html/health.txt

# PHP bilgi dosyasi olusturma (test ortami icin)
echo "" > /var/www/html/info.php
echo "[UYARI] info.php olusturuldu, test sonrasi silmeyi unutma!"

# /dev/null'a yonlendirme: ciktiyi susturma
echo "Bu mesaj gorunmeyecek" > /dev/null

Özel Değişken Türleri ve echo

Bash’in özel değişkenleri web sunucusu scriptlerinde çok işe yarar. Bu değişkenleri echo ile birleştirdiğinde, scriptlerin debug edilmesi ve izlenmesi çok kolaylaşır.

DeğişkenAnlamıÖrnek Kullanım
$0Scriptin adıecho “Script: $0”
$1, $2…Positional parametrelerecho “Domain: $1”
$#Argüman sayısıecho “$# arguman verildi”
$?Son komutun çıkış koduecho “Cikis kodu: $?”
$$Mevcut process IDecho “PID: $$”
$@Tüm argümanlarecho “Tum: $@”
$HOSTNAMESunucu adıecho “Sunucu: $HOSTNAME”
$USERAktif kullanıcıecho “Kullanici: $USER”
#!/bin/bash
# server_info.sh — Sunucu ozet bilgisi

echo "========================================"
echo " Sunucu Ozet Raporu"
echo "========================================"
echo "Script      : $0"
echo "Calistiran  : $USER"
echo "Sunucu Adi  : $HOSTNAME"
echo "Tarih/Saat  : $(date '+%d.%m.%Y %H:%M:%S')"
echo "Uptime      : $(uptime -p)"
echo "----------------------------------------"
echo "CPU Kullanim: $(top -bn1 | grep 'Cpu(s)' | awk '{print $2}')%"
echo "RAM Kullanim: $(free -h | awk '/^Mem:/ {print $3"/"$2}')"
echo "Disk (/)    : $(df -h / | awk 'NR==2 {print $3"/"$2" ("$5" dolu)"}')"
echo "----------------------------------------"
echo "Aktif Nginx : $(systemctl is-active nginx)"
echo "Aktif MySQL : $(systemctl is-active mysql)"
echo "Aktif PHP   : $(systemctl is-active php8.2-fpm)"
echo "----------------------------------------"
echo "Acik Portlar:"
ss -tlnp | grep LISTEN | awk '{print "  " $4}'
echo "========================================"

# Son komutun basarili olup olmadigini kontrol et
if [ $? -eq 0 ]; then
    echo "Rapor basariyla olusturuldu."
else
    echo "Rapor olusturulurken sorun yasandi. Cikis kodu: $?"
fi

echo ile PHP ve Apache .htaccess Oluşturmak

Web sunucusu yönetiminde sık karşılaşılan bir senaryo: birden fazla site için standart .htaccess veya PHP yapılandırma dosyaları oluşturmak. echo ile bunu script haline getirdiğinde, onlarca siteyi dakikalar içinde yapılandırabilirsin.

#!/bin/bash
# setup_site_config.sh — Site yapılandırma dosyalarini olustur

DOMAIN="${1:-ornek.com}"
WEB_ROOT="/var/www/${DOMAIN}/public"

echo "[INFO] ${DOMAIN} icin yapilandirma dosyalari olusturuluyor..."

# .htaccess olustur (Apache icin)
cat > "${WEB_ROOT}/.htaccess" << 'HTACCESS'
Options -Indexes
ServerSignature Off


    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^ index.php [L]



    ExpiresActive On
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"

HTACCESS
echo "[OK] .htaccess olusturuldu"

# php.ini override olustur
PHP_INI="/var/www/${DOMAIN}/php.ini"
echo "upload_max_filesize = 64M" > "${PHP_INI}"
echo "post_max_size = 64M" >> "${PHP_INI}"
echo "max_execution_time = 120" >> "${PHP_INI}"
echo "memory_limit = 256M" >> "${PHP_INI}"
echo "display_errors = Off" >> "${PHP_INI}"
echo "log_errors = On" >> "${PHP_INI}"
echo "error_log = /var/log/php/${DOMAIN}_error.log" >> "${PHP_INI}"
echo "[OK] php.ini override olusturuldu: ${PHP_INI}"

echo "[INFO] Tum dosyalar basariyla olusturuldu."
echo "Domain     : ${DOMAIN}"
echo "Web Root   : ${WEB_ROOT}"
echo "htaccess   : ${WEB_ROOT}/.htaccess"
echo "PHP Config : ${PHP_INI}"

Sık Yapılan Hatalar

echo kullanımında yıllar içinde gördüğüm ve bizzat yaptığım hataları paylaşayım:

  • Tek tırnak ve çift tırnak karıştırmak: Değişken içeren stringleri tek tırnak içine almak, değişkenin expand edilmemesine yol açar. Her zaman bilinçli seç.
  • $? kontrolünü geciktirmek: $? sadece bir sonraki komutu çalıştırana kadar geçerli. echo $? demeden önce başka bir komut çalıştırırsan, o komutun çıkış kodunu görürsün.
  • Özel karakterleri escape etmemek: echo ile string içinde ! kullanmak Bash history expansion’ı tetikler. Özel karakterlerin önüne \ koy veya tek tırnak kullan.
  • -e flag’ini unutmak: veya kullanacaksan -e flag’ini eklemeyi unutma, yoksa bu karakterler olduğu gibi ekranda görünür.
  • >> yerine > kullanmak: Log dosyasına eklemek istediğinde > ile tüm log geçmişini silmek, en acı verici hatalardan biri.

Uyari: Eğer scriptlerini sudo ile çalıştırıyorsan ve echo ile kritik sistem dosyalarına yazıyorsan, her adımda bir yedek al. “sudo echo ‘bir sey’ > /etc/critical.conf” şeklindeki komutlar, yönlendirme operatörünün sudo kapsamı dışında kalması nedeniyle beklenmedik şekilde davranabilir. Bu durumda “sudo tee” kullanmak daha güvenlidir.

echo mi, printf mi?

Bu soruyu kaçınılmaz olarak soruyorsun. Kısa cevap: web sunucusu scriptlerinde echo genellikle yeterli. Ama şu durumlarda printf’e geç:

  • Farklı shell’lerde (sh, dash, zsh) çalışması gereken taşınabilir scriptler yazıyorsun
  • Sayısal formatlama gerekiyor (örneğin: %.2f ile ondalık basamak kontrolü)
  • Çıktıda kesin boşluk hizalaması önemli
  • Kaçış karakteri davranışının tutarlı olmasını garanti altına almak istiyorsun

Sonraki Adımlar

echo komutunu bu yazıda sıfırdan ele aldık ve web sunucusu yönetimindeki gerçek dünya kullanım senaryolarına baktık. Ama bu sadece bir başlangıç. echo’yu gerçekten verimli kullanmak için şu konulara da hakim olman gerekiyor:

  • tee komutu: Hem ekrana yazmak hem de dosyaya kaydetmek istediğinde echo | tee kombinasyonu hayat kurtarır. Özellikle sudo gerektiren dosyalara yazarken.
  • printf komutu: Taşınabilir ve formatlı çıktı için echo’nun daha güçlü alternatifi. C programcıları kendini evinde hisseder.
  • Heredoc (cat << EOF): Çok satırlı içerik üretirken echo’yu defalarca çağırmak yerine heredoc kullanmak çok daha temiz kod üretir.
  • Bash string manipülasyonu: ${DEGISKEN#prefix}, ${DEGISKEN%suffix} gibi parametre expansion teknikleri, echo ile birleştiğinde çok güçlü araçlara dönüşür.
  • Cron ile echo: Cron job’larında echo çıktısını log dosyasına yönlendirerek otomatik raporlama sistemi kurabilirsin.

Web sunucusu yönetiminde otomasyon ne kadar çok olursa, manuel hata riski o kadar azalır. echo komutunun bu kadar basit görünmesine aldanma — iyi yazılmış bir scriptte bu küçük komut, saatlik manuel işleri dakikalara indirir. Şimdi gidip kendi deploy scriptini yaz, içine biraz renk ekle ve terminal çıktısını güzelleştir. Bir dahaki deploy’da farkını göreceksin.

cat Komutu: Dosya İçeriği Görüntüleme ve Birleştirme Rehberi

Linux dünyasında her gün onlarca kez kullandığın cat komutu, göründüğünden çok daha yetenekli bir araç. Dosya okumaktan log analizi yapmaya, config birleştirmekten veri akışı oluşturmaya kadar uzanan geniş kullanım alanlarını gerçek sunucu senaryolarıyla anlattım.

Sysadmin olarak yıllar içinde fark ettim ki en basit araçlar çoğu zaman en fazla işe yarayan araçlar oluyor. cat komutu tam olarak böyle bir araç. İsmini “concatenate” yani birleştirme kelimesinden alıyor ama çoğu insan onu sadece dosya okumak için kullanıyor. Oysa bir web sunucusu yönetiyorsan, log dosyalarından config karşılaştırmalarına kadar pek çok kritik işte cat sana zaman kazandırır. Gelin bu komutu gerçekten tanıyalım.

cat Nedir ve Ne Yapar?

cat, Unix/Linux sistemlerde dosya içeriklerini standart çıktıya yazan temel bir araçtır. 1971’den bu yana Unix’in ayrılmaz bir parçası olan bu komut, POSIX standardının zorunlu araçları arasında yer alır. Yani hangi Linux dağıtımında çalışıyor olursan ol, cat orada seni bekliyor olacak. Nginx mi, Apache mi, Ubuntu mu, CentOS mu — fark etmez.

Temel söz dizimi son derece basit:

# Temel kullanim
cat [secenek] [dosya...]

# Tek dosya okuma
cat /etc/hostname

# Birden fazla dosya okuma
cat /etc/hostname /etc/os-release

# Standart girdi okuma (CTRL+D ile bitir)
cat

Bu kadar basit görünen bir komutun neden ayrı bir yazı hak ettiğini sorabilirsin. Cevap şu: cat’i sadece “dosya açma” komutu olarak görmek, bir tornavidayı sadece vida sıkmak için kullanmak gibi. Gelin seçeneklere ve gerçek senaryolara geçelim.

Temel Seçenekler ve Anlamları

cat komutunun fazla seçeneği yok ama olanlar oldukça işe yarıyor. Özellikle web sunucusu config dosyalarını incelerken bunları çok kullanacaksın.

SeçenekUzun HaliAçıklama
-n–numberTüm satırlara numara ekler
-b–number-nonblankSadece boş olmayan satırlara numara ekler
-s–squeeze-blankBirden fazla boş satırı tek boş satıra indirir
-A–show-allTüm görünmez karakterleri gösterir
-E–show-endsSatır sonlarını $ ile gösterir
-T–show-tabsTab karakterlerini ^I olarak gösterir
-v–show-nonprintingYazdırılamayan karakterleri gösterir

Bu seçenekleri pratikte nasıl kullandığını görelim. Özellikle -n ve -A seçenekleri web sunucusu config dosyalarında hata ayıklarken hayat kurtarıcı oluyor.

# Satir numaralariyla nginx config dosyasini oku
cat -n /etc/nginx/nginx.conf

# Apache virtual host dosyasini satir numaralariyla goster
cat -n /etc/apache2/sites-enabled/000-default.conf

# Gizli karakterleri goster (tab ve satir sonu dahil)
# Config dosyasinda sekme/bosluk karisikligini tespit etmek icin mukemmel
cat -A /etc/nginx/sites-available/mysite.conf

# Bos olmayan satirlara numara ekle, coklu boslugu sikistir
cat -bs /etc/nginx/nginx.conf

# Sadece satir sonlarini goster (Windows CRLF sorununu tespit et)
cat -E /etc/apache2/.htaccess

Ipucu: Windows’tan FTP ile yüklenen config dosyaları bazen CRLF satır sonları içerir. cat -A komutu bu satırların sonunda ^M$ gösterir. Apache veya Nginx bunu parse edemez ve seni saatlerce hata ayıklamaya mahkum eder. Bu yüzden config dosyalarını düzenlerken her zaman -A ile bir kontrol yap.

Web Sunucusu Log Dosyalarını Okumak

Web sunucusu yönetiminin en kritik parçalarından biri log okumaktır. Apache ve Nginx’in access log ile error log dosyaları, sitenle ne olduğunu anlaman için birincil kaynakların. cat burada genellikle diğer araçlarla birlikte pipeline içinde kullanılır.

# Nginx access log dosyasini oku
cat /var/log/nginx/access.log

# Apache error log dosyasini oku
cat /var/log/apache2/error.log

# Birden fazla log dosyasini birlestirip oku
# Ornegin: birden fazla virtual host logu tek seferde
cat /var/log/nginx/site1-access.log /var/log/nginx/site2-access.log

# Log icerigini grep ile filtrele - 500 hatalarini bul
cat /var/log/nginx/access.log | grep " 500 "

# Son 100 satiri bul (cat + tail kombinasyonu)
cat /var/log/apache2/error.log | tail -100

# IP adreslerine gore erisim sayisi (cat + awk + sort)
cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# Belirli bir tarih icin log satirlarini filtrele
cat /var/log/nginx/access.log | grep "14/Jan/2025"

Uyari: Büyük log dosyalarında cat kullanırken dikkatli ol. Gigabaytlarca büyümüş bir access.log dosyasını cat ile açmak terminali uzun süre kitleyebilir ve sisteme gereksiz I/O yükü bindirir. Bu tür durumlarda tail, less veya grep doğrudan daha iyi tercihlerdir. cat’i büyük dosyalar için pipeline’ın başında kullanmak yerine, grep veya awk’a doğrudan dosya argümanı vermek daha verimlidir.

Dosya Birleştirme: cat’in Asıl Gücü

cat komutunun adının nereden geldiğini hatırlıyor musun? Concatenate — birleştirme. İşte bu özelliği web sunucusu yönetiminde gerçekten çok işe yarıyor. SSL sertifika dosyalarını birleştirmek, birden fazla config parçasını tek dosyaya toplamak, yedek log dosyalarını arşivlemek gibi senaryolarda cat olmadan yaşayamazsın.

# SSL sertifika zinciri olusturma (en klasik kullanim senaryosu)
# Once site sertifikasi, sonra intermediate CA, sonra root CA
cat domain.crt intermediate.crt root.crt > fullchain.pem

# Sertifika ve ozel anahtari birlestir (bazı uygulamalar ister)
cat domain.crt domain.key > combined.pem

# Let's Encrypt ile manuel zincir olusturma
cat /etc/letsencrypt/live/example.com/cert.pem 
    /etc/letsencrypt/live/example.com/chain.pem > /etc/ssl/example_fullchain.pem

# Birden fazla .htaccess parcasini birlestir
cat htaccess-security.txt htaccess-redirects.txt htaccess-cache.txt > .htaccess

# Nginx include dosyalarini tek dosyada topla (debug icin)
cat /etc/nginx/conf.d/*.conf > /tmp/nginx-all-configs.txt

# Apache config parcalarini birlestir
cat /etc/apache2/conf-enabled/*.conf > /tmp/apache-merged.conf

Ipucu: SSL sertifika zinciri oluştururken sıralama kritiktir. Her zaman domain sertifikasını önce, root CA’yı en sona koy. Sırayı karıştırırsan tarayıcılar sertifikayı güvensiz olarak işaretler ve müşterilerinden şikayet gelmeye başlar.

Dosyaya Yazmak: Yönlendirme Operatörleriyle cat

cat komutunu yönlendirme operatörleriyle birlikte kullanmak, hızlı dosya oluşturma ve içerik ekleme için son derece pratik. Özellikle bir sunucuya bağlandığında editör kurmak istemediğin durumlarda ya da script içinde hızlıca bir dosya oluşturman gerektiğinde çok işe yarıyor.

# Yeni bir dosya olustur ve icerik gir (CTRL+D ile bitir)
cat > /etc/nginx/conf.d/custom-headers.conf

# Var olan dosyaya icerik ekle (ustune yazmaz)
cat >> /var/log/deployment.log

# Heredoc ile script icinde dosya olustur
cat > /etc/nginx/conf.d/security.conf < /etc/nginx/nginx.conf.backup

# Bos dosya olustur (touch gibi ama farklı)
cat /dev/null > /var/log/myapp/app.log

# Deployment notunu log dosyasina ekle
echo "=== Deployment: $(date) ===" | cat - /tmp/changelog.txt >> /var/log/deployment.log

Uyari: Tek büyüktür işareti ( > ) hedef dosyanın üzerine yazar ve eski içeriği siler. Bunu production ortamında yanlış dosyaya yönlendirirsen geri dönüşü olmayan veri kaybı yaşarsın. Her zaman iki kez kontrol et. Mümkün olduğunca önemli dosyalara yazmadan önce yedeğini al.

Gerçek Dünya Senaryo: Web Sunucusu Sorun Tespiti

Diyelim ki gece 2’de telefon çaldı, sitenin down olduğunu söylüyorlar. SSH ile sunucuya bağlandın. Tam olarak ne kullanacaksın? İşte bu noktada cat ve arkadaşları devreye giriyor.

# Adim 1: Nginx durumunu kontrol et
systemctl status nginx

# Adim 2: Son hatalara bak
cat /var/log/nginx/error.log | tail -50

# Adim 3: Config dosyasinda syntax sorunu var mi?
cat -n /etc/nginx/nginx.conf | grep -n "server_name|listen|root"

# Adim 4: Virtual host config dosyasini incele
cat -n /etc/nginx/sites-enabled/production.conf

# Adim 5: PHP-FPM soket/port ayarini kontrol et
cat /etc/nginx/sites-enabled/production.conf | grep fastcgi_pass

# Adim 6: PHP-FPM pool config ile eslesip eslesmedigini karsilastir
cat /etc/php/8.2/fpm/pool.d/www.conf | grep "^listen"

# Adim 7: Disk dolulugunu hizlica kontrol et (full disk = log yazamiyor = crash)
cat /proc/mounts | grep -v tmpfs
df -h

# Adim 8: Erisim logunda anormal trafik var mi?
cat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5

Bu akışı standart bir troubleshooting runbook’una koyabilirsin. Ekibindeki junior sysadmin’lere de öğrettiğinde, gece aramalarını azaltabilirsin.

Config Dosyası Karşılaştırma ve Yönetim

Web sunucusu yönetiminde config dosyaları kutsal metinler gibidir. Neyin ne zaman değiştiğini takip etmek, eski konfigürasyona dönmek ya da iki sunucu arasındaki farkı anlamak için cat’i diff ve diğer araçlarla birlikte sık kullanırsın.

# Mevcut nginx config ile yedeği karsilastir
diff <(cat /etc/nginx/nginx.conf) <(cat /etc/nginx/nginx.conf.backup)

# Iki sunucudaki config farkini bul (SSH uzerinden)
diff <(cat /etc/nginx/nginx.conf)  /tmp/all-nginx-configs.txt
cat /tmp/all-nginx-configs.txt

tac, zcat ve Türevleri: Bilmene Değer Kardeşler

cat’in bazı kardeşleri var ve bunlar da web sunucusu yönetiminde işe yarıyor. Bunları öğrenmek için ayrı saatler harcamana gerek yok ama isimlerini ve ne yaptıklarını bilmek, doğru zamanda doğru aracı seçmeni sağlar.

  • tac: cat’in tersine çalışır, dosyayı sondan başa okur. Log dosyasının son satırlarını önce görmek için kullanılır.
  • zcat: Sıkıştırılmış .gz dosyalarını açmadan okur. Rotasyon yapılmış log arşivlerini okurken hayat kurtarır.
  • bzcat: bzip2 ile sıkıştırılmış dosyaları okur.
  • xzcat: xz formatındaki dosyaları okur.
# Log dosyasini sondan basa oku (en yeni kayit once)
tac /var/log/nginx/access.log | head -20

# Rotasyon yapilmis gz logunu acmadan oku
zcat /var/log/nginx/access.log.1.gz

# Tum rotasyon loglarini birden ara
zcat /var/log/nginx/access.log.*.gz | grep "500"

# Eski ve yeni loglari birlestir
zcat /var/log/apache2/access.log.2.gz | cat - /var/log/apache2/access.log > /tmp/merged-access.log

# Log rotasyon arsivlerini tarih sirali birlestir
ls -t /var/log/nginx/access.log*.gz | xargs zcat | cat - /var/log/nginx/access.log > /tmp/full-history.log

Performans ve Dikkat Edilmesi Gerekenler

cat kullanırken bilmen gereken birkaç önemli nokta var. Bu noktaları göz ardı edersen, production ortamında istemediğin sonuçlarla karşılaşabilirsin.

Uyari: “Useless Use of Cat” (UUOC) olarak bilinen anti-pattern’den kaçın. Örneğin cat dosya | grep pattern yerine grep pattern dosya kullanmak hem daha hızlı hem de daha az sistem kaynağı tüketir. Büyük log dosyalarında bu fark önemli hale gelir.

Uyari: Binary dosyaları cat ile açmaya çalışma. Terminali bozabilir, beklenmedik kontrol karakterleri çalıştırabilir. Şüpheli bir dosyayı önce file komut ile kontrol et.

Ipucu: Büyük dosyalarla çalışırken cat yerine less veya more kullanmak terminali kitlemez ve geriye ileri gitme imkanı tanır. Sadece tüm içeriği pipeline’a aktarman gerektiğinde cat tercih et.

Sonraki Adımlar

cat komutunu artık sadece dosya açan bir araç olarak görmüyorsundur umarım. Web sunucusu yönetiminde bu komutu günlük rutininin bir parçası haline getirdiğinde, troubleshooting sürelerin kısalacak ve config yönetimi çok daha düzenli hale gelecek.

cat’i daha verimli kullanmak için şu araçları da öğrenmeni öneririm:

  • less ve more: Büyük dosyaları sayfalayarak okumak için. Özellikle GB’lık log dosyalarında cat’in yerini tutarlar.
  • grep: cat ile pipeline oluşturarak log filtreleme işlerini otomatize etmek için olmazsa olmaz.
  • awk ve sed: cat’ten gelen veriyi işlemek, dönüştürmek ve rapor oluşturmak için güçlü araçlar.
  • tail -f: Gerçek zamanlı log izleme için cat’in yerini tutan araç. Aktif bir web sunucusunda hataları anlık görmek için kullanılır.
  • diff: cat ile birleştirdiğinde config dosyalarını karşılaştırma süreçlerini otomatize edebilirsin.

Bir sonraki yazıda tail ve head komutlarını web sunucusu log yönetimi perspektifinden ele alacağım. O yazıda cat ile birlikte nasıl güçlü bir log analiz pipeline’ı oluşturabileceğini de göreceğiz. Sorularını yorumlara bırakabilirsin.

clear Komutu: Terminal Ekranını Temizleme ve Bilmen Gereken Her Şey

Terminal ekranın kaotik bir hale mi geldi? clear komutu ve Ctrl+L kısayolu günlük işlerini çok daha temiz hale getirir. Bu yazıda clear komutunun tüm inceliklerini, alternatiflerini ve sysadmin senaryolarındaki kullanımını ele alıyoruz.

Uzun bir troubleshooting seansının ardından terminale bakıyorsun ve ekran komut çıktılarıyla, hata mesajlarıyla, log satırlarıyla dolup taşmış durumda. Neyin nerede olduğunu bulmak için scroll yapıp duruyorsun. İşte tam bu noktada terminaldeki en basit ama en kurtarıcı komutlardan biri devreye giriyor: clear. Günde onlarca kez kullandığın bu küçük komutun aslında bilmediğin pek çok yönü var. Gelin hepsini konuşalım.

<!– wp:heading {

ln Komutu: Sembolik ve Sabit Bağlantı Oluşturma Rehberi

Linux sistem yönetiminin en temel araçlarından biri olan ln komutu, dosya ve dizinleri bağlantılar aracılığıyla yönetmeni sağlar. Web sunucularında konfigürasyon yönetiminden deployment süreçlerine kadar pek çok alanda işine yarayacak bu komutu baştan sona ele alıyoruz.

ln Komutu Nedir ve Neden Önemli?

Linux dünyasında çalışıyorsan, er ya da geç ln komutuyla yüzleşmek zorunda kalacaksın. Özellikle web sunucusu yönetiyorsan, bu komut senin en yakın dostlarından biri haline gelecek. Nginx veya Apache konfigürasyonlarını yönetirken, deployment scriptleri yazarken ya da paylaşılan kütüphaneleri düzenlerken ln olmadan işlerin çok daha zor olacağını garantiyle söyleyebilirim.

Temel mantığını şöyle açıklayayım: ln komutu, bir dosya ya da dizine başka bir isimden erişmeni sağlayan bağlantılar oluşturur. İki türü var: sembolik bağlantılar (symbolic links) ve sabit bağlantılar (hard links). Bunların arasındaki fark sandığından çok daha önemli, o yüzden ikisini de iyi anlamak gerekiyor.

Sabit Bağlantı (Hard Link) Nedir?

Sabit bağlantıyı anlamak için önce inode kavramını bilmen gerekiyor. Linux dosya sisteminde her dosyanın bir inode numarası vardır. Bu inode, dosyanın gerçek verisinin diskte nerede tutulduğunu, izinlerini, sahibini ve diğer meta verilerini saklar. Bir dosya adı aslında sadece bu inode numarasına bir referanstır.

Sabit bağlantı oluşturduğunda, aynı inode’a işaret eden ikinci bir dosya adı yaratmış olursun. Yani iki farklı isim, aynı veriye bakıyor. Orijinal dosyayı silsen bile, hard link varken veri diskten kalkmaz çünkü inode’a en az bir referans kaldığı sürece veri yaşamaya devam eder.

# Temel hard link oluşturma
ln /var/www/html/config.php /var/www/html/config_backup.php

# İki dosyanın aynı inode'a sahip olduğunu doğrula
ls -li /var/www/html/config.php /var/www/html/config_backup.php

Çıktıda her iki dosyanın da aynı inode numarasını göreceğini fark edeceksin. Bu, iki ismin gerçekten aynı veriye baktığının kanıtıdır.

Uyari: Sabit bağlantılar farklı dosya sistemleri (partition’lar) arasında çalışmaz. /home üzerindeki bir dosyaya /var üzerinden hard link oluşturamazsın. Bu sınırlamayı aklında tut.

Bilgi: Hard link’ler dizinler için oluşturulamaz. Sadece düz dosyalar (regular files) için geçerlidir. Dizin bağlantısı oluşturman gerekiyorsa sembolik bağlantı kullanman gerekecek.

Sembolik Bağlantı (Symbolic Link / Symlink) Nedir?

Sembolik bağlantı ise tamamen farklı bir mantıkla çalışır. Bir symlink, içinde başka bir dosyanın yolunu tutan özel bir dosyadır. Windows’taki kısayollara benzetebilirsin ama çok daha güçlü ve sistem düzeyinde entegre çalışıyor.

Symlink, farklı dosya sistemleri arasında çalışabilir, dizinlere link oluşturabilirsin ve orijinal dosya silindiğinde link kırık (dangling link) hale gelir. Bu son özellik hem avantaj hem dezavantajdır, duruma göre değerlendirmek gerekiyor.

# Temel sembolik bağlantı oluşturma (-s parametresi şart)
ln -s /var/www/html/sites/mysite.com /var/www/html/current

# Sembolik bağlantıyı doğrulama
ls -la /var/www/html/current
# Çıktı: lrwxrwxrwx 1 www-data www-data 28 ... current -> /var/www/html/sites/mysite.com

# Bağlantının nereye işaret ettiğini öğrenme
readlink /var/www/html/current
readlink -f /var/www/html/current  # Tam gerçek yolu gösterir

Çıktıdaki o ok işareti (->), dosyanın bir symlink olduğunu ve nereye işaret ettiğini gösterir. İzin kısmındaki “l” harfi de bu dosyanın bir link olduğunun göstergesidir.

Hard Link ve Symlink Karşılaştırması

ÖzellikHard LinkSembolik Link
Farklı dosya sistemiHayırEvet
Dizin bağlantısıHayırEvet
Orijinal silinirseVeri korunurLink kırılır
Farklı inodeHayır (aynı)Evet
Dosya boyutuOrijinalle aynıYol uzunluğu kadar
Web sunucu kullanımıNadirÇok yaygın

ln Komutunun Temel Parametreleri

Komutun sözdizimi şu şekildedir:

ln [SECENEK] KAYNAK HEDEF

# En sık kullanilan parametreler:
# -s : Sembolik link oluştur
# -f : Hedef varsa zorla üzerine yaz (force)
# -n : Hedef sembolik linkse dereferans etme
# -v : Ayrıntılı çıktı ver (verbose)
# -r : Göreceli sembolik link oluştur (relative)
# -b : Üzerine yazmadan önce yedek al (backup)

Mevcut Linki Güncellemek

Web sunucusu yönetiminde en sık karşılaşacağın senaryo, mevcut bir symlink’i güncellemektir. Örneğin yeni bir deployment yaptın ve “current” linkini yeni versiyona yönlendirmen gerekiyor.

# Yanlis yontem - bu hata verir ya da beklenmedik davranir
ln -s /var/www/html/releases/v2.0 /var/www/html/current

# Dogru yontem: -sfn kombinasyonu
ln -sfn /var/www/html/releases/v2.0 /var/www/html/current

# Detayli aciklama:
# -s : sembolik link
# -f : varsa uzerine yaz
# -n : hedef dizin linkse, onu takip etme

# Sonucu dogrula
ls -la /var/www/html/current

Uyari: -f parametresini -n olmadan kullanırsan ve hedef bir sembolik link ise, ln yeni linki hedefin içine oluşturabilir. Bu sessiz bir hatadır ve deployment’larında beklenmedik davranışlara yol açar. Her zaman -sfn kullan.

Web Sunucusu Senaryoları: Gerçek Hayattan Örnekler

Nginx: sites-available ve sites-enabled Yönetimi

Nginx kullanıyorsan bu pattern’i mutlaka biliyorsundur. Konfigürasyon dosyaları sites-available altında tutulur, aktif etmek için sites-enabled altına sembolik link oluşturulur. Bu yapı hem düzenli hem de güvenli bir yaklaşım sağlar.

# Yeni bir site konfigurasyonu olustur
nano /etc/nginx/sites-available/mysite.com

# Siteyi aktif et (sembolik link olustur)
ln -s /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/mysite.com

# Konfigurasyonu test et
nginx -t

# Nginx'i yeniden yukle
systemctl reload nginx

# Siteyi deaktif etmek icin linki sil (kaynak dosya kalir)
rm /etc/nginx/sites-enabled/mysite.com

# Tum aktif siteleri listele
ls -la /etc/nginx/sites-enabled/

Bu yaklaşımın güzelliği şu: sites-available altındaki konfigürasyonun kendisine hiç dokunmadan siteyi aktif/pasif edebiliyorsun. Bir şeyler ters giderse konfigürasyon hâlâ orada duruyor, sadece linki silip ekleyerek yönetiyorsun.

Apache: a2ensite ile Aynı Mantık

Apache’de a2ensite ve a2dissite komutları arka planda zaten ln kullanır. Ama bazen bunları bypass ederek doğrudan link oluşturman gerekebilir.

# Apache icin manuel sembolik link
ln -s /etc/apache2/sites-available/mysite.conf /etc/apache2/sites-enabled/mysite.conf

# Veya Apache'nin kendi aracini kullan (tercih edilen)
a2ensite mysite.conf
a2dissite mysite.conf

# SSL sertifikasi icin ornek link yapisi
ln -s /etc/letsencrypt/live/mysite.com/fullchain.pem /etc/ssl/certs/mysite.com.pem
ln -s /etc/letsencrypt/live/mysite.com/privkey.pem /etc/ssl/private/mysite.com.key

Zero-Downtime Deployment: Capistrano Tarzı

Bu senaryo gerçekten değerli. Bir web uygulamasını sıfır kesinti ile güncellemenin en klasik yolu sembolik link rotasyonudur. Capistrano, Deployer ve benzeri araçlar tam olarak bunu yapar.

# Dizin yapisi su sekilde olacak:
# /var/www/myapp/
#   releases/
#     20240101120000/
#     20240115093000/
#     20240120150000/  <- en yeni
#   shared/            releases/20240120150000  <- aktif versiyon

# Yeni deployment
NEW_RELEASE="/var/www/myapp/releases/$(date +%Y%m%d%H%M%S)"
mkdir -p $NEW_RELEASE

# Kodu kopyala / git clone yap
git clone https://github.com/user/myapp.git $NEW_RELEASE

# Paylasilan dizinleri linkle
ln -s /var/www/myapp/shared/uploads $NEW_RELEASE/public/uploads
ln -s /var/www/myapp/shared/.env $NEW_RELEASE/.env

# Yeni versiyonu aktif et (atomik islem)
ln -sfn $NEW_RELEASE /var/www/myapp/current

# Rollback icin bir onceki versiyona don
PREV_RELEASE=$(ls -t /var/www/myapp/releases/ | sed -n '2p')
ln -sfn /var/www/myapp/releases/$PREV_RELEASE /var/www/myapp/current
echo "Rollback tamamlandi: $PREV_RELEASE"

# Eski surumlerden sadece son 5'ini tut
cd /var/www/myapp/releases && ls -t | tail -n +6 | xargs rm -rf

Ipucu: ln -sfn ile symlink’i değiştirme işlemi atomiktir, yani yarım kalmaz. Bu yüzden Nginx veya Apache bu işlem sırasında asla kırık bir link görmez. Zero-downtime deployment’ın sırrı büyük ölçüde budur.

PHP Sürüm Yönetimi

Birden fazla PHP sürümü kurulu olan sunucularda hangi sürümün varsayılan olduğunu sembolik linklerle yönetebilirsin.

# Mevcut php linkini kontrol et
ls -la /usr/bin/php
readlink -f /usr/bin/php

# PHP 8.2'ye gec
update-alternatives --set php /usr/bin/php8.2

# Ya da manuel olarak:
ln -sfn /usr/bin/php8.2 /usr/local/bin/php

# PHP-FPM socket linkini kontrol et
ls -la /var/run/php/
# php-fpm.sock -> php8.2-fpm.sock gibi bir yapi gormeli

Göreceli ve Mutlak Yol Farkı

Sembolik link oluştururken mutlak yol mu göreceli yol mu kullanmalısın? Bu sorunun net bir cevabı var: genellikle mutlak yol kullanmak daha güvenlidir, ama bazı durumlarda göreceli yol tercih edilir.

# Mutlak yol ile sembolik link (tavsiye edilen)
ln -s /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/mysite.com

# Goreceli yol ile sembolik link
cd /etc/nginx/sites-enabled
ln -s ../sites-available/mysite.com mysite.com

# -r parametresi ile otomatik goreceli link
ln -sr /etc/nginx/sites-available/mysite.com /etc/nginx/sites-enabled/mysite.com

# Goreceli linkin icerigi
readlink /etc/nginx/sites-enabled/mysite.com
# Cikti: ../sites-available/mysite.com

Göreceli yollar, link ve hedef birlikte taşınacaksa mantıklıdır. Örneğin tüm yapıyı farklı bir sunucuya kopyalıyorsan göreceli linkler bozulmaz. Ama sabit bir sunucu yapısında mutlak yollar daha okunabilir ve sorun ayıklaması kolaydır.

Sık Karşılaşılan Sorunlar ve Çözümleri

Kırık Sembolik Linkler (Dangling Links)

Hedef dosya veya dizin silindiğinde symlink kırık kalır. Bunu tespit etmek ve temizlemek için şunları kullanabilirsin:

# Kirık linkleri bul
find /etc/nginx/sites-enabled -type l ! -exec test -e {} ; -print

# Daha kapsamlı arama
find /var/www -maxdepth 3 -xtype l 2>/dev/null

# Kirık linkleri otomatik sil (dikkatli kullan!)
find /etc/nginx/sites-enabled -type l ! -exec test -e {} ; -delete

# Link zinciri takibi
ls -la /etc/nginx/sites-enabled/mysite.com
readlink -f /etc/nginx/sites-enabled/mysite.com  # Son hedefi goster, kirıksa hata verir

Uyari: Kırık sembolik linkleri toplu silerken çok dikkatli ol. Özellikle /etc altında otomatik silme işlemi yapmadan önce mutlaka ne bulduğunu listele ve gözden geçir.

İzin Sorunları

Sembolik linkin izinleri her zaman lrwxrwxrwx görünür, bu normaldir. Önemli olan hedef dosyanın izinleridir. Ama link oluştururken de dikkat edilmesi gereken noktalar var:

# Link uzerindeki izinler (her zaman 777 gorunur, yaniltici olma)
ls -la /etc/nginx/sites-enabled/mysite.com
# lrwxrwxrwx 1 root root 42 Jan 20 15:00 mysite.com -> /etc/nginx/sites-available/mysite.com

# Asıl onemli olan hedef dosyanin izni
ls -la /etc/nginx/sites-available/mysite.com
# -rw-r--r-- 1 root root 1234 Jan 20 14:00 mysite.com

# www-data kullanicisi linke erisemiyorsa, hedefin izinlerini kontrol et
namei -l /etc/nginx/sites-enabled/mysite.com  # Tum yol boyunca izinleri goster

Log Yönetiminde ln Kullanımı

Web sunucularında log yönetimi de ln’nin sıkça kullanıldığı bir alan. Farklı lokasyonlardaki logları merkezi bir yere toplamak ya da logrotate yapısını düzenlemek için faydalanabilirsin.

# Dagitik loglari merkezi klasore topla
mkdir -p /var/log/webapps
ln -s /var/log/nginx/mysite.access.log /var/log/webapps/mysite-access.log
ln -s /var/log/nginx/mysite.error.log /var/log/webapps/mysite-error.log
ln -s /var/log/php8.2-fpm.log /var/log/webapps/php-fpm.log

# /dev/stdout ve /dev/stderr'a link - Docker konteynerlerinde yaygin
# Bazi uygulamalarda log dosyasini stdout'a yonlendirmek icin:
ln -sf /dev/stdout /var/log/nginx/access.log
ln -sf /dev/stderr /var/log/nginx/error.log

Bilgi: Docker imajlarında /dev/stdout’a sembolik link oluşturmak yaygın bir pattern’dir. Bu sayede uygulama log dosyasına yazarken aslında container loglarına yazıyor, docker logs komutuyla takip edebiliyorsun.

Özet: Ne Zaman Hangisini Kullanmalısın?

Pratikte bakacak olursan, web sunucusu yönetiminde neredeyse her zaman sembolik link kullanırsın. Hard link’lerin kullanım alanı daha çok yedekleme araçları ve dosya sistemi düzeyindeki optimizasyonlardır. Ama ikisini de bilmek işinin gereğidir.

  • Nginx/Apache site konfigürasyonlarını aktif/pasif etmek icin sembolik link kullan
  • Zero-downtime deployment ve versiyon yönetimi icin sembolik link kullan
  • Birden fazla yerde erişilmesi gereken paylaşılan konfigürasyon dosyaları icin sembolik link kullan
  • Log merkezi yönetimi icin sembolik link kullan
  • Yedekleme araçları (rsync –hard-links gibi) disk alanı optimizasyonu icin hard link kullan
  • Orijinal silindiğinde verinin kaybolmamasını istediğin durumlarda hard link kullan

Sonraki Adımlar

ln komutunu iyi kavradıktan sonra deployment otomasyonu tarafına bakmanı tavsiye ederim. Bash ile basit bir deployment scripti yazmak, ln -sfn komutunu gerçek ortamda nasıl kullanacağını somutlaştıracak. Bunun yanında inotifywait ile symlink değişikliklerini izleyebileceğini, rsync’in –copy-links ve –keep-dirlinks parametreleriyle link’leri nasıl ele aldığını ve logrotate’in postrotate scriptlerinde ln kullanımını da araştırabilirsin. Bir sonraki yazıda Nginx’in sites-available/sites-enabled yapısını sıfırdan kurarak üzerine otomatik SSL entegrasyonu eklemeyi ele alacağım.

touch Komutu: Dosya Oluşturma ve Zaman Damgası Değiştirme

touch komutu göründüğünden çok daha güçlü bir araç. Sadece boş dosya oluşturmakla kalmıyor, web sunucusu yönetiminde kritik öneme sahip zaman damgası işlemlerini de üstleniyor. Bu yazıda touch komutunu her yönüyle inceliyoruz.

Sysadmin kariyerinde bir noktada şunu fark ediyorsun: en basit görünen komutlar çoğu zaman en çok işe yarayan komutlar oluyor. touch da tam olarak bu kategoride. “Ne kadar karmaşık olabilir ki, dosya oluşturuyorsun işte” diye düşünebilirsin. Ama web sunucusu yönetimi söz konusu olduğunda bu küçük komut seni ciddi baş ağrılarından kurtarabilir, ya da yanlış kullanırsan ciddi sorunlara davet edebilir. Hadi konuya girelim.

touch Komutu Nedir ve Ne Yapar?

touch, temel olarak iki işi yapan bir komut. Birincisi, var olmayan bir dosyayı oluşturur. İkincisi, var olan bir dosyanın erişim (access) ve değiştirme (modification) zaman damgalarını günceller. Çoğu insan sadece birinci kullanımı bilir ama asıl güç ikincisinde.

Man page’e baktığında seni karşılayan tanım şudur: “touch — change file timestamps”. Dosya oluşturmak aslında bir yan etki. Eğer belirttiğin dosya yoksa, touch onu oluşturur. Varsa, sadece zaman damgasını günceller. Bu ayrımı aklında tutmak önemli.

Temel Kullanım: Dosya Oluşturma

En basit kullanımıyla başlayalım. Web sunucusu ortamında sıklıkla boş dosya oluşturman gerekir. Maintenance sayfaları, lock dosyaları, pid dosyaları veya sadece test amaçlı placeholder dosyalar…

# Tek dosya oluşturma
touch maintenance.html

# Birden fazla dosyayı tek seferde oluşturma
touch index.html style.css app.js

# Belirli bir dizinde dosya oluşturma
touch /var/www/html/.maintenance

# Birden fazla log dosyası oluşturma
touch /var/log/myapp/{error,access,debug}.log

Süslü parantez kullanımına dikkat et. Bu bash’ın brace expansion özelliği ve touch ile birleşince çok kullanışlı bir hal alıyor. Tek komutla birden fazla dosya oluşturabiliyorsun.

Bilgi: touch ile oluşturulan dosya tamamen boştur, 0 byte boyutundadır. İçine bir şey yazmak istiyorsan farklı komutlara ihtiyacın olacak. touch sadece dosyanın var olmasını sağlar.

Zaman Damgaları: Asıl Mesele Burada

Linux’ta her dosyanın üç tür zaman damgası vardır. Bunları bilmeden touch’ı gerçek anlamda kullanamazsın.

Zaman DamgasıKısaltmaNe Zaman Değişir?touch ile Değişir mi?
Access TimeatimeDosya okunduğundaEvet (-a ile)
Modification Timemtimeİçerik değiştiğindeEvet (-m ile)
Change TimectimeMetadata değiştiğindeDolaylı olarak

touch varsayılan olarak hem atime’ı hem de mtime’ı şu anki zamana günceller. ctime ise her zaman otomatik güncellenir çünkü bir şeyleri değiştirdiğinde dosyanın metadata’sı da değişmiş olur.

Mevcut Zaman Damgalarını Görüntüleme

Önce mevcut durumu nasıl göreceğini bilelim. stat komutu bu iş için biçilmiş kaftan:

# Dosyanın tüm zaman damgalarını göster
stat /var/www/html/index.html

# Örnek çıktı:
#   File: /var/www/html/index.html
#   Size: 10674     Blocks: 24         IO Block: 4096   regular file
# Device: fd00h/64768d    Inode: 785432      Links: 1
# Access: (0644/-rw-r--r--)  Uid: (   33/www-data)   Gid: (   33/www-data)
# Access: 2024-01-15 14:23:45.123456789 +0300
# Modify: 2024-01-14 09:15:22.987654321 +0300
# Change: 2024-01-14 09:15:22.987654321 +0300

# Sadece modification time'ı görmek için
date -r /var/www/html/index.html

touch Seçenekleri ve Parametreler

Komutun seçeneklerine geçelim. Bunları bilmeden touch’ın yarısını kullanmıyorsun demektir.

# Sadece access time'ı güncelle (-a)
touch -a /var/www/html/index.html

# Sadece modification time'ı güncelle (-m)
touch -m /var/www/html/index.html

# Dosya yoksa oluşturma, sadece varsa güncelle (-c veya --no-create)
touch -c /var/www/html/opsiyonel-dosya.html

# Belirli bir zaman damgası belirt (-t)
# Format: [[CC]YY]MMDDhhmm[.ss]
touch -t 202401150930.00 /var/www/html/index.html

# Belirli bir tarihi string olarak belirt (-d)
touch -d "2024-01-15 09:30:00" /var/www/html/index.html
touch -d "yesterday" /var/www/html/index.html
touch -d "2 hours ago" /var/www/html/index.html
touch -d "next monday" /var/www/html/index.html

# Başka bir dosyanın zaman damgasını kopyala (-r)
touch -r /var/www/html/referans.html /var/www/html/hedef.html

Ipucu: -d seçeneği oldukça esnek bir format kabul ediyor. “yesterday”, “last week”, “2 hours ago” gibi insan okunabilir ifadeler de çalışıyor. Bu özelliği özellikle test senaryolarında çok işe yarar buluyorum.

Web Sunucusu Senaryolarında Gerçek Dünya Kullanımı

Teoriden pratiğe geçelim. Web sunucusu yönetiminde touch’ı en çok nerede ve nasıl kullanıyorsun, bunlara bakalım.

1. Maintenance Modu Lock Dosyası

Laravel, Symfony gibi PHP framework’leri maintenance modunu genellikle bir dosyanın varlığına göre kontrol eder. touch burada biçilmiş kaftan:

# Laravel maintenance modunu aktif et (manuel yöntem)
touch /var/www/html/myapp/storage/framework/down

# Birden fazla sanal sunucu için aynı anda maintenance aç
for site in site1 site2 site3; do
    touch /var/www/html/${site}/storage/framework/down
    echo "${site} maintenance moduna alindi"
done

# Maintenance bitti, lock dosyasını kaldır
rm /var/www/html/myapp/storage/framework/down

# Nginx için maintenance flag dosyası
touch /var/run/nginx-maintenance
# nginx.conf'ta bu dosyanın varlığını kontrol edip 503 döndürebilirsin

2. PHP-FPM ve Nginx Cache Yönetimi

Web sunucusu caching mekanizmaları zaman damgalarına büyük önem verir. mtime değiştiğinde cache geçersiz sayılır. Bu davranışı touch ile kontrol edebilirsin:

# PHP-FPM'i yeniden başlatmadan opcache'i temizlemek için
# (bazı yapılandırmalarda dosya değişikliği opcache invalidation'ı tetikler)
touch /var/www/html/myapp/public/index.php

# Nginx fastcgi_cache'i belirli dosyalar için geçersiz kıl
# cache key dosyasının timestamp'ini güncelle
touch /var/cache/nginx/cache-purge-trigger

# Tüm PHP dosyalarının mtime'ını güncelle (dikkatli kullan!)
find /var/www/html/myapp -name "*.php" -exec touch {} ;

# Sadece belirli bir dizindeki dosyaları güncelle
find /var/www/html/myapp/app -name "*.php" -maxdepth 2 -exec touch {} ;

Uyari: find ile birlikte toplu touch kullanımı çok sayıda dosyayı etkiler. Production ortamında bunu yapmadan önce tam olarak ne yapacağını bildiğinden emin ol. Yanlış dizinde çalıştırırsan beklenmedik cache invalidation sorunlarıyla karşılaşabilirsin.

3. Log Dosyası Yönetimi

Yeni bir web uygulaması deploy ederken log dosyalarının önceden oluşturulmuş ve doğru izinlerle hazır olması gerekir. Uygulama başladığında log dosyası yoksa hata verebilir:

# Uygulama log dosyalarını oluştur ve izinleri ayarla
LOG_DIR="/var/log/mywebapp"

# Dizini oluştur
mkdir -p ${LOG_DIR}

# Log dosyalarını oluştur
touch ${LOG_DIR}/error.log
touch ${LOG_DIR}/access.log
touch ${LOG_DIR}/slow-query.log

# Sahipliği ve izinleri ayarla
chown -R www-data:www-data ${LOG_DIR}
chmod 640 ${LOG_DIR}/*.log

# Doğrulama
ls -la ${LOG_DIR}/

4. Deployment Script’lerinde touch Kullanımı

CI/CD pipeline’larında ve deployment script’lerinde touch oldukça sık kullanılır. İşte tipik bir deployment senaryosu:

#!/bin/bash
# deploy.sh - Basit web uygulaması deployment scripti

APP_DIR="/var/www/html/myapp"
DEPLOY_TIME=$(date +%Y%m%d_%H%M%S)

echo "[${DEPLOY_TIME}] Deployment basliyor..."

# 1. Maintenance modunu aktif et
touch ${APP_DIR}/storage/framework/down
echo "Maintenance modu aktif"

# 2. Yeni kodları cek (git, rsync vb.)
git -C ${APP_DIR} pull origin main

# 3. Config dosyalarının varlığını garantile
touch ${APP_DIR}/.env
touch ${APP_DIR}/storage/logs/laravel.log

# 4. Cache dosyalarının timestamp'ini güncelle
# Bu sayede PHP opcache yeni kodu alacak
find ${APP_DIR}/bootstrap/cache -name "*.php" -exec touch {} ;

# 5. Deployment zaman damgasını kaydet
touch ${APP_DIR}/storage/deployed_at
echo "Son deployment: ${DEPLOY_TIME}" > ${APP_DIR}/storage/deployed_at

# 6. Maintenance modunu kapat
rm -f ${APP_DIR}/storage/framework/down
echo "Deployment tamamlandi. Maintenance modu kapatildi."

Zaman Damgasını Taklit Etmek: Dikkatli Ol

touch’ın güçlü özelliklerinden biri geçmişe veya geleceğe tarih atayabilmek. Bu özellik bazen meşru ihtiyaçlar için kullanılır, örneğin bir dosyayı eski bir yedeğe senkronize etmek. Ama aynı zamanda kötüye kullanılabilecek bir özellik.

# Dosyayı belirli bir tarihe "götür"
touch -d "2023-06-15 12:00:00" /var/www/html/eski-icerik.html

# Bir dosyanın zaman damgasını başka bir dosyayla eşitle
# Örnek: yedekten gelen dosyayla production'ı senkronize et
touch -r /backup/2024/index.html /var/www/html/index.html

# Belirli bir formatta zaman damgası ata
# Format: CCYYMMDDhhmm.ss
touch -t 202406151200.00 /var/www/html/special-file.html

Uyari: Dosya zaman damgalarını manipüle etmek güvenlik loglarını ve audit trail’leri bozabilir. Forenzik inceleme gerektiren sistemlerde ya da compliance zorunluluğu olan ortamlarda zaman damgasını geriye almak ciddi sorunlara yol açabilir. Bu özelliği ne zaman ve neden kullandığını belgele.

Atomik Dosya Oluşturma ve Race Condition

Yüksek trafikli web sunucularında birden fazla process aynı anda çalışıyor olabilir. touch’ın atomik olmayan bir operasyon olduğunu bilmek gerekiyor. Yani iki process aynı anda aynı dosyayı oluşturmaya çalışırsa race condition oluşabilir. Lock mekanizması için touch’a güvenmemelisin.

Bunun yerine gerçek lock dosyası oluşturma için daha güvenilir yöntemler var:

# touch ile basit varlık kontrolü (lock için YETERSİZ)
if [ ! -f /tmp/myapp.lock ]; then
    touch /tmp/myapp.lock  # Race condition riski var!
    # işlemler...
    rm /tmp/myapp.lock
fi

# Daha güvenilir lock için flock kullan
flock -n /tmp/myapp.lock -c "bash /var/www/html/myapp/cron/cleanup.sh"

# Ya da mkdir kullan (atomik operasyon)
if mkdir /tmp/myapp.lockdir 2>/dev/null; then
    echo $$ > /tmp/myapp.lockdir/pid
    # işlemler...
    rm -rf /tmp/myapp.lockdir
else
    echo "Baska bir process calisıyor, cikiliyor."
    exit 1
fi

Bilgi: mkdir operasyonu atomiktir çünkü işletim sistemi seviyesinde tek bir sistem çağrısıyla gerçekleşir. Bu yüzden lock mekanizması olarak mkdir, touch’a göre çok daha güvenilirdir. Bu küçük ama önemli bir fark.

Otomatik Görevlerde touch Kullanımı

Cron job’larında ve otomatik bakım scriptlerinde touch sıklıkla kullanılır. İşte birkaç pratik örnek:

# Crontab'dan çalışacak bir bakım scripti
#!/bin/bash
# /usr/local/bin/webserver-health-check.sh

HEALTH_FILE="/var/run/webserver-health"
LOG_FILE="/var/log/health-check.log"

# Nginx çalışıyor mu kontrol et
if systemctl is-active --quiet nginx; then
    # Sağlık dosyasının timestamp'ini güncelle
    # Monitoring sistemi bu dosyanın tarihini izleyebilir
    touch ${HEALTH_FILE}
    echo "$(date): Nginx sagliklı" >> ${LOG_FILE}
else
    # Dosyayı silme veya güncelleme, monitoring alarm verir
    echo "$(date): Nginx calısmiyor! Alarm!" >> ${LOG_FILE}
    # Alert gönder
    /usr/local/bin/send-alert.sh "Nginx down" "critical"
fi

# Log dosyasını rotasyona hazırla
# Son güncelleme üzerinden 7 gün geçmişse sıfırla
find ${LOG_FILE} -mtime +7 -exec sh -c 'cat /dev/null > {}' ;

Sık Yapılan Hatalar

Yıllar içinde gördüğüm ve bizzat yaptığım bazı hataları paylaşayım:

  • Var olan bir dosyayı touch’lamak içeriğini silmez ama aklından çıkarabilir. Dosyayı truncate etmek istiyorsan farklı bir yöntem kullanmalısın.
  • touch için hedef dizin mevcut olmalıdır. Dizin yoksa touch hata verir. Önce mkdir -p ile dizini oluştur.
  • touch’ın başarıyla çalışması için ilgili dizinde write iznine ihtiyacın var. Web sunucusu dizinlerinde root veya www-data olarak çalışman gerekebilir.
  • Symlink’leri touch’larken dikkatli ol. Varsayılan olarak touch symlink’in kendisini değil, işaret ettiği dosyayı günceller. Symlink’in kendisini güncellemek için -h veya –no-dereference seçeneğini kullan.
  • NFS mount edilmiş dosya sistemlerinde zaman senkronizasyon sorunları olabilir. touch -t ile kesin bir zaman belirtmek bazen daha güvenlidir.

Hızlı Referans Tablosu

SecenekUzun HaliAçıklamaÖrnek
-a–time=atimeSadece access time güncelletouch -a dosya.txt
-m–time=mtimeSadece modification time güncelletouch -m dosya.txt
-c–no-createDosya yoksa oluşturmatouch -c dosya.txt
-d–date=STRINGString ile tarih belirttouch -d “yesterday” dosya.txt
-tTimestamp formatıyla tarih belirttouch -t 202401150930 dosya.txt
-r–reference=DOSYAReferans dosyanın zamanını kullantouch -r ref.txt hedef.txt
-h–no-dereferenceSymlink’in kendisini güncelletouch -h link.txt

Özet

touch komutu basit görünür ama web sunucusu yönetiminde düşündüğünden çok daha fazla yerde karşına çıkar. Maintenance lock dosyaları, cache invalidation, log dosyası hazırlama, deployment scriptleri… Bunların hepsi touch’ın doğal habitatı. Özellikle zaman damgası manipülasyonu özelliğini ve -r, -d seçeneklerini bilmek seni ortalama kullanıcıdan bir adım öne çıkarır.

En önemli nokta şu: touch’ı bir lock mekanizması olarak kullanma. Race condition’lara açık. Bunun için flock veya mkdir kullan. Geri kalan her şeyde touch oldukça güvenilir ve hızlı bir araç.

Sonraki Adımlar

touch’ı sindirdiysen, birlikte çok güzel çalıştığı araçlara da bakmanı öneririm:

  • stat komutu: Dosya zaman damgalarını ve metadata’yı detaylı görüntülemek için
  • find komutu: Zaman damgasına göre dosya aramak için (-mtime, -atime, -newer seçenekleri)
  • flock komutu: Gerçek dosya kilitleme mekanizması için
  • inotifywait: Dosya değişikliklerini gerçek zamanlı izlemek için
  • logrotate: Log dosyası rotasyonunu otomatikleştirmek için

Bu araçları birlikte öğrenmek, web sunucusu yönetiminde dosya operasyonlarını çok daha verimli yapmanı sağlayacak. Her biri ayrı bir yazı konusu, sırasıyla ele alacağız.

rm Komutu ile Dosya Silme: Web Sunucusunda Güvenli Kullanım Rehberi

Linux’ta rm komutu basit görünür ama yanlış kullanıldığında web sunucunu dakikalar içinde çökertebilir. Bu yazıda rm’nin tüm inceliklerini, güvenli kullanım yöntemlerini ve gerçek sunucu senaryolarını ele alıyoruz.

Linux dünyasında bazı komutlar vardır ki görünürde masum, ama elinde patlayacak dinamit gibidir. rm komutu da tam olarak bu kategoriye girer. Web sunucusu yönetiyorsan ve terminale “rm -rf /” yazarsan ne olacağını merak ediyorsan, cevap şu: bir daha o sunucuyu göremezsin. Abartmıyorum.

Ama paniklemene de gerek yok. rm komutu doğru anlaşıldığında ve doğru kullanıldığında vazgeçilmez bir araçtır. Eski log dosyalarını temizlemek, geçici upload dosyalarını silmek, eski deployment kalıntılarını ortadan kaldırmak — bunların hepsinde rm kullanırsın. Bu yazıda hem temel kullanımı hem de bir web sunucusu yöneticisi olarak günlük hayatta karşılaşacağın gerçek senaryoları ele alacağız.

rm Komutu Nedir ve Nasıl Çalışır?

rm, “remove” kelimesinin kısaltmasıdır ve Linux/Unix sistemlerde dosya ile dizinleri silmek için kullanılır. Windows’taki Delete tuşundan temel farkı şudur: silinen dosyalar Geri Dönüşüm Kutusu’na gitmez. Silinen dosya gider, noktası.

Teknik olarak konuşmak gerekirse, rm komutu dosyanın kendisini değil, dosya sistemindeki inode bağlantısını siler. Eğer o dosyaya başka hard link yoksa, inode ve veri blokları serbest bırakılır. Bu yüzden bazen özel araçlarla (extundelete, testdisk gibi) silinen dosyaları kurtarmak mümkün olabilir — ama buna güvenerek çalışma, her silme işlemini geri dönüşü olmayan bir işlem olarak gör.

Temel Söz Dizimi

rm komutunun temel kullanımı son derece sade:

rm [seçenekler] [dosya/dizin]

# Tek dosya silmek
rm dosya.txt

# Birden fazla dosya silmek
rm dosya1.txt dosya2.txt dosya3.log

# Belirli bir pattern ile silmek
rm *.log

# Belirli bir dizindeki tüm .tmp dosyalarını silmek
rm /var/www/html/uploads/*.tmp

Bu kadar basit. Ama işte tam burada dikkatli olmak gerekiyor. Yukarıdaki son komuta bak: /var/www/html/uploads dizinindeki tüm .tmp dosyalarını silmek istiyorsun. Eğer yanlışlıkla bir boşluk karakteri koyarsan ya da dizin adını yanlış yazarsan, sonuçlar beklenmedik olabilir.

Önemli Parametreler ve Anlamları

ParametreUzun HaliNe Yapar?
-r–recursiveDizini ve içindeki her şeyi siler
-f–forceVar olmayan dosyalar için hata vermez, onay istemez
-i–interactiveHer silme işleminden önce onay ister
-I–interactive=once3’ten fazla dosya veya -r kullanılıyorsa bir kez onay ister
-v–verboseHer silinen dosyayı ekrana yazar
-d–dirBoş dizinleri siler (rmdir gibi)

Web Sunucusunda Gerçek Kullanım Senaryoları

Teoriyi bir kenara bırakalım ve asıl konuya gelelim: web sunucusu yönetirken rm’yi nerede, nasıl kullanırsın?

Senaryo 1: Eski Log Dosyalarını Temizleme

Nginx veya Apache çalıştırıyorsun ve /var/log dizini dolmaya başladı. Disk dolunca web sunucusu yeni bağlantılara cevap veremez hale gelir. Bu yüzden log rotasyonu ve temizliği kritik önem taşır. Logrotate kullanıyor olsan bile, bazen manuel müdahale gerekir:

# 30 günden eski nginx access log dosyalarını bul ve sil
find /var/log/nginx/ -name "access.log.*" -mtime +30 -exec rm -v {} ;

# 7 günden eski tüm .gz uzantılı sıkıştırılmış logları sil
find /var/log/apache2/ -name "*.gz" -mtime +7 -exec rm -v {} ;

# Silmeden önce ne silineceğini gör (dry-run)
find /var/log/nginx/ -name "*.log.*" -mtime +30 -print

Ipucu: rm’yi doğrudan find ile kullanmadan önce mutlaka -print ile ne silineceğini gör. Bu alışkanlık seni bir gün büyük bir felaketten kurtarabilir.

Senaryo 2: Upload Klasöründeki Geçici Dosyaları Temizleme

PHP tabanlı bir web uygulaması çalıştırıyorsun ve kullanıcılar dosya yüklüyor. Yarım kalan yüklemeler, işlenmeyi bekleyen geçici dosyalar, hatalı upload’lar zamanla birikir. Bunu düzenli olarak temizlemek hem disk alanı hem de güvenlik açısından önemli.

# /var/www/html/uploads dizinindeki 24 saatten eski .tmp dosyalarını sil
find /var/www/html/uploads/ -name "*.tmp" -mtime +1 -exec rm -f {} ;

# Boş dizinleri de temizle
find /var/www/html/uploads/ -type d -empty -exec rm -d {} ;

# İşlem sonrası ne kadar yer açıldığını kontrol et
df -h /var/www/

Senaryo 3: Eski Deployment Dosyalarını Kaldırma

Manuel veya CI/CD ile deployment yapıyorsan, eski versiyonlar birikebilir. Bir WordPress güncellemesinden sonra eski plugin dosyalarını temizlemek ya da manuel olarak yüklediğin eski bir PHP uygulamasının kalıntılarını kaldırmak gerekebilir:

# Eski deployment klasörünü sil (dikkatli ol, önce ls ile kontrol et)
ls -la /var/www/
rm -rf /var/www/app_v1.2.3/

# Aktif deployment sembolik linkini değiştirmeden önce eski versiyonu kaldır
rm -rf /var/www/releases/20231101120000/

# Belirli dosya uzantılarını recursive olarak sil (örn: .bak dosyaları)
find /var/www/html/ -name "*.bak" -type f -delete

Uyari: rm -rf komutunu çalıştırmadan önce mutlaka pwd ile hangi dizinde olduğunu kontrol et ve silmek istediğin yolu tam olarak belirt. Eksik bir slash, yanlış bir dizin adı büyük sorunlara yol açabilir.

rm -rf: Güçlü Ama Tehlikeli

Bu parametre kombinasyonunu ayrıca ele almak istiyorum çünkü en çok kullanılan ve en tehlikeli olanı bu. -r recursive (alt dizinlerle birlikte), -f ise force (onay istemeden, hata görmezden gelerek) demek. İkisini birleştirdiğinde önüne gelen her şeyi süpüren bir komut elde edersin.

Gerçek bir hikaye anlatayım: Bir sysadmin, eski bir web uygulamasını kaldırmak için şu komutu çalıştırmak istiyor: rm -rf /var/www/eski-uygulama. Ama yanlışlıkla araya bir boşluk giriyor: rm -rf /var/www/ eski-uygulama. Bu durumda sistem önce /var/www/ dizinini, ardından eski-uygulama adlı dosyayı silmeye çalışır. /var/www/ dizininin tüm içeriği gider.

Uyari: rm -rf komutunu root kullanıcısı olarak çalıştırırken son derece dikkatli ol. Modern Linux sistemleri rm -rf / komutunu –no-preserve-root parametresi olmadan çalıştırmana izin vermez, ama bu seni her şeyden korumaz. /var/www, /etc, /home gibi kritik dizinlerde rm -rf kullanmadan önce iki kez düşün.

Güvenli rm Kullanımı için Pratik Yöntemler

1. -i Parametresi ile Onaylı Silme

Eğer kritik bir dizinde çalışıyorsan ve tam olarak emin değilsen, -i parametresini kullan. Her dosya için senden onay ister:

# Her silme için onay iste
rm -i *.log

# Recursive silme için bir kez onay iste (-I büyük harf)
rm -rI /var/www/eski-klasor/

# Önce ne silineceğini listele, sonra karar ver
ls -la /var/www/html/cache/
rm -riv /var/www/html/cache/

2. Alias ile Güvenli rm Tanımla

Bazı sysadminler rm komutunu doğrudan çağırmak yerine, her zaman onaylı çalışması için alias tanımlar. Bu özellikle yeni başlayan ekip üyeleri için iyi bir pratiktir:

# ~/.bashrc veya ~/.bash_aliases dosyasına ekle
alias rm='rm -i'

# Alias'ı aktif et
source ~/.bashrc

# Eğer bir kez onaysız çalıştırmak istersen
rm -rf /gecici/klasor/
# veya
command rm -rf /gecici/klasor/

Bilgi: Alias tanımladıktan sonra rm komutunun her zaman -i ile çalışacağını unutma. Script’lerin içinde rm kullanıyorsan, orada da bu davranışı dikkate alman gerekir. Script’lerde genellikle rm veya command rm kullanmak daha güvenlidir.

3. trash-cli: Geri Dönüşüm Kutulu rm Alternatifi

Eğer silme işlemlerinde biraz güvenlik ağı istiyorsan, trash-cli aracını kullanabilirsin. Bu araç dosyaları direkt silmek yerine önce bir çöp klasörüne taşır:

# trash-cli kur (Debian/Ubuntu)
apt install trash-cli

# Dosyayı çöpe gönder
trash-put /var/www/html/gereksiz-dosya.php

# Çöp kutusunu listele
trash-list

# Çöp kutusunu boşalt
trash-empty

# Yanlış sildiysen kurtar
trash-restore

Production sunucularda trash-cli kullanmak tartışmalı bir konu. Disk dolma riskini artırır, ama kritik dosyaların yanlışlıkla silinmesi riskini azaltır. Ekibinin deneyim seviyesine göre karar ver.

Web Sunucusunda Sık Yapılan Hatalar

Yıllar içinde gördüğüm, işittiğim ve ne yazık ki zaman zaman yaşadığım hataları listeleyelim:

  • Dizin değişkeninin boş olması: rm -rf $APP_DIR/ komutunda APP_DIR değişkeni boşsa rm -rf / çalışır
  • Wildcard’ı yanlış kullanmak: rm *.php gibi bir komut mevcut dizindeki tüm PHP dosyalarını siler, hangi dizinde olduğundan emin ol
  • Sembolik linklerin hedefini silmek: rm -rf ile sembolik bir dizini silmeye çalışırken hedef dizini de silebilirsin
  • root olarak çalışırken dikkatsiz olmak: sudo ile çalışırken sistem dosyalarını silmek çok kolaydır
  • Production ve test sunucularını karıştırmak: Birden fazla terminal penceresi açık tutup yanlış pencerede komut çalıştırmak

Bash Script’lerinde rm Kullanımı

Otomatik temizlik script’leri yazarken rm’yi kullanmak kaçınılmaz. Ama script içinde rm kullanırken daha da dikkatli olmak gerekiyor, çünkü bir hata tüm sistemde otomatik olarak çalışabilir.

#!/bin/bash
# Güvenli temizlik scripti örneği

set -euo pipefail  # Hata durumunda dur, tanımsız değişkende dur

# Değişkenleri tanımla
WEB_ROOT="/var/www/html"
LOG_DIR="/var/log/nginx"
MAX_AGE_DAYS=30

# Kritik kontrol: değişken boş mu?
if [ -z "$WEB_ROOT" ] || [ -z "$LOG_DIR" ]; then
    echo "HATA: Dizin değişkenleri boş olamaz!"
    exit 1
fi

# Dizin var mı kontrol et
if [ ! -d "$WEB_ROOT/cache" ]; then
    echo "Cache dizini bulunamadı, atlanıyor."
else
    echo "Cache temizleniyor..."
    find "$WEB_ROOT/cache" -type f -mtime +1 -delete
    echo "Cache temizlendi."
fi

# Eski logları temizle
echo "$MAX_AGE_DAYS günden eski loglar temizleniyor..."
find "$LOG_DIR" -name "*.gz" -mtime +$MAX_AGE_DAYS -exec rm -v {} ;

echo "Temizlik tamamlandi."
df -h $WEB_ROOT $LOG_DIR

Ipucu: Script’lerin başına set -euo pipefail eklemek iyi bir alışkanlıktır. -e herhangi bir komut hata verirse script’i durdurur, -u tanımlanmamış değişkeni kullanmaya çalışırsan hata verir, -o pipefail ise pipeline’daki hataları yakalar. Bu üç ayar, rm içeren otomatik script’lerde kritik öneme sahiptir.

Silinen Dosyaları Kurtarma Girişimi

Teorik olarak ele alalım: yanlışlıkla bir dosyayı sildiysen ne yaparsın? Önce paniği bırak, sonra adım adım düşün.

  • Dosya hala açık bir process tarafından kullanılıyorsa /proc/[pid]/fd/ üzerinden kurtarılabilir
  • ext4 dosya sisteminde testdisk veya extundelete araçlarıyla kurtarma denenebilir
  • Disk üzerine yeni yazma yapılmadan önce ne kadar hızlı müdahale edersen o kadar iyi
  • En güvenli çözüm her zaman yedeğe dönmektir — backupsuz çalışma
# Açık dosya tanımlayıcılarını kontrol et
# Silinmiş ama hala açık olan dosyaları gösterir
lsof | grep deleted

# Eğer process bulunursa, içeriği kurtar
# Örnek: PID 1234, fd 3 numaralı dosya tanımlayıcısı
cat /proc/1234/fd/3 > /tmp/kurtarildi.txt

# Dosya sistemi durumunu kontrol et (unmount gerekir)
# extundelete sadece unmount edilmiş partition üzerinde çalışır
extundelete /dev/sda1 --restore-all

Uyari: Silme işlemi sonrası kurtarma denemesi yaparken hedef partition’a asla yeni veri yazma. Kurtarmayı farklı bir disk üzerine yap. Her yeni yazma işlemi silinen verinin üzerine yazabilir ve kalıcı kayba yol açar.

rm ve Web Sunucusu Güvenliği

Web sunucusu yönetirken rm komutunu güvenlik bağlamında da düşünmek gerekiyor. Saldırganlar web uygulamasına sızdığında bazen dosyaları silmeye çalışabilir ya da zararlı dosyalar bırakabilir. Bu yüzden özellikle kritik web dizinlerinde dosya izinlerini doğru yapılandırmak önemli.

Öte yandan, web uygulamasının kendisinin rm komutunu tetikleyecek shell komutları çalıştırıp çalıştıramayacağını da kontrol altında tutmalısın. PHP uygulamalarında exec(), system(), passthru() gibi fonksiyonların mümkünse devre dışı bırakılması veya en azından kısıtlanması gerekir.

Hizli Referans: rm Komutunun En Sık Kullanılan Formları

KomutNe Yapar?Ne Zaman Kullan?
rm dosya.txtTek dosya silerBelirli bir dosyayı silerken
rm -i dosya.txtOnay sorarak silerKritik dizinlerde çalışırken
rm -f dosya.txtHata vermeden silerScript’lerde, dosya olmayabilir
rm -r dizin/Dizini recursive silerDizin kaldırırken
rm -rf dizin/Onaysız recursive silerEmin olduğunda hızlı temizlikte
rm -v dosya.txtVerbose, işlemi gösterirNe silindiğini takip ederken
rm — -dosya.txtTire ile başlayan dosyayı silerÖzel isimli dosyalarda

Ozet

rm komutu Linux sistemlerde dosya ve dizin silmenin temel yoludur. Basit söz dizimine karşın, özellikle web sunucusu ortamlarında yanlış kullanıldığında ciddi hasara yol açabilir. -r ve -f parametrelerini birlikte kullanırken her zaman dikkatli ol, değişken tabanlı yolları doğrula, ve önemli işlemlerden önce ne sileceğini gözden geçir.

Otomatik script’lerde set -euo pipefail kullanmak, değişken boşluk kontrolü yapmak ve silme öncesi find ile önizleme almak gibi alışkanlıklar, zamanla seni büyük felaketlerden koruyacak. Ayrıca ne kadar deneyimli olursan ol, backup almayı ihmal etme — rm’nin geri alınamaz olduğunu her zaman aklında tut.

Sonraki Adimlar

rm komutuna hakim olduysan, sıradaki adımlar şunlar olabilir:

  • find komutu ile rm’yi birlikte kullanmayı derinlemesine öğren, karmaşık temizlik senaryolarını handle etmek için gerekli
  • rsync ile yedekleme kurarak silme işlemleri öncesi güvenli bir ağ oluştur
  • logrotate yapılandırmasını öğren, log dosyalarını manuel rm ile silmek yerine otomatize et
  • cron job’ları ile düzenli temizlik script’leri yaz ve bunları rm yerine find -delete kombinasyonuyla güvenli hale getir
  • ZFS veya Btrfs gibi snapshot destekleyen dosya sistemlerini araştır, anlık görüntüler sayesinde yanlış silme işlemlerini kolayca geri alabilirsin

mkdir Komutu: Dizin Oluşturma ve Gelişmiş Kullanımı

mkdir komutu göründüğünden çok daha güçlü bir araç. Temel dizin oluşturmanın ötesine geçip, iç içe yapılar, izin yönetimi ve web sunucusu kurulumlarında nasıl kullanacağını bu yazıda adım adım ele alıyoruz.

Sysadmin olarak günde kaç kez mkdir yazıyorsun? Muhtemelen o kadar çok ki artık düşünmeden yapıyorsun. Ama şunu sormam lazım: mkdir‘ın bütün yeteneklerini gerçekten kullanıyor musun? Çoğu kişi bu komutu sadece tek bir dizin oluşturmak için kullanıyor ve olayı orada kapatıyor. Oysa mkdir, doğru kullanıldığında seni onlarca tekrarlayan komuttan kurtarabilir, özellikle web sunucusu kurulumlarında hayat kurtarıcı oluyor.

Bu yazıda mkdir’ı sıfırdan ele alacağız. Temel kullanımdan başlayıp, gelişmiş seçeneklere, gerçek web sunucusu senaryolarına ve sık yapılan hatalara kadar her şeyi konuşacağız. Hazırsan başlayalım.

mkdir Nedir ve Ne İşe Yarar?

mkdir, “make directory” yani “dizin oluştur” anlamına gelir. Linux, macOS ve Windows’ta (hem CMD hem PowerShell üzerinden) kullanılabilen temel bir komuttur. Görevi basit: belirttiğin yerde dizin oluşturmak. Ama bu basit görevin arkasında, işini çok daha verimli yapmanı sağlayacak bir sürü parametre var.

Özellikle web sunucusu yönetimi yapıyorsan — Apache, Nginx, ya da Node.js tabanlı bir şey kuruyorsan — dizin yapılarını doğru ve hızlı oluşturmak kritik. Yanlış izinle oluşturulmuş bir dizin, saat başı dönen bir destek talebi demek. Bunu yaşadın mı biliyorum, herkes yaşadı.

Temel Kullanım

En basit haliyle mkdir şöyle çalışır:

# Tek bir dizin oluştur
mkdir mywebsite

# Tam yol belirterek dizin oluştur
mkdir /var/www/mywebsite

# Aynı anda birden fazla dizin oluştur
mkdir logs uploads cache temp

Bu kadar basit. Ama dikkat et: eğer oluşturmaya çalıştığın dizinin üst dizini yoksa, mkdir hata verir. Mesela /var/www/mywebsite/public oluşturmak istiyorsan ve mywebsite henüz yoksa, komut çakılır. İşte burada -p bayrağı devreye giriyor.

-p Parametresi: En Çok Kullandığın Seçenek Olacak

-p parametresi (“parents” yani üst dizinler) olmayan tüm üst dizinleri otomatik olarak oluşturur. Üstelik zaten var olan bir dizin için hata vermez — bunu özellikle belirtmek istiyorum çünkü script yazarken bu davranış kritik önem taşır.

# İç içe dizin yapısını tek komutla oluştur
mkdir -p /var/www/mywebsite/public_html

# Birden fazla iç içe yapı aynı anda
mkdir -p /var/www/mywebsite/{public_html,logs,ssl,backup}

# Daha karmaşık bir web projesi yapısı
mkdir -p /var/www/myproject/{public,src/{controllers,models,views},config,logs,tests}

Son komuta dikkat et. Süslü parantez genişletmesi (brace expansion) ile tek bir satırda tüm proje iskeletini oluşturuyorsun. Bu bash’ın bir özelliği, mkdir’ın değil — ama ikisini birlikte kullanınca gerçekten güçlü bir kombinasyon elde ediyorsun.

💡İpucu: Brace expansion’ı kullanırken süslü parantezler arasında boşluk bırakma. {public, src} değil {public,src} yazmalısın. Boşluk bırakırsan bash bunu tek bir string olarak yorumlar ve beklediğin sonucu alamazsın.

-m Parametresi: Dizini Oluştururken İzinleri Ayarla

Bu parametre, özellikle web sunucusu kurulumlarında seni ayrı bir chmod adımından kurtarır. Dizini oluştururken aynı anda izinlerini de belirleyebilirsin.

# 755 izniyle dizin oluştur (web dizinleri için yaygın)
mkdir -m 755 /var/www/mywebsite

# 700 izniyle gizli/hassas dizin oluştur
mkdir -m 700 /var/www/mywebsite/private

# -p ile birlikte kullanım
mkdir -m 755 -p /var/www/mywebsite/public_html

# Yalnızca sahibinin okuyabileceği log dizini
mkdir -m 600 /var/www/mywebsite/secure_logs
Uyarı: -m parametresini -p ile birlikte kullandığında dikkatli ol. -m yalnızca en son oluşturulan (hedef) dizine uygulanır, ara üst dizinlere değil. Üst dizinlerin izinleri umask değerinden etkilenir. Kritik ortamlarda her dizinin iznini ayrıca doğrula.

-v Parametresi: Ne Olduğunu Gör

-v (verbose) parametresi, oluşturulan her dizin için ekrana bilgi yazar. Script yazarken veya büyük bir yapı oluştururken gerçekten ne yapıldığını görmek istiyorsan bu bayrağı ekle.

# Verbose mod ile dizin oluştur
mkdir -pv /var/www/newsite/{public_html,logs,ssl}

# Örnek çıktı:
# mkdir: created directory '/var/www/newsite'
# mkdir: created directory '/var/www/newsite/public_html'
# mkdir: created directory '/var/www/newsite/logs'
# mkdir: created directory '/var/www/newsite/ssl'

Özellikle büyük otomasyonlarda ya da bir junior’a bir şeyler anlatırken verbose mod çok işe yarıyor. Ne oluşturuldu, ne oluşturulmadı — her şey gözünün önünde.

Tüm Parametreler Hızlı Başvuru Tablosu

ParametreUzun AdAçıklamaÖrnek
-p--parentsEksik üst dizinleri de oluşturur, var olanlar için hata vermezmkdir -p /a/b/c
-m--modeDizin izinlerini belirler (chmod formatında)mkdir -m 755 /dir
-v--verboseHer oluşturulan dizin için mesaj yazarmkdir -v /dir
-ZSELinux bağlamını varsayılana ayarlarmkdir -Z /dir
--helpYardım metnini gösterirmkdir --help
--versionSürüm bilgisini gösterirmkdir --version

Gerçek Dünya Senaryosu 1: Apache Web Sunucusu Kurulumu

Yeni bir Apache sanal sunucusu (virtual host) kuruyorsun. Standart dizin yapısını elle tek tek oluşturmak yerine aşağıdaki script’i kullan. Bu benim yıllardır kullandığım, ufak tefek geliştirdiğim bir yaklaşım.

#!/bin/bash
# Apache sanal sunucusu için dizin yapısı oluşturma scripti

DOMAIN="example.com"
WEBROOT="/var/www"
WWW_USER="www-data"

# Ana dizin yapısını oluştur
mkdir -pv ${WEBROOT}/${DOMAIN}/{public_html,logs,ssl,backup}

# Log dizini için özel izinler
mkdir -m 750 -p ${WEBROOT}/${DOMAIN}/logs

# Public HTML için doğru izinler
chmod 755 ${WEBROOT}/${DOMAIN}/public_html

# Sahipliği web sunucusu kullanıcısına ver
chown -R ${WWW_USER}:${WWW_USER} ${WEBROOT}/${DOMAIN}

# Doğrulama
ls -la ${WEBROOT}/${DOMAIN}/
echo "Dizin yapısı ${DOMAIN} için oluşturuldu."

Bu script’i /usr/local/bin/setup-vhost.sh olarak kaydedip çalıştırılabilir yaparsan, her yeni domain için tek satırla kullanabilirsin. Domain adını değişken olarak geçirmek istersen script’e parametre desteği eklemek de çok basit.

Gerçek Dünya Senaryosu 2: Nginx + PHP-FPM Projesi

Nginx kullananlar için biraz farklı bir yapı tercih ediliyor. Özellikle PHP-FPM ile çalışıyorsan, socket dosyası için ayrı bir dizin, önbellek için ayrı bir alan lazım.

# Nginx + PHP-FPM projesi için tam dizin yapısı
PROJECT="myapp"

mkdir -pv /var/www/${PROJECT}/{public,storage/{logs,cache,sessions,uploads},config}

# PHP-FPM socket dizini
mkdir -m 710 -p /run/php/${PROJECT}

# Nginx önbellek dizini
mkdir -m 755 -p /var/cache/nginx/${PROJECT}

# İzinleri ayarla
chown -R www-data:www-data /var/www/${PROJECT}/storage
chmod -R 775 /var/www/${PROJECT}/storage

# Yapıyı görüntüle
find /var/www/${PROJECT} -type d | sort
Bilgi: Laravel gibi PHP framework’leri kullanıyorsan, storage dizininin altındaki klasörlerin www-data tarafından yazılabilir olması şart. Yoksa session, cache ve log sorunlarıyla karşılaşırsın. mkdir -m 775 ile oluşturmak bu sorunu baştan çözer.

Gerçek Dünya Senaryosu 3: Node.js / Next.js Projesi

Node.js tabanlı bir uygulama deploy ediyorsun. PM2 ile çalışıyorsa log dosyaları için, statik dosyalar için ve uploads için yapıyı önceden kurmak işleri kolaylaştırır.

# Node.js projesi için dizin yapısı
APP_NAME="nextjs-app"
APP_DIR="/var/www/${APP_NAME}"

# Ana yapı
mkdir -pv ${APP_DIR}/{current,releases,shared/{logs,uploads,config}}

# PM2 log dizini
mkdir -m 755 -p /home/deploy/.pm2/logs

# Nginx statik dosyalar için
mkdir -m 755 -p /var/www/${APP_NAME}/public/static

# Sahiplik ataması (deploy kullanıcısı varsayılıyor)
chown -R deploy:deploy ${APP_DIR}
chown -R www-data:www-data ${APP_DIR}/public

echo "Node.js proje yapısı hazır: ${APP_DIR}"

Windows’ta mkdir: PowerShell ve CMD

Windows tarafında iş yapıyorsan da mkdir komutu var, hem CMD hem PowerShell’de çalışır. Ama davranış biraz farklı, bunu bilmekte fayda var.

CMD’de mkdir ve md aynı şeydir. -p bayrağına gerek yok, CMD varsayılan olarak üst dizinleri oluşturur:

# PowerShell ile tek dizin
New-Item -ItemType Directory -Path "C:inetpubmysite"

# PowerShell ile iç içe dizin yapısı (-Force var olan dizinde hata vermez)
New-Item -ItemType Directory -Force -Path "C:inetpubmysitelogs"
New-Item -ItemType Directory -Force -Path "C:inetpubmysiteuploads"
New-Item -ItemType Directory -Force -Path "C:inetpubmysitessl"

# mkdir alias'ı PowerShell'de de çalışır
mkdir -Force "C:inetpubmysitepublic"

# Birden fazla dizin oluştur (döngüyle)
$dirs = @("logs", "uploads", "ssl", "backup", "config")
foreach ($dir in $dirs) {
    New-Item -ItemType Directory -Force -Path "C:inetpubmysite$dir"
    Write-Host "Oluşturuldu: C:inetpubmysite$dir"
}
Bilgi: PowerShell’de mkdir aslında New-Item -ItemType Directory komutunun bir alias’ıdır. Her ikisi de aynı işi yapar ama script’lerde okunabilirlik açısından tam adını kullanmak daha iyidir.

Sık Yapılan Hatalar ve Çözümleri

Hata 1: “cannot create directory: No such file or directory”

Üst dizin yok, -p kullanmadın. Çözüm basit:

# Hatalı kullanım
mkdir /var/www/site/public_html  # /var/www/site henüz yok

# Doğru kullanım
mkdir -p /var/www/site/public_html

Hata 2: “Permission denied”

Hedef konumda yazma izniniz yok. sudo kullanman ya da doğru kullanıcıya geçmen gerekiyor:

# Permission denied aldığında
sudo mkdir -p /var/www/mysite

# Sonra kendi kullanıcına veya www-data'ya sahipliği ver
sudo chown -R $USER:$USER /var/www/mysite
# ya da
sudo chown -R www-data:www-data /var/www/mysite

Hata 3: Yanlış İzinle Oluşturulmuş Dizin

Umask değerin beklenenden farklı izinler üretebilir. Özellikle shared hosting ortamlarında ya da özelleştirilmiş sunucularda bu başını ağrıtabilir.

# Mevcut umask değerini kontrol et
umask

# Dizin oluşturduktan sonra izni kontrol et
ls -ld /var/www/mysite

# İzni düzelt
chmod 755 /var/www/mysite

# Alternatif: Kesin izinle mkdir kullan
mkdir -m 755 -p /var/www/mysite
Uyarı: Web dizinlerinde asla 777 izni kullanma. Bu, sunucudaki herhangi bir kullanıcının veya güvenlik açığı yoluyla saldırganın dizine yazmasına izin verir. Web sunucusu için standart olan 755 (dizinler) ve 644 (dosyalar) kombinasyonu çoğu durumda yeterlidir. Özel yazma ihtiyacı varsa sahipliği doğru kullanıcıya ata.

Bonus: Tarih Bazlı Log Dizinleri Oluşturma

Log yönetimi yapıyorsan, tarihe göre otomatik dizin oluşturmak çok işe yarıyor. Bunu cron job’a bağlarsan her gece otomatik olarak çalışır.

#!/bin/bash
# Tarih bazlı log dizini oluşturma - cron'a eklenebilir

LOG_BASE="/var/log/myapp"
DATE=$(date +%Y/%m/%d)

# Bugünün tarihine göre dizin oluştur
mkdir -pv "${LOG_BASE}/${DATE}"

# Sahipliği ayarla
chown www-data:www-data "${LOG_BASE}/${DATE}"

# 30 günden eski log dizinlerini sil
find ${LOG_BASE} -type d -mtime +30 -exec rm -rf {} + 2>/dev/null

echo "Log dizini hazır: ${LOG_BASE}/${DATE}"

Bu script’i /etc/cron.daily/ altına koyarsan sistem her gece otomatik çalıştırır. Hem yeni dizini hazırlar hem de eski logları temizler.

Özet

mkdir, basit görünümünün arkasında güçlü bir araç. Özellikle şu noktaları aklında tut:

  • -p parametresi olmadan çalışıyorsan eksik kalıyorsun. Her script’inde kullan.
  • -m ile izinleri baştan belirle, sonradan chmod ile uğraşma.
  • -v parametresi, özellikle otomasyonda debug için çok değerli.
  • Brace expansion ile tek komutta karmaşık dizin yapıları oluşturabilirsin.
  • Web sunucusu dizinlerinde izin yönetimini asla ihmal etme; 777 kesinlikle hayır.
  • Windows’ta mkdir çalışır ama PowerShell’de New-Item -ItemType Directory -Force tercih edilmeli.

Sonraki Adımlar

mkdir’ı kavradıktan sonra sıradaki adımlar şunlar olabilir:

  • chmod ve chown: Dizin izinlerini ve sahipliğini tam anlamıyla kontrol etmeyi öğren. mkdir ile başladığın iş, bu komutlarla tamamlanıyor.
  • find komutu: Oluşturduğun dizin yapılarını yönetmek, aramak ve toplu işlemler yapmak için şart.
  • Bash scripting: mkdir tek başına güçlü ama bir script içinde değişkenler, döngüler ve koşullarla birleşince gerçek gücünü ortaya koyuyor.
  • rsync ile dizin senkronizasyonu: Oluşturduğun yapıları sunucular arasında taşımak için rsync’i incele.
  • ACL (Access Control Lists): Temel chmod izinlerinin yetmediği durumlarda, ACL ile daha ince izin yönetimi yapabilirsin.

Sorun yaşıyorsan ya da farklı bir senaryon varsa yorumlarda anlat, bakıp yanıtlarım. Sysadmin dünyasında kimse her şeyi tek başına öğrenmez, paylaşmak meseleye dahil.