3 puan yazan GN⁺ 2023-07-06 | 1 yorum | WhatsApp'ta paylaş
  • suc, Slack/Mattermost tarzı sohbetin bazı temel işlevlerini UNIX temel bileşenleri ve Bash birleşimiyle hayata geçiren Simple Unix Chat’tir; çekirdek döngü 5 satırdır, ancak gerçek betik daha uzundur
  • Mesajlar standart girdiden satır satır okunur, tarih ve kullanıcı adı eklenir, ardından /var/lib/suc/ altındaki kanal dosyasına eklenir; kimlik doğrulama ve yetki kontrolü SSH’ye ve UNIX izin modeline bırakılır
  • Mattermost sunucusunun yalnızca Go kodu yaklaşık 500 bin satır iken, suc çok daha küçük kodla benzer temel davranışın oluşturulabileceğini vurgular
  • usuc, tail -f, rlwrap, pygmentize ve : komut önekini birleştirerek kanal okuma, Markdown tarzı çıktı ve komut sonucu paylaşımını işler
  • Kanallar basit metin dosyaları olduğu için grep, tail, bat, lnav, Git hook’ları ve bot betikleri gibi UNIX araçlarıyla kolayca birbirine bağlanabilir

suc’nin azaltmaya çalıştığı karmaşıklık

  • suc, Simple Unix Chat’in kısaltmasıdır; Slack, Mattermost ve IRC’den daha az özelliğe sahiptir ve toplam satır sayısı 5 satırı aşar, ancak mesaj yazan çekirdek döngü 5 satırlık Bash’ten oluşur
  • Hedeflenen işlevler gerçek zamanlı zengin metin sohbeti, dosya paylaşımı, ayrıntılı erişim kontrolü, otomasyon ve dış araç entegrasyonu, aktarım sırasında şifreleme, isteğe bağlı olarak depolamada şifreleme ve kullanıcı kimlik doğrulamasıdır
  • Küçük bir uygulama, modern UNIX uygulamalarının sunduğu tutarlı ve birleştirilebilir temel bileşenlerden yararlandığı için mümkündür
  • Mattermost sunucusu karşıt örnek olarak yalnızca yaklaşık 500 bin satır Go kodundan oluşur; suc’nin Mattermost’un temel işlevlerini bunun %0,005’i kadar kodla uygulayabileceği düşünülür

5 satırlık mesaj yazma döngüsü

  • suc’nin çekirdek Bash döngüsü standart girdiden bir satır okur, tarih ve gerçek kullanıcı adını ekler, ardından bunu /var/lib/suc/"$1" dosyasına ekler
  • Gerçek betik, güvenlik amaçlı ön işleme ve kullanıcı adı rengi hesaplaması nedeniyle daha uzundur; ancak sohbet geçmişi yazmanın temel davranışı üç başlıkta özetlenir
    • Standart girdiden bir satır okuma
    • Tarih ve gerçek kullanıcı adını ekleme
    • /var/lib/suc/ altındaki kanal dosyasına ekleme
  • Kimlik doğrulama, erişim kontrolü, şifreleme ve zengin metin suc içindeki kod tarafından değil, SSH, UNIX erişim kontrolü API’leri ve metin tabanlı modülerlik tarafından sağlanır

Kimlik doğrulamadan SSH sorumlu

  • suc süreci zaten kimliği doğrulanmış bir kullanıcı tarafından çalıştırıldığı için suc içinde kimlik doğrulama kodu yoktur
  • Uzak kimlik doğrulamasını, tipik bir UNIX sunucusunda olduğu gibi ssh halleder
    • Parola gibi paylaşılan sırlar
    • Kriptografik challenge
    • Tek kullanımlık parola (OTP) üreten cihaz
    • Birden fazla yöntemi birleştiren MFA
  • ssh, ortadaki adam saldırılarını önlemek için sunucuyu da istemciye doğrular ve istemci ile sunucu arasındaki tüm verileri şifreler
  • suc kurulumu bir UNIX host’una ve ssh sunucu yapılandırmasına dayanır
    • Kullanıcı sistemde var olmalıdır
    • ssh sunucusu ilgili kullanıcının uzaktan oturum açmasına izin vermelidir
  • GNU Guix’te deklaratif yapılandırmayla kullanıcı ve SSH anahtarı tek satırda eklenebilir; yapılandırma satırı kaldırılırsa yeniden yapılandırma sırasında kullanıcı da kaldırılır

