Backend
PowerShell ile Kanıt Dosyası Üretirken Yaşadığım 580 Baytlık Hata
Serdar Tavukçu DEV Community
3 views
Olay nasıl başladı
Bir sabah kalite kapısı sisteminden gelen hata bildirimleriyle uyandım. Otomasyon sistemim her gün çalışıyor ve yaptığı işlemlerin kanıtlarını bir metin dosyasına kaydediyordu. Sistem, dosyanın içinde olması gereken 2026.8 değerini bulamadığını söylüyordu. Dosyayı açtım, gözümle baktım, rakamlar orada duruyordu. Neden okuyamadığını anlamak için dosyayı bir metin editöründe incelemeye karar verdim. Hex görünümüne geçtiğimde ise şok oldum. Değer 2 0 2 6 . 8 şeklinde görünüyordu ve her karakterin arasında NUL baytları vardı. Dosyanın toplam boyutu 2198 bayt iken bunun 580 baytı sadece boşluk ve NUL karakterlerinden oluşuyordu. Sistemim veriyi yazıyordu ama veriyi yazarken kullandığım araçlar birbirleriyle kavga ediyordu. Bu durum hem zaman kaybettirdi hem de tüm raporlama sistemimi durdurdu.
Bu nerede karşına çıkar
Bu tür bir sorun sadece benim otomasyonumda değil, veri işlemi yapan herkesin başına gelebilir. Mesela bir trading botu yazıyorsun ve yaptığın işlemleri bir log dosyasına kaydediyorsun. Eğer logları farklı kodlama standartlarıyla yazan iki farklı komut kullanırsan, verin bozulur. Başka bir örnek ise veri analizi yapan bir sistem olabilir. Fed verilerini veya bist endekslerini takip eden bir python scripti yazıyorsun diyelim. Bu scriptin çıktısını başka bir sistem okuyacaksa, dosyanın kodlaması kritik hale gelir. Eğer bir araç UTF-16 yazarken diğeri UTF-8 bekliyorsa, okuyucu sistem veriyi boşluklarla dolu veya anlamsız karakterlerle görür.
Örneğin, sunucu tarafında çalışan bir PowerShell betiği, sistem saatini ve işlemci kullanım oranını bir metin dosyasına sürekli ekliyor olsun. Eğer bu betik içerisinde zaman damgasını bir komutla, işlemci yükünü başka bir komutla dosyaya basıyorsan, dosyanın ortasında kodlama kırılması yaşanır. Bir noktada dosya UTF-8 ile başlar, ardından gelen veri UTF-16 ile devam eder. Okuyucu sistem, dosyanın tamamını tek bir kodlama ile okumaya çalıştığında, UTF-16 kısmındaki her karakterin arasına giren NUL baytlarını geçersiz karakter olarak görür. Bu hata genellikle farklı kütüphanelerin veya komutların varsayılan davranışlarını bilmediğimizde ortaya çıkar ve sistemler arasındaki veri akışını tamamen keser.
Gerçek hayatta bu durum özellikle büyük ölçekli log dosyalarında kendini belli eder. Örneğin, 50 megabaytlık bir log dosyasının ilk 10 megabaytlık kısmı düzgün okunurken, 11. megabayttan itibaren verinin bozulması, analiz yazılımının dosya sonuna kadar olan kısmı tamamen reddetmesine neden olur. Bu durum, özellikle gece çalışan ve ertesi sabah rapor bekleyen bir otomasyon zincirinde, tüm gecenin verisinin çöp olması demektir.
Kök neden
Sorunun kaynağı PowerShell 5.1 sürümünün varsayılan davranışlarında saklı. Ben başlık satırlarını Set-Content komutuyla ve UTF8 kodlamasıyla yazmıştım. Sonra sistemin geri kalanını Tee-Object ile dosyaya ekledim. PowerShell 5.1 içindeki Tee-Object komutu, varsayılan olarak dosyayı UTF-16 formatında yazar. Bir dosyaya önce UTF-8 başlık ekleyip sonra üzerine UTF-16 veri yazınca, dosya içinde iki farklı kodlama yapısı oluşur. 2198 baytlık dosyanın 580 baytı bu NUL karakterlerinden oluşuyordu. PowerShell, UTF-16 yazarken her karakterin yanına bir NUL baytı koyar. Bu yüzden 2 0 2 6 . 8 gibi görünen veri, aslında bilgisayar için okunamaz bir karışıklık halini aldı. Kodlama uyumsuzluğu, verinin içeriğini değiştirmese de formatını tamamen bozduğu için sistemim bunu bir hata olarak algıladı ve reddetti.
Çözüm
Bu sorunu çözmek için Tee-Object yerine daha kontrollü bir çıktı yöntemi olan Out-File komutunu kullanmaya karar verdim. Ayrıca veriyi okumadan önce bir normalizasyon adımı ekledim.
$cikti | Out-File -FilePath $dosyaYolu -Encoding utf8 -Append
$hamVeri = Get-Content $dosyaYolu -Raw
$temizVeri = $hamVeri.Replace([char]0, "").Replace(" ", "")
Bu kod bloğunda ilk satırda veriyi doğrudan UTF-8 formatında dosyaya ekliyoruz. Out-File komutuna verdiğimiz -Append parametresi, mevcut dosyanın sonuna ekleme yaparken kodlamayı korumasını sağlar. İkinci satırda dosyanın içeriğini ham haliyle okuyoruz. Üçüncü satırda ise karşılaştırmadan önce veriyi temizliyoruz. Replace ile NUL karakterlerini ve gereksiz boşlukları kaldırarak veriyi standart bir metin haline getiriyoruz. Böylece sistemimiz, dosya içindeki kodlama farklılıklarından etkilenmeden doğru rakamlara ulaşabiliyor.
Yolda çıkan hatalar
Çözümü uygularken ilk hatam, sadece kodlamayı değiştirmek oldu. Kodlamayı UTF-8 yaptım ama dosya içinde zaten birikmiş olan eski veriler vardı. Eski veriler bozuk kaldığı için sistem hala hata vermeye devam etti. Dosyayı tamamen silip temiz bir şekilde yeniden oluşturmam gerektiğini fark ettim. İkinci hatam ise normalizasyon adımını atlamaktı. Sadece Out-File kullanmak dosyanın bundan sonra düzgün yazılmasını sağlasa da, sistemim hala eski bozuk dosyayı okumaya çalışıyordu.
Normalizasyon adımını eklerken de bir süre zorlandım. İlk denememde sadece NUL karakterlerini temizledim ama bu sefer de dosya içindeki boşluklar, karşılaştırma mantığımı bozmaya devam etti. Regex kullanarak tüm beyaz boşluk karakterlerini temizlemeyi düşündüm ama bu sefer de verinin okunabilirliği azaldı. Sonunda, sadece NUL karakterlerini ve bilinen boşlukları temizleyen zincirleme bir Replace metodu kullandım. Ayrıca dosyayı bozuk diye işaretleyen ayrı bir kontrol mekanizması kurdum. Eğer dosya boyutu ile karakter sayısı arasında tutarsızlık varsa veya dosya içinde beklenmedik karakter kodları tespit edilirse, sistem uyarı verip dosyayı arşivliyor ve yeni bir tane oluşturuyor. Bu iki adım sayesinde sistemin stabil hale gelmesini sağladım.
Karşılaştığım bir diğer teknik zorluk, PowerShell'in Get-Content komutunun dosyayı satır satır okurken NUL karakterlerini nasıl işlediğiydi. Dosyayı -Raw parametresi olmadan okuduğumda, PowerShell bozuk karakterleri satır sonu olarak algılayıp veriyi parçalara ayırıyordu. Bu da verinin bütünlüğünü bozuyordu. -Raw parametresini kullanarak dosyanın tamamını tek bir blok olarak belleğe aldım ve temizleme işlemini bu blok üzerinde gerçekleştirdim. Böylece satır sonu karmaşasından kurtulup veriyi tek parça halinde işleyebildim.
Alternatifler
Bu sorunu çözmek için farklı yaklaşımlar da vardı. Bir alternatif, bütün dosya işlemlerini tek bir komutla ve tek bir kodlama parametresiyle yapmaktır. Ancak sistemimdeki bazı modüller farklı çıktı tipleri üretiyordu. Bir diğer alternatif ise veriyi yazarken her seferinde kodlamayı kontrol eden bir fonksiyon kullanmaktı. Bu yöntem daha güvenli olsa da kodun karmaşıklığını artırıyordu. Ben, veriyi yazarken standartlaşmayı sağlayan ve okurken temizleyen yöntemi seçtim. Çünkü bu yöntem hem mevcut sistemimi çok fazla değiştirmeme izin verdi hem de gelecekte oluşabilecek benzer kodlama hatalarına karşı bir güvence sundu. Diğer yöntemler daha temiz görünse de benim senaryomda sistemin tüm akışını bozma riski taşıyordu.
[[GÖRSEL2]]
Bundan sonra ne yapmalı
Bundan sonraki süreçte bu tarz hataları önlemek için üç somut adım atmalısın. Birincisi, tüm çıktı dosyalarının kodlamasını projenin başında standart hale getir. Hangi komutu kullanırsan kullan, her zaman -Encoding parametresini belirtmeyi alışkanlık haline getir. İkincisi, ürettiğin kanıt dosyalarını sadece yazmakla kalma. Yazdığın her dosya için, dosyanın içeriğini doğrulayan basit bir kontrol scripti yaz. Bu script dosyanın içinde NUL karakteri olup olmadığını veya beklenen formata uygun olup olmadığını kontrol etsin. Üçüncüsü, hata ayıklama sürecinde her zaman dosyanın ham baytlarına bak. Metin editörü bazen karakterleri gizler, bu yüzden hex görünümü her zaman en doğruyu söyler. Bu adımları takip ederek otomasyon sistemlerini daha sağlıklı ve güvenilir hale getirebilirsin.
Read original: https://dev.to/serdartavukcu/powershell-ile-kanit-dosyasi-uretirken-yasadigim-580-baytlik-hata-4pjf
← Previous
NicheDB 0.2.0: the domain layer, counted daily
Next →
Open-Source Oracle Database Performance History with PostgreSQL and Grafana
Related
AI psychosis might be a result of subscription fatigue
Backend
1
DEV Community
Dead Code Is More Dangerous Than Broken Code — How a Non-Homologous AI Caught the Blind Spot the AI Itself Had Rubber-Stamped
Backend
3
DEV Community
Borsa Verisiyle Çalışırken Sürekli Dönüp Dolaşıp Kullandığım 6 Python Kütüphanesi
Backend
3
Dev.to (EN Zone)
Monitor Call Quality in Real Time with Telnyx Webhooks and Python
Backend
2
Dev.to (EN Zone)
Comments0
No comments yet — be the first