Şu ana kadar yazdığımız betikler, yukarıdan aşağıya doğru akan ve genellikle tek bir amaca hizmet eden kısa kod bloklarıydı. Ancak yazılım dünyasında ve sistem otomasyonunda altın bir kural vardır: DRY (Don't Repeat Yourself - Kendini Tekrar Etme).
Eğer bir switch'e SSH bağlantısı kuran, konfigürasyon gönderen ve bağlantıyı kapatan 15 satırlık bir kodunuz varsa ve script'in farklı yerlerinde bu işlemi 4 kez yapmanız gerekiyorsa, bu 15 satırı 4 kez kopyalayıp yapıştırmamalısınız. Bunun yerine o kod bloğunu bir "kapsüle" koyar, ona bir isim verir ve ihtiyaç duyduğunuzda sadece o ismi çağırırsınız. İşte bu kapsüllere Fonksiyon (Function) diyoruz.
Kendi Komutumuzu Yaratmak: Fonksiyon Tanımlama (def)
Python'da bir fonksiyon tanımlamak için def (define) anahtar kelimesi kullanılır. Ardından fonksiyona açıklayıcı bir isim verilir, parantez açıp kapatılır ve iki nokta üst üste : konulur. İçeriğine yazılacak her şey bir girinti (tab/boşluk) içeriden başlar.
# Fonksiyonu tanımlıyoruz (Şu an çalışmaz, sadece belleğe kazınır)
def karsilama_mesaji():
print("---------------------------------")
print("Sistem Otomasyonuna Hoş Geldiniz!")
print("---------------------------------")
# Fonksiyonu çağırıyoruz (İstediğimiz kadar çağırabiliriz)
karsilama_mesaji()
karsilama_mesaji()Dışarıdan Veri Almak: Parametreler ve Argümanlar
Yazdığımız bir fonksiyonun gerçekten akıllı olabilmesi için dinamik çalışması, yani dışarıdan veri kabul etmesi gerekir. Fonksiyonu tanımlarken parantez içine yazdığımız değişkenlere parametre, fonksiyonu çağırırken gönderdiğimiz gerçek verilere ise argüman denir.
Sistemci Senaryosu: Bir sunucuya "Ping" atma işlevini simüle eden bir fonksiyon yazalım. Hedef IP'yi dışarıdan alsın.
# ip_adresi burada bir parametredir.
def cihaza_ping_at(ip_adresi):
print(f"[{ip_adresi}] adresine ICMP paketleri gönderiliyor...")
print("Yanıt alındı: 0% packet loss\n")
# Gerçek IP'ler (Argümanlar) ile fonksiyonu çağırıyoruz
cihaza_ping_at("192.168.10.1")
cihaza_ping_at("10.0.5.50")Birden fazla parametre de kullanabiliriz. Parametreleri virgülle ayırmamız yeterlidir. Ayrıca bir parametreye varsayılan (default) bir değer de atayabiliriz. Böylece kullanıcı o değeri girmezse script çökmez, varsayılan değeri kullanır.
def ssh_baglantisi_kur(ip, port=22, kullanici="admin"):
print(f"-> {ip} adresine {port}. port üzerinden {kullanici} kullanıcısıyla bağlanılıyor.")
# Sadece IP verirsek, varsayılan port ve kullanıcıyı kullanır:
ssh_baglantisi_kur("192.168.1.5")
# Tüm parametreleri kendimiz belirlersek:
ssh_baglantisi_kur("10.0.0.10", 2222, "root")İşlem Sonucunu Geri Döndürmek: Return İfadesi
Fonksiyonlar genellikle sadece ekrana (print) bir şeyler yazdırmak için kullanılmaz. Arka planda bir hesaplama yapar, bir cihaza bağlanıp durumunu kontrol eder ve çıkan "sonucu" ana programa geri teslim etmesi gerekir.
İşte bu veri teslimatını return komutu ile yaparız. return komutu çalıştığı anda fonksiyon işini bitirir ve oradan çıkar.
Sistemci Senaryosu: Bir portun durumunu kontrol edip, sadece True veya False döndüren bir fonksiyon yazalım.
def port_acik_mi(hedef_port):
acik_portlar = [22, 80, 443, 3389]
if hedef_port in acik_portlar:
return True
else:
return False
# Fonksiyondan dönen sonucu bir değişkene atayabiliriz
ssh_durumu = port_acik_mi(22)
telnet_durumu = port_acik_mi(23)
if ssh_durumu:
print("Güvenli bağlantı kurulabilir.")
else:
print("SSH erişimi kapalı!")Sistemcilerin Sık Düştüğü Hata: Kapsam (Scope) Kavramı
Python'a yeni başlayanların en çok hata yaptığı konu Kapsam (Scope), yani bir değişkenin nerede geçerli olduğudur. Kural basittir: Bir fonksiyonun içinde tanımlanan değişken, o fonksiyonun içinde yaşar ve fonksiyon bittiğinde ölür (silinir). Buna Local (Yerel) değişken denir. Her yerden erişilebilenlere ise Global değişken denir.
sistem_versiyonu = "v1.5" # Global değişken (Her yerden okunabilir)
def versiyon_guncelle():
# Burada yeni bir 'yerel' değişken yaratılır, dışarıyı etkilemez.
yeni_versiyon = "v2.0"
print(f"Fonksiyon içi: {yeni_versiyon}")
versiyon_guncelle()
print(f"Sistem versiyonu: {sistem_versiyonu}")
# print(yeni_versiyon) -> YAZAMAYIZ! Hata verir, çünkü o değişken sadece fonksiyonun içindeydi.Eğer bir fonksiyonun içinden, dışarıdaki (global) bir değişkeni değiştirmek istiyorsanız, bunu global anahtar kelimesiyle Python'a açıkça belirtmeniz gerekir (Ancak bu kurumsal kod mimarilerinde çok tavsiye edilmez, veriyi return ile dışarı aktarmak her zaman daha güvenlidir).
Artık betiklerimizi fonksiyonlar sayesinde küçük, akıllı ve tekrar kullanılabilir modüllere ayırabiliyoruz. Ancak gerçek sistemlerde işler her zaman yolunda gitmez. IP adresi yanlış girilebilir, cihazın fişi çekilmiş olabilir veya log dosyası silinmiş olabilir. Bu durumlarda ekranda çirkin kırmızı hata mesajları görmek ve betiğin çökmesini izlemek profesyonelce değildir.
Serinin bir sonraki yazısında betiklerimizi kırılmaz hale getirecek olan Hata Yakalama (Try-Except) ve Dosya İşlemleri (I/O) konularını inceleyeceğiz.