Erişim kontrolünden UNIX izin modeli sorumlu

  • suc, kimlik doğrulamanın yanı sıra erişim kontrolü kodu da içermez; bu yaklaşım güvenlik agnostisizmi (security agnosticism) olarak adlandırılır
  • UNIX çekirdeği kullanıcıları, grupları, süreçleri ve dosyaları bilir; dosya okuma/yazma izinlerine sürecin etkin sahibine (effective owner) göre karar verir
  • /var/lib/suc içindeki kanal dosyaları suc kullanıcısına aittir ve grup bazlı okuma izinleriyle kullanıcıların bazı kanalları okuyabilmesi sağlanır
  • Normal kullanıcılar dosyalara doğrudan yazmaz, suc çalıştırır; izin eşleştirme ve engelleme çekirdek tarafından ele alınır
  • Daha kısıtlayıcı topluluklarda grup bazlı setuid binary’leri bulunabilir
    • Örneğin suc_blue, blue kullanıcısına aittir ve yalnızca blue grubu tarafından çalıştırılabilir
    • blue grubundaki kullanıcılar suc_blue üzerinden blue kanalına yazabilir
    • red grubu kullanıcıları blue kanalını okuyamaz veya yazamaz
  • Kanal oluşturma yardımcı betiği suc_channel.sh yaklaşık 80 satırdır; GNU Guix kullanıcıları (suc-private-channel "red" "red") şeklinde tek satırla gerekli setuid binary’sini, kullanıcıyı, grubu ve kanal dosyasını oluşturabilir
  • GNU Guix’in işlemsel güncellemeleri, yapılandırma değişikliklerinin ya tamamen uygulanmasını ya da hiç uygulanmamasını garanti eder ve önceki çalışan duruma geri dönülebilir

Zengin metin ve usuc

  • Birçok sohbet uygulaması metni bir HTML motoruyla render eder; Mattermost masaüstü istemcisi Electron kullanır
  • suc, kanal başına tek bir metin dosyası kullanır; kullanıcılar bunu tail veya cat gibi komut satırı araçlarıyla görüntüleyebilir
  • Terminalin ANSI escape kodları ve UTF-8 desteğinden yararlanarak renkler, emoji ve temel bir zengin metin deneyimi oluşturulabilir
  • suc yalnızca kanal dosyasına yazar; okuma işini usuc üstlenir
    • suc yetkili bir binary olduğu için mantık ve dış bağımlılıklar en aza indirilmelidir
    • usuc, çağıran kullanıcının izinleriyle çalıştığından özellikler daha serbestçe eklenebilir
  • usuc, birçok küçük aracı bir araya getirerek sohbet istemcisi rolü üstlenir
    • rlwrap ile geçmiş ve satır düzenleme işlevi sağlar
    • Kanal dosyasının sahibine göre uygun setuid suc binary’sini seçer
    • tail -f -n 20 ile son 20 satırı ve sonradan eklenen satırları gösterir
    • Girdi satırının : ile başlayıp başlamadığını kontrol eder
    • Kullanıcının girdiği metni pygmentize ile işler
  • pygmentize, standart girdiyi Markdown olarak görüp ANSI renkli metin çıktısı verdiği için **bold** gibi markup’ı tek satırlık kodla destekleyebilir

Sohbet komutları ve shell entegrasyonu

  • usuc, mesaj : ile başlıyorsa bunu normal mesaj olarak göndermez; ilgili komutu çalıştırır ve çıktı sonucunu suc ile gönderir
  • Örneğin gum style --border=rounded --bold --foreground=#F00 "Hello World !" çalıştırıldığında kanalda kenarlık ve stil uygulanmış metin görünür
  • Komutlar usuc’yi çağıran kullanıcının namespace’inde çalıştığı için kullanıcılar diğer kullanıcıları etkilemeden kendilerine ait sohbet makroları tutabilir
  • the dam içinde masaüstü rol yapma oyunları sırasında roll 2d6 gibi komutlarla zar atmak için kullanılır

