Bash tools
TEKNİK REHBER BASH TOOLS UZAK SİSTEM 2026

SSH, SCP
ve rsync.

Anahtar üretmekten ~/.ssh/config alias'larına, tünel açmaktan mirror eşitlemeye — uzak sistemle dosya ve komut alışverişinin tam rehberi.

00 SSH mental modeli

SSH (Secure Shell) şifreli bir tünel açar ve bu tünelden hem komut çalıştırır hem dosya aktarır.

  İstemci                              Sunucu
  ─────────────────────────────────────────────────────
  ssh kullanıcı@host

    1. TCP bağlantısı kur (port 22)
    2. SSH versiyon handshake
    3. Anahtar değişimi (DH/ECDH) → oturum anahtarı
    4. Sunucu kimliği doğrula (known_hosts)
    5. İstemci kimlik doğrula:
         a. public key auth  → tercih edilen
         b. password auth    → daha zayıf
    6. Şifreli kanal kuruldu
    7. Kabuk veya komut çalıştır
    

SSH bağlantısı kurulduktan sonra her şey şifrelenir. SCP ve rsync da aynı SSH tünelini kullanır — ayrıca şifreleme yapmaz, SSH'ı kullanır.

PASSWORD vs PUBLIC KEY AUTH

Parola ile giriş brute-force saldırısına açık. Public key auth'ta sunucu sadece ortak anahtarın kimliğini doğrular; özel anahtar asla ağdan geçmez. Prodüksiyonda parola auth'u devre dışı bırak: PasswordAuthentication no (sshd_config).

01 ssh-keygen — anahtar üret

Bir anahtar çifti oluştur: özel anahtar sende kalır, ortak anahtar sunucuya gider.

bash
# Modern ve önerilen: ed25519
ssh-keygen -t ed25519 -C "ali@work-laptop"

# RSA (geriye dönük uyumluluk gerektiriyorsa 4096 bit)
ssh-keygen -t rsa -b 4096 -C "ali@legacy-server"

# Farklı dosyaya kaydet (birden fazla anahtar yönetmek için)
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_github -C "github"
-t tip
anahtar tipi: ed25519 (modern, kısa), rsa (eski uyumluluk), ecdsa, dsa (kullanma).
-b bit
RSA için anahtar uzunluğu. 2048 minimum, 4096 iyi pratik. ed25519 için anlamsız (sabit uzunluk).
-C yorum
ortak anahtar sonuna eklenen yorum. Kim oluşturdu, nereden olduğu için kullanışlı.
-f dosya
varsayılan yerine bu yola kaydet. Birden fazla anahtar varsa şart.
-N passphrase
anahtar parolası. Boş string için -N "". Parola koyarsan özel anahtarı şifreler — çalıntı anahtara karşı ek koruma.
bash
# Oluşan dosyalar
~/.ssh/id_ed25519       ← özel anahtar (600 izni, kimseye verme)
~/.ssh/id_ed25519.pub   ← ortak anahtar (sunucuya kopyalanır)

# Ortak anahtarı göster
cat ~/.ssh/id_ed25519.pub
# → ssh-ed25519 AAAA...uzun_baz64... ali@work-laptop
ÖZEL ANAHTARI ASLA PAYLAŞMA

~/.ssh/id_ed25519 — bu dosya bilgisayarından çıkmamalı. Parolasız bir özel anahtara sahip olan biri, sunucularına erişebilir. Güvenli yedek alıyorsan şifreli arşivle (veya parola koy).

ssh-agent — passphrase'i bir kez gir

bash
# Agent'i başlat (zaten çalışıyorsa atla)
eval "$(ssh-agent -s)"

# Anahtarı agent'e ekle (bir kez passphrase sorar)
ssh-add ~/.ssh/id_ed25519

# Yüklü anahtarları listele
ssh-add -l

02 Anahtarı sunucuya kopyala

Ortak anahtarın sunucudaki ~/.ssh/authorized_keys dosyasına eklenmesi gerekir.

bash
# En kolay yol — ssh-copy-id
ssh-copy-id kullanici@sunucu

# Belirli anahtar dosyası ile
ssh-copy-id -i ~/.ssh/id_ed25519.pub kullanici@sunucu

# ssh-copy-id yoksa (macOS, bazı sistemler) elle kopyala
cat ~/.ssh/id_ed25519.pub | ssh kullanici@sunucu \
  'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'
NE OLUYOR

ssh-copy-id ortak anahtarı (.pub) alır ve sunucudaki ~/.ssh/authorized_keys dosyasına ekler. Bir sonraki ssh bağlantısında sunucu bu dosyayı okur, özel anahtarınla kriptografik olarak eşleşiyor mu diye kontrol eder. Eşleşiyorsa parola sormadan girer.