Metin pipe’ları ve dış araç entegrasyonu

  • Kullanıcılar usuc’nin komut çalıştırma işlevi yerine shell’den komut çıktısını doğrudan suc’ye pipe edebilir
  • bat’in renkli çıktısını suc’ye göndererek kod parçaları kanalda sözdizimi vurgulu şekilde paylaşılabilir
  • make test > testlog || (suc devops < testlog ; exit 1), test başarısız olduğunda log’u devops kanalına gönderen tek satırlık Bash örneğidir
  • Bu tek satır bir Git deposunun update hook’una konabilir; push sırasında testleri çalıştırır, başarısız olursa güncellemeyi reddeder ve DevOps ekibini bilgilendirir
  • Slack veya Mattermost’taki entegrasyon işlevlerine karşılık gelen işler UNIX metin pipe’ları ve betikleriyle kurulabilir

Kanal okuma, bildirimler, botlar

  • suc kanalı sürekli güncellenen bir metin dosyası olduğundan tail -f ile yeni satırlar okunup işlenebilir
  • Yeni mesaj geldiğinde notify-send ile bildirim gösteren bir pipeline kurulabilir; grep ile yalnızca adlar veya “build failure” gibi anahtar kelimeler filtrelenebilir
  • Birden fazla kanalı tek bir feed’de birleştirmek için tail -f /var/lib/suc/* kullanılabilir
  • lnav kullanıldığında okunan konumu hatırlama, yer imleri, kanal bazlı renkler, tarih/kullanıcı adı/kullanıcı tanımlı alan ayrıştırma, filtreleme ve SQL sorgularından yararlanılabilir
  • Botlar, kanalı okuyup aynı anda yazabildiği sürece uygulanabilir
    • Örnek, kanalda 33000 ft gibi uzunluk ifadelerini bulur
    • units komutuyla metre birimine dönüştürür
    • Aynı kanala [metric_bot] 33000 ft is 10058.4 meters. gibi bir yanıt yazar

Karşılaştırma ve sonuç

  • Karşılaştırma hedefleri olarak Slack, Mattermost ve Discord gibi büyük sistemler gösterilse de daha adil karşılaştırma hedefleri arasında IRC, talk ve writeın da bulunduğu düşünülür
  • IRC’nin, geçmiş sohbet kayıtlarını okumak için bouncer gerektirmesi bakımından suc’den daha az işlevsel olduğu değerlendirilir
  • talk, ytalk ve wallın modern Linux dağıtımlarında çalışır hâle getirilemediği belirtilir
  • suc, kimlik doğrulamayı SSH’ye, erişim kontrolü ve birleştirilebilirliği UNIX’e bırakır; kanalları metin dosyası olarak tutar
  • Araçlar metin okuyup yazabildiği sürece herhangi bir dilde yazılabilir

1 yorum

 
GN⁺ 2023-07-06
Hacker News görüşleri
  • Aklıma hemen “Master Foo and the Ten Thousand Lines” geldi: http://catb.org/~esr/writings/unix-koans/ten-thousand.html
    Bu, Master Foo’nun kendisini ziyaret eden programcıya “bir satırlık shell script’te, 10 bin satır C kodundan daha fazla Unix doğası vardır” dediği hikâye

  • Eğer bir şeyin belirlenmiş çekirdek işlevi fazla kolay ve önemsiz biçimde yeniden üretilebiliyorsa, o işlev gerçek değerin çekirdeği ya da kaynağı olmayabilir
    1980’lerden beri UI geliştirmenin ne kadarını yazılım mühendisliğinin içine alıp otomatikleştirdiğimizi, ya da bunun hâlâ saf insan sanatının alanı olup olmadığını merak ettiriyor

    • Doğru. Örneğin Slack’in temel katma değeri “kimliği doğrulanmış kullanıcıların birbirine mesaj göndermesi” değil
      Slack ortaya çıkıp diğerlerini sahneden itmeden önce de, hem ticari hem açık kaynak tarafta bunu yapan zaten düzinelerce uygulama vardı
      Slack’in asıl değeri bir sonraki katmanda. Görsel olarak hoş ve son derece sezgisel bir UI/UX sunuyor; böylece neredeyse herkes, eğitim, kurulum, kılavuz ya da öğretim olmadan oturur oturmaz kullanabiliyor. Teknik bilgi gerekmiyor ve “kullanıcı adı ile şifreyi gir”den fazlasını anlamasanız da geri kalanı kendiliğinden açık oluyor
    • Çok keskin bir bakış açısı. O zaman Slack’in değeri kullanıcı dostuluğu ve suc açıkça genel kullanıcıya yönelik değil
      Ama bu daha zor bir soruyu doğuruyor. Çok temel komut satırı çağrılarını yapabilen kullanıcıları biraz daha eğitmek gibi bir alternatife kıyasla Slack fiyatına değer mi? Slack’in veriyi elinde tutup geri vermemesi de hesaba katılırsa ne olur? Slack’ten ayrılmanın maliyeti ne kadar yüksek?
      suc’un kullanışsız olduğu doğru, ama belki Slack’ten daha az şişkin ve daha az tekelci bir şeye doğru yakınsanabilir
  • Ortaya çıkan işi beğendim. Birleştirilebilirlik ile neler yapılabileceğini görmek güzel
    Yine de bunu Slack vb. ile karşılaştırmak bana çok anlamlı gelmiyor. Hiçbir mühendis böyle birbirine bağlanmış bir şeyi prodüksiyonda sahiplenmek istemez. İnsan kaynağını nasıl bulacaksınız, test ve debug işlerini nasıl yapacaksınız, log ve analitiği nasıl yürüteceksiniz?
    Bu yazı, Slack benzeri uygulamaların sohbet işlevinin bir kısmını kopyalıyor, ama sohbet bu tür uygulamaların %100’ü değil. Bunlar tamamen farklı ortamlarda üretilmiş şeyler; dolayısıyla mevcut durumu şişkin diye saldırmak Stockton Rush tarzı çarpık bir yorum gibi duruyor. Yazılımda gerçekten şişkinlik var, ama “Anne bak, ıvır zıvırdan bir denizaltı yaptım, demek ki pahalı denizaltılar aptalca” bunun yazarın amaçladığı karşı çıkış gibi gelmiyor

    • Mesele şu ki, kod tabanının yüzey alanı küçüldüğünde bunların önemli bir kısmı daha az kritik hâle geliyor
      Tekil yardımcı araçları genelde ayrı ayrı anlamak, test etmek ve debug etmek kolaydır; logging zaten sistemin içinde var. syslog yok mu? Ayrıca neden analitik gerekli olsun?
    • Ben de okurken öyle düşündüm. Harika bir mühendislik çalışmasıydı ve okuması keyifliydi, ama Slack yerine doğrudan IRC ile karşılaştırılsa daha dürüst olurdu bence
      Yine de Slack benzeri araçlar yeni özellikler yerine sadeliği agresif biçimde öncelemiş olsaydı nasıl görünürdü, gerçekten merak ediyorum. Sanki kapitalizmin bütünü bu tür geliştirmeleri teşvik etmiyor; bu yüzden makul ölçüde mümkün olan en sade kurumsal yazılım örneği pek yok. Yine de ilginç bir düşünce deneyi
  • Benzer biçimde doğrudan IRC üzerinde çalışan ii de var: https://tools.suckless.org/ii/
    Tüm sohbetlerde tek bir standart dosya kullanıyor, kimlik doğrulama ve erişim kontrolünü IRC ağı doğrudan yönetiyor ve zaten pek çok UI mevcut. Bu yazıda olduğu gibi, eklentiler de herhangi bir dosyayı okuyup başka bir dosyaya yazan her şey olabilir

  • craigslist diyagramı gibi, Unix işlevlerindeki dilimleri alıp startup’lara dönüştüren bir spawn of unix diyagramı yapmak eğlenceli olabilir
    https://thegongshow.tumblr.com/post/345941486/the-spawn-of-craigslist-like-most-vcs-that-focus
    ftp/rsync => Dropbox
    suc => Slack
    ...

  • Başlık clickbait gibi görünüp geçmeyi düşünüyorsanız, bir ölçüde clickbait sayılır ama aslında epey iyi bir yazıydı
    suc(Simple Unix Chat) adlı bir aracı ele alıyor ve çok küçük bir kod tabanıyla Slack, Discord gibi sunucu işlevlerini gerçekleştiriyor
    Yeni olan tarafı, mevcut Unix araçlarını ve metodolojilerini yeniden icat etmek yerine kullanması. Kimlik doğrulamayı SSH hallediyor, kanallar sadece birer dosya, yönetici/moderatör kontrolü ise kullanıcı grupları ve dosya izinleriyle sağlanıyor. Biçimlendirilmiş metin ya da dosya yükleme gibi şeyler için kanala istenen veriyi yazıp istemcinin bunu yorumlamasına izin vermek yeterli. Botlar da kanal dosyasına pipe bağlanınca çok kolay oluyor
    Yazıdaki kanala mesaj yazan 5 satırla kusursuz bir Slack klonu yapılamaz ama gerçekten basit Unix araçlarıyla ne kadar ileri gidilebildiği oldukça etkileyici

    • Mevcut sohbet platformları Unix araçlarını “yeniden icat” etmiş değil; bunun üstünde inşa etmeye uygun olmadığı için kullanmamışlar
      “Her şey dosyadır” paradigmasıyla ve shell script’lerle yazılmış büyük ölçekli production sistemlerin neredeyse hiç olmamasının bir nedeni var. Gerçek dünyada kullanılacak, önemsiz olmayan sistemler için kabul edilemez bir yaklaşım olduğu için
    • Çoğu son kullanıcı için Slack bir istemcidir
      Buna yönetici arayüzü, kullanıcı yönetimi arayüzü, genişletilebilirlik, webhook’lar vb. dahildir. “Herkes o kutuya giriş yaparsa Linux üzerinde diğer kullanıcılarla sohbet edebilir” demek bunların hiçbirini çözmüyor. Bu tür özellikler burada okuyanların çoğu doğmadan çok önce tüm *nix sistemlerinde zaten vardı
    • Burada append-only dosyalar iyi uyuyor gibi görünüyor. Çünkü normal kullanıcıların ve botların başkalarının gönderilerini değiştirememesini garanti edebilirler
      Ne yazık ki bu Plan 9 özelliği hâlâ Linux’a taşınmadı. “Okuma” ya da “yazma”ya benzer izin bitleri ama çok daha belirli
    • “Mevcut Unix araçlarını ve metodolojilerini kullanıyor” ifadesi neredeyse her zaman “X’i inanılması güç derecede az satır kodla gerçekleştirdi” anlamına geliyor
      Yazarı suçlamıyorum; yazıda da bu nokta gayet dürüst biçimde belirtiliyor
  • Slack ve Discord’da ekran paylaşımı ve sesli sohbet var. Bunlar ek özellikler değil, pazardaki hakimiyetleri için oldukça belirleyici özellikler

    • Belirleyiciler ama kalite sanki giderek düşüyor
  • Bu blog yazısının suc hakkında olduğunu ve başlığın biraz yanıltıcı olabileceğini en baştan dürüstçe kabul etse de, sonuçta suc ile doğrudan ilgili olmayan önemli bir mesajı var
    Modern yazılımların neredeyse tamamı korkunç derecede şişkin. Zengin özellikli bir sohbet sunucusu için 1,7 milyon satır gerektiği fikri saçma. Bill Gates usulü söylersek, ne kadar uğraşsam da bir sohbet sunucusunda o kadar satır kodu “tüketebileceğimi” sanmıyorum
    Sadece soruna dikkat çekmek ya da bir alternatif önermekle kalmayıp, tekerleği yeniden icat etmek zorunda olmadığımızı hatırlattığı için alkışı hak ediyor. Mevcut sistem ve alt sistemlerin özelliklerini, örneğin kimlik doğrulama ve şifreleme için SSH kullanmak gibi, ilk tasarlandıkları amaçtan farklı olsa bile o özelliklerin niyetine uygun şekilde akıllıca kullanmak hacker ruhunun güzel bir örneği
    Keşke yazılım dünyası bu kavramdan çok şey öğrenebilse. Daha düşük maliyet, daha kısa geliştirme süresi ve işlevsel olarak aynı kodu yeniden yazmaya harcanan mühendislik zamanının azalması; geliştiriciler, şirketler, son kullanıcılar ve nihayetinde insanlık için iyi olur. Gelecekte bunun gibi daha fazla yaratıcı yıkım görmek isterim, ben de ilerideki projelerde böyle akıllı teknikler uygulamayı denemek isterim

    • Bu arada TypeScript satırlarının çoğu E2E testleri[0] ve webapp dizininde[1] yer alıyor. Adından da anlaşılacağı gibi webapp, “Mattermost web uygulamasının istemci kodunu” içeriyor
      Yani aslında sadece Go kod satırlarını saymak daha doğru olur
      [0] https://github.com/mattermost/mattermost/tree/master/e2e-tests
      [1] https://github.com/mattermost/mattermost/tree/master/webapp
    • Bir site için kullanılacak web kimlik doğrulama framework’ünü seçme toplantısındaydım; bikeshedding yüzünden o kadar uzadı ki toplantı sırasında HTTP’nin zaten sunduğu kimlik doğrulama özellikleri temelinde bunu kendim yazıp toplantı bittiğinde demosunu göstermiştim
    • Prensipte katılıyorum ama şişkinliğin önemli bir kısmı birden fazla platformu tek bir kod tabanıyla desteklemeye çalışmaktan kaynaklanıyor
      Bu genelde çıkış hızını artırdığı ve organizasyonun boyutunu küçülttüğü için iyi bir fikir. Ama karmaşıklık ve soyutlama açısından büyük bir trade-off var. Soyutlama seviyesi yükseldikçe durum daha da kötüleşebiliyor. Yani tamamen sebepsiz değil
  • Günümüzde çoğu dağıtım, güvenlik gerekçeleriyle setuid bash script oluşturmayı engelliyor
    Ancak belirli bir sudoers girdisiyle neredeyse aynı etki elde edilebilir

    • Aslında sadece bash değil, neredeyse tüm shebang script'leri için durum böyle; istisna olarak Perl script'leri sayılabilir. Bunun nedeni uid != euid olduğunda Perl'de taint mode'un otomatik olarak etkinleşmesidir
      https://perldoc.perl.org/perlsec#Taint-mode
      Bazı sistemlerde temel bir yarış durumu olabilir:
      https://perldoc.perl.org/perlsec#Shebang-Race-Condition
      sudo -T kullanımına bakmak da faydalı olabilir:
      https://perldoc.perl.org/perlsec#Using-Sudo
      Ruby'de yakın zamanda taint mode'un kaldırılmış olması üzücü. Taint tracking, script'lerin çok ötesine geçebilen güçlü bir mekanizmadır. Örneğin Rack/Rails'in #html_safe yaklaşımı taint tracking ile ele alınsaydı daha katı çalışabilir, kirlenmiş kullanıcı string'leri SQL parçalarına bağlandığı/yerleştirildiği/formatlandığı anda hata vererek bir SQL injection sınıfını tasarım gereği engelleyebilirdi
      Eskiden CGI/mod_perl üzerinde taint tracking'i çok etkili kullanan insanlar da vardı. Elbette sihirli bir çözüm değil ama hâlâ oldukça etkili bir araç
    • Shell script'i çağıran bir C wrapper kullanın. Görünüşü pek hoş değil ve script'i biraz daha sağlamlaştırmanız gerekir ama çalışıyor :)
      https://gitlab.com/edouardklein/suc/-/blob/master/suc_wrapper.c
    • Bunu izin veren bir dağıtım gerçekten var mı? Kendim denemeye çalıştığımda okuduğum her yerde setuid'nin uygulanmadığı yazıyordu. Çünkü çalıştırılan şey dosyanın kendisi değil, shebang'de belirtilen hedef oluyor
      GitLab deposundaki wrapper dosyasını görene kadar, okurken bir yöntem olmasını umuyordum
  • Bu ayrı bir konu ama talk(1)'den bahsedilmemesi şaşırtıcı: https://man.netbsd.org/talk.1

    • Ya da write(2) var[1]. Benim aklıma hemen ntalk geldi, çünkü aynı makinede böyle bir şeyi en son o zaman kullanmıştım. O dönem IRC şifreli değildi
      Güzel yanı, yalnızca yerel olarak alacak şekilde ayarlanabilmesi; böylece o makinede bir kullanıcı hesabı gerekiyor. Bu yüzden SDF gibi yerler veya daha büyük cluster'lar için uygun. Kimlik doğrulamayı kendiniz yapmak yerine PAM ya da BSD_Auth'a bırakabilirsiniz. Socket veya şifrelemeyi de kendiniz yapmak yerine TLS'e bırakabilirsiniz. SSH ile güvenli shell'e girip ardından tmux ve (n)talk kullanmak da mümkün
      Elbette (n)talk C ile yazılmıştır, yani 5 satırlık bash değildir
      [1] https://man7.org/linux/man-pages/man2/write.2.html