authorized_keys dosyası

~/.ssh/authorized_keys
# Her satır bir ortak anahtar
ssh-ed25519 AAAA...abc... ali@laptop
ssh-ed25519 AAAA...xyz... ali@work-desktop
# Kısıtlama: sadece belirli bir komut çalıştırabilsin
command="rsync --server ..." ssh-ed25519 AAAA...ghi... rsync-backup-key
İzin sorunları

~/.ssh/ dizini 700, authorized_keys dosyası 600 olmalı. Aksi halde sshd bu dosyaları güvensiz sayarak yok sayar. chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys

03 ~/.ssh/config — alias ve seçenekler

Her sunucu için ayrı ayrı flag yazmak yerine config dosyasında bir kez tanımla.

~/.ssh/config
# Genel ayarlar (tüm host'lar için)
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    AddKeysToAgent yes

# Üretim sunucusu alias'ı
Host prod
    HostName 203.0.113.10
    User deploy
    IdentityFile ~/.ssh/id_ed25519_prod
    Port 2222

# Bastion üzerinden erişim (ProxyJump)
Host internal
    HostName 10.0.0.50
    User alice
    ProxyJump bastion
    IdentityFile ~/.ssh/id_ed25519

Host bastion
    HostName 203.0.113.1
    User alice
    IdentityFile ~/.ssh/id_ed25519

# Bağlantı tekrar kullanımı (ControlMaster)
Host dev-server
    HostName dev.example.com
    User dev
    ControlMaster auto
    ControlPath ~/.ssh/cm_%r@%h:%p
    ControlPersist 10m
Host takmaad
alias: ssh prod dediğinde bu bloğun ayarları uygulanır.
HostName
gerçek IP ya da hostname.
User
varsayılan kullanıcı. Artık ssh user@host yazmana gerek yok.
IdentityFile
bu host için kullanılacak özel anahtar dosyası.
Port
varsayılan 22 dışında bir port.
ProxyJump
önce bu host'a bağlan, oradan hedef host'a zıpla (bastion/jump host). -J flag'inin config karşılığı.
ControlMaster auto
aynı host'a ikinci bağlantıda yeni handshake yapmaz, var olan tüneli kullanır — çok hızlı.
ControlPersist 10m
son oturum kapandıktan 10 dakika tüneli açık tut.
ServerAliveInterval
N saniyede bir keepalive gönder — idle bağlantı kopmalarını önler.
bash
# Artık kısa kullanım
ssh prod              # → deploy@203.0.113.10:2222
ssh internal          # → bastion üzerinden 10.0.0.50
scp dosya.txt prod:~/ # → alias çalışır

04 ssh ile komut çalıştırma

ssh sadece interaktif kabuk açmaz — uzakta tek bir komut veya pipeline çalıştırabilir.

bash
# Uzakta komut çalıştır, çıktı yerel stdout'a gelir
ssh prod 'df -h'
ssh prod 'systemctl status nginx'

# Uzakta pipeline
ssh prod 'tail -n 100 /var/log/app.log | grep ERROR'

# -t: interaktif TTY gerekiyorsa (sudo, vi, top gibi)
ssh -t prod 'sudo journalctl -f'

# -N: komut çalıştırma, sadece tünel aç (port forwarding için)
ssh -N -L 8080:localhost:80 prod

# Uzaktaki komutu yerel pipe'a bağla
ssh prod 'cat /var/log/app.log' | grep 'ERROR' | tail -20

# Yerel dosyayı uzak komuta gönder
cat yerel.sql | ssh prod 'mysql -u root mydb'
-t
pseudo-TTY tahsis et. sudo, vim, htop gibi interaktif komutlar için gerekli — aksi halde "stdin is not a tty" hatası alırsın.
-N
uzakta kabuk açma, sadece bağlantıyı kur. Port forwarding yaparken kullanışlı.
-f
arka planda çalıştır (-N ile birlikte kullanılır). ssh -fN -L ...
ÇIKTI YÖNLENDIRME

Uzak komutun stderr'i de yerel stderr'e akar: ssh prod 'komut' 2>&1 | grep ... ile uzak stderr'i de pipeline'a dahil edebilirsin.

05 Port yönlendirme — -L, -R, -D

SSH tüneli ağ bağlantısı da taşıyabilir. Üç yön: local, remote, dynamic (SOCKS).

-L (Local port forward) — uzak servise yerel eriş

bash
# Yerel 8080'i, prod üzerindeki localhost:80'e yönlendir
ssh -L 8080:localhost:80 prod

# Sonra: http://localhost:8080 → prod'daki nginx

# Üçüncü bir sunucuya yönlendirme
ssh -L 5432:db-internal:5432 bastion
# Yerel 5432 → bastion → db-internal:5432 (yerel psql bağlanabilir)

-R (Remote port forward) — yerel servise uzaktan eriş

bash
# Sunucudaki 9000 portunu, yereldeki localhost:3000'e yönlendir
ssh -R 9000:localhost:3000 prod

# Sonra: prod'da curl http://localhost:9000 → senin yerel dev sunucun
# Webhook test etmek için idealdir

-D (Dynamic SOCKS proxy)

bash
# SOCKS5 proxy: tüm trafiği SSH tünelinden geçir
ssh -D 1080 prod

# Sonra: tarayıcı veya curl'de SOCKS5 proxy = localhost:1080 ayarla
curl --socks5 localhost:1080 http://internal-only-site/

# Arka planda çalıştır
ssh -fND 1080 prod
FlagYönKullanım
-L yerel:uzak_host:uzak_portYerel → UzakUzaktaki servise yerel erişim (DB, admin UI)
-R uzak_port:yerel_host:yerel_portUzak → YerelDev sunucunu dışarıya aç, webhook test
-D yerel_portSOCKS proxyTüm trafiği tünellemek, kısıtlı ağdan çıkmak

06 scp — dosya kopyalama

scp (Secure Copy) SSH üzerinden dosya kopyalar. Sözdizimi cp'ye benzer, kaynak veya hedef uzak olabilir.

bash
# Yerelden uzağa
scp dosya.txt kullanici@sunucu:/hedef/yol/
scp dosya.txt prod:~/                         # config alias

# Uzaktan yerele
scp kullanici@sunucu:/log/app.log ./
scp prod:/etc/nginx/nginx.conf ./nginx.conf   # config alias

# Dizin kopyala (-r)
scp -r ./dist/ prod:/var/www/html/

# Farklı port (-P büyük harf!)
scp -P 2222 dosya.txt kullanici@sunucu:/tmp/

# Uzaktan uzağa
scp sunucu1:/data/dump.sql sunucu2:/restore/
-r
dizinleri özyinelemeli kopyala.
-P port
SSH portu (dikkat: büyük P — ssh'taki küçük -p değil).
-i anahtar
belirli identity file kullan.
-C
aktarım sırasında sıkıştır (yavaş ağlarda yardımcı olur).
-l limit
bant genişliği sınırı Kbit/s. -l 1000 → 1 Mbit/s.
-v
verbose — bağlantı sorunlarını debug etmek için.
scp sınırları

scp büyük dizinlerde yavaş ve güvenilmezdir: resume (devam) desteği yok, kısmi dosyada kesilirse baştan başlar. Büyük ya da artımlı aktarımlarda rsync kullan.

07 rsync — artımlı eşitleme

rsync sadece değişen parçaları gönderir. Büyük dizinler, kesintili bağlantılar ve yedekleme için doğal tercih.

bash
# -a (archive): -rlptgoD kısaltması
#   -r: recursive  -l: symlink  -p: izinler
#   -t: timestamp  -g: grup     -o: sahip  -D: device
rsync -av ./src/ kullanici@sunucu:/dest/

# -v: verbose (ne gönderildiğini göster)
# -z: sıkıştır (WAN için yardımcı, LAN'da ekstra yük)
# --progress: her dosyanın ilerlemesini göster
rsync -avz --progress ./büyük-dizin/ prod:/backup/

# --delete: hedefte kaynak'ta olmayan dosyaları sil (mirror)
rsync -av --delete ./site/ prod:/var/www/html/

# --dry-run (-n): gerçekten yapma, sadece ne olacağını göster
rsync -av --delete --dry-run ./site/ prod:/var/www/html/

# --exclude: belirli dosyaları atla
rsync -av --exclude '*.log' --exclude '.git' ./proje/ prod:/deploy/

# --exclude-from: exclude listesi dosyadan oku
rsync -av --exclude-from .rsyncignore ./proje/ prod:/deploy/
-a (--archive)
-rlptgoD kombinasyonu. Dosya özniteliklerini (izin, sahip, timestamp, symlink) koruyarak kopyalar. Çoğunlukla kullanılacak temel flag.
-v (--verbose)
aktarılan dosyaları göster.
-z (--compress)
aktarım sırasında sıkıştır. Yavaş WAN bağlantılarında faydalı, LAN'da gereksiz CPU yükü.
--progress
aktarım ilerlemesini gerçek zamanlı göster.
--delete
kaynakta olmayan hedef dosyaları sil. Mirror için şart ama dikkatli kullan.
--dry-run / -n
simülasyon — gerçekte hiçbir şey değiştirmez. --delete gibi tehlikeli flag'lerden önce her zaman çalıştır.
--exclude 'desen'
bu desene uyan dosyaları atla. Birden fazla kez tekrarlanabilir.
--bwlimit=KBPS
bant genişliği sınırı. --bwlimit=5000 → 5 MB/s.
-e 'ssh -p 2222'
SSH seçeneklerini özelleştir (port, identity file vb.).

Trailing slash kuralı

bash
# src/ SONUNDA / VAR → dizin içeriğini kopyala
rsync -av src/ sunucu:/dest/
# Sonuç: /dest/dosya1  /dest/dosya2 …

# src SONUNDA / YOK → dizinin kendisini kopyala
rsync -av src sunucu:/dest/
# Sonuç: /dest/src/dosya1  /dest/src/dosya2 …
Trailing slash — ince ama kritik

rsync'in en sık karşılaşılan hatası budur. rsync -av src/ dest/ ile rsync -av src dest/ farklı sonuçlar verir. Kuralı: kaynak sonundaki / "dizinin kendisi değil içeriği" anlamına gelir.

08 rsync vs scp — ne zaman hangisi

İkisi de SSH kullanır ama farklı güçleri var.

Kriterscprsync
Tek dosya kopyalamaHızlı ve basitFazla
Büyük dizin aktarımıYavaş, tüm dosyaları gönderirSadece değişeni gönderir
Kesinti sonrası devamBaştan başlarKaldığı yerden devam eder
Mirror (--delete)YokVar
Dosya öznitelikleri-p ile kısmi-a ile tam (-r -l -p -t -g -o)
Bant genişliği kontrolü-l ile sınırlı--bwlimit ile hassas
Exclude/filterYokVar
Dry-runYok--dry-run
KARAR AĞACI

Tek bir dosya veya küçük bir şey mi? → scp. Dizin, büyük veri, yedekleme, deployment, ya da tekrar çalışacak bir şey mi? → rsync. Şüphe durumunda rsync.

09 Debug ve yaygın hatalar

SSH bağlantısı kurulmuyorsa adım adım teşhis.

-v ile verbose

bash
ssh -v kullanici@sunucu     # verbose (1 seviye)
ssh -vvv kullanici@sunucu   # maksimum debug çıktısı

known_hosts temizleme

bash
# "REMOTE HOST IDENTIFICATION HAS CHANGED" hatası aldığında
# (sunucu yeniden kurulduysa, IP değiştiyse normaldir)
ssh-keygen -R sunucu_ip_veya_hostname

# Ya da elle düzenle
nano ~/.ssh/known_hosts  # ilgili satırı sil

İzin sorunları

bash
# Sunucuda şunları kontrol et
ls -la ~/.ssh/
# drwx------  ~/.ssh/              (700 olmalı)
# -rw-------  ~/.ssh/authorized_keys  (600 olmalı)

# Düzelt
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# Yerel özel anahtar izni de önemli
chmod 600 ~/.ssh/id_ed25519

sshd_config debug (sunucu tarafında)

bash
# Sunucudan auth logunu izle
sudo journalctl -fu ssh

# veya
sudo tail -f /var/log/auth.log

# PubkeyAuthentication açık mı? (sshd_config kontrol)
grep 'PubkeyAuth' /etc/ssh/sshd_config

Hatırlanacaklar

  • Anahtar tipi: ssh-keygen -t ed25519 -C "yorum" — modern ve kısa
  • Ortak anahtarı sunucuya kopyala: ssh-copy-id user@host
  • ~/.ssh/config ile alias: Host prod bloğu, ssh prod kısalığı
  • ProxyJump: bastion üzerinden iç ağa ulaşmak için
  • ControlMaster: aynı host'a çoklu bağlantıda yeniden handshake yapmaz
  • scp: tek dosya, hızlı. rsync: dizin, artımlı, mirror, devam
  • rsync trailing slash: src/ içeriği, src dizinin kendisi
  • rsync --dry-run: tehlikeli işlemden önce her zaman
  • İzinler: ~/.ssh 700, authorized_keys 600, özel anahtar 600

Güvenli bağlantı kurulduktan sonra mTLS ile nasıl sertifika tabanlı kimlik doğrulama yapılacağını merak ediyorsan: Sıfırdan mTLS rehberi.