2 puan yazan GN⁺ 2024-06-24 | 2 yorum | WhatsApp'ta paylaş
  • Unix kullanıcıları kişisel betiklerini ~/bin/ dizinine koyup PATH’e eklediğinde, kısa komut adları yeni sistem komutlarıyla çakışabilir
  • Debian/Ubuntu gibi çok sayıda komut sunan ortamlarda risk daha da artar; örnek Ubuntu dizüstü bilgisayarda /usr/bin komutlarının sayısı 21.733 olarak hesaplanmış
  • Kişisel komutların başına virgül (, değil, ,) koymak, kabuk ve araçlar tarafından normal bir dosya adı karakteri olarak işlenirken sistem komutlarından kolayca ayırt edilmelerini sağlar
  • Virgül Shift kullanmadan yazılabilir ve kabukta güçlü anlamları olan parantez, ters eğik çizgi, iki nokta, backtick, tek tırnak, eğik çizgi ve noktaya göre çakışma olasılığı daha düşüktür
  • , sonrasında Tab’a basınca kişisel komut listesini hemen gözden geçirebilirsiniz; bu da ~/bin/ komut adlarını düzenli tutmayı kolaylaştırır

Kişisel komut adları neden çakışır?

  • Birçok Unix kullanıcısı ev dizininde ~/bin/ oluşturup bunu PATH’e ekleyerek kişisel kolaylık komutları ve kabuk betikleri kullanır
  • Sorun, kişisel betik adlarının genellikle kısa küçük harf kombinasyonları olması ve bu yüzden varsayılan sistem komutlarına benzeme olasılığının yüksek olmasıdır
  • Bir Linux dağıtımı yeni bir komut eklediğinde, mevcut bir kişisel komutla tesadüfen aynı ada sahip olabilir
  • Debian türevi ortamlarda sunulan komut sayısı fazla olduğu için bu sorun daha gerçekçi hale gelir
    • Örnek Ubuntu dizüstü bilgisayarda /usr/bin dizininin hemen altındaki komutları sayınca 21.733 sonucu çıkıyor
    • apt-file search -x '^/usr/bin/[^/]*$' | wc -l

Virgül önekinin sağladığı avantajlar

  • Çözüm, kişisel komut adlarını hem yazması kolay hem de sistem komutu adı olarak pek seçilmeyecek bir biçime dönüştürmektir
  • Yazım kolaylığı için ölçüt Shift tuşunu kullanmamaktır; bu koşulu karşılayıp güvenli olan karakter sayısı çok değildir
    • Küçük harfler sistem komutlarında zaten yaygın kullanılır
    • Parantezler, ters eğik çizgi, iki nokta, backtick ve tek tırnak kabukta özel anlam taşır
    • Eğik çizgi dizin ayırıcıdır, bu yüzden dosya adında yer alamaz
    • Nokta, dosya adının başında gizli dosya anlamına gelir; başka konumlarda da uzantı ayırıcı olarak sık kullanılır
  • Geriye kalan seçenek basit bir virgüldür (,); çevredeki araçlar ve kabuk, virgülü dosya adındaki normal bir karakter olarak işler
  • Her kişisel komuta önek olarak virgül eklemek, onları sistem komutlarından net biçimde ayırır ve ad çakışmalarından kaçınmayı kolaylaştırır
  • Tab tamamlama ile birlikte kullanıldığında, , yazdıktan sonra kişisel komut listesini hemen görebilirsiniz
    • Örnek listede ,complete-scp, ,complete-ssh, ,coreoff, ,coreon, ,find, ,go-thpgp, ,gr, ,hss, ,mount-thpgp, ,mount-twt, ,range, ,svn-store-password, ,umount gibi komutlar yer alır
  • Bu yöntem yaklaşık 10 yıldır kullanılıyor ve kişisel ~/bin/ komut adlarını temiz ve düzenli tutmanın bir yolu olarak öneriliyor

2 yorum

 
GN⁺ 2024-06-24
Hacker News yorumları
  • Sadece başlığa bakınca berbat bir fikir sanmıştım ama aslında oldukça hoşuma gitti. Özellikle Tab ile tüm araçlarımı listeleme kısmını sevdim.
    Son zamanlarda ad alanı çakışmalarıyla pek karşılaşmadım; yönetim tarafına geçtikten sonra teknik sezgilerimin biraz gevşediği de doğru. Teknoloji yığınımın yaklaşık 10 yıl eskimiş gibi hissettirdiğini düşünüyorum; yeniden güncel hissiyatı yakalamak için nereden başlamak iyi olur merak ediyorum.

    • Bugünün havalı yolu, boş zamanında kendi başına bir şeyler yapmak ve yaparken doğal olarak öğrenmek gibi görünüyor. Kendi kendine yetme, yaratıcılık ve kendi kendine başlama tavrı bugünün ruhu; ne kadar çok şey yaparsan, gerçek sorunları çözmenin yollarını ve modern çözümleri kendi başına bulma motivasyonun o kadar artıyor.
    • Ben de yönetim tarafındayım ve takip etmeyi sürdürmezsem teknik becerilerimin köreleceğini hissediyorum.
      Benim yöntemim, hayatımı kolaylaştıran araçları kendim yapmak. Örneğin şirkette basit sorgulamalar için sık kullandığım bir web servisi varsa API’si var mı diye bakıyorum ve günlük işleri hızlandırmak için CLI yazıyorum. İstediğim gibi cilaladıktan sonra ekiple paylaşıyorum ama başkalarını denemeye ikna etmek zor oluyor. Yine de her gün ben kullandığım için bunu çok dert etmiyorum.
    • Aynı nedenle işte alışık olduğum yığın yerine daha popüler ayrı bir yığınla yan proje yaptım.
      Amacım yeni bir bakış açısı görmek ve trendler hakkında konuşabilmekti; bunların bir kısmı artık işe de taşındı. Bu sayede eski bileşenleri de daha derinlemesine anlamış oldum.
  • Bu sorunu pek anlamıyorum. Kendi bin dizinimi $PATH’in sonuna değil başına koyarım, olur biter. Kendi komutlarıma göz atmak için de sadece ls ~/bin çalıştırırım.

    • Sonra bir araç $0’ın sistem yolunda olduğunu varsayar, bu bozulur ve can sıkıcı bir hata ayıklama süreci başlar.
      Sonuçta hangi zehri seçeceğin meselesi.
    • Sadece verdiğin adları hatırlasan olmaz mı? Bunun neden bir tür hack gibi görüldüğünü anlamıyorum.
    • Avantajlarından biri fzf otomatik tamamlamasını kullanabilmek. Örneğin fish’te komutun ilk karakterini yazıp Tab’a basarak fzf’yi açabilirsin.
      Böylece sadece ,+Tab ile kullanıcı tanımlı komutları hızlıca süzebilirsin. Buna karşılık ls ~/bin, sık yapılan bir iş için yazılacak karakter sayısı fazla; ya da önce otomatik tamamlamayı bulmak için ls+yukarı ok tuşuna birkaç kez basman gerekebilir.
    • ls ~/bin yazmak , yazmaktan çok daha yavaş.
  • Ben git için ince bir sarmalayıcıda aa, st, di, dp, cm, le gibi kısa kullanıcı tanımlı komut adları kullanıyorum.
    Bunlardan biri bazı sistemlerde varsayılan kurulu gelen bir yardımcı programla gerçekten çakışıyor. Yine de benim bin dizinim $PATH’te sistem dizinlerinden önce olduğu için benimki kazanıyor ve çakışan o araca pek ilgi duymuyorum. Bana faydalı başka bir araç benim aracımla çakışırsa, kendi aracımın adını değiştirmektense muhtemelen o diğer araca çakışmayan bir takma ad veririm. Bu iki harfli araçlar fazla kullanışlı.

    • Bu yaklaşım, apt-get upgrade’in Dwarf Fortress çalıştırması gibi sorunlara yol açabilir.
      https://askubuntu.com/questions/938606/dwarf-fortress-starti...
    • Doğru. 1–3 harfli adlar kullanıcı takma adları, fonksiyonları, betikleri ve standart yardımcı programlar için ayrılmalı.
    • Benim git takma adlarım genelde g ile başlayan iki harfli kombinasyonlardan oluşuyor. Örneğin gs, git status demek.
      Ama bazen gerçekten GhostScript’e ihtiyaç duyduğum oluyor. PDF dosyalarına yazı tipi gömmek gibi durumlarda harika iş çıkarıyor. Genelde o zaman env gs kullanıyorum.
    • Kişisel komutlarımın hepsi j ile başlıyor. java ortaya çıktığında işler epey eğlenceli hale geldi. Virgül kullanmak oldukça ilginç bir fikir.
      Yine de k ile başlamadığı iyi olmuş, KDE yüzünden :)
    • Biraz güçlü bir görüş ama sistem komutlarının kullanıcı komutları kadar kolay erişilebilir olmaması gerektiğini düşünüyorum. Bir biçimde ad alanı olmalı.
      Örneğin mkfs bence sys::mkfs gibi çağrılmalı. Sistem komutlarıyla kullanıcı komutlarını ayıran çizgi çeşitli şekillerde tanımlanabilir ve gri alanlar da olur; ama kullanıcı, varlığını bile bilmediği ve açıkça kurmadığı bir komutu yanlışlıkla çalıştırabiliyorsa, o komut doğrudan küresel ad alanına açık olmamalı.
  • İlgili bir soru var
    Çoğunlukla Windows kullanıyorum ve yazar gibi Python ağırlıklı birkaç CLI betiği oluşturup ~/bin/ karşılığı bir yere koyuyorum. python.exeyi .py uzantısının varsayılan programı olarak ayarlayıp .pyyi %pathext%e ekleyince, herhangi bir dizinden sadece hello yazarak ~/bin/hello.pyyi çalıştırabiliyorum ve bunu günde yüzlerce kez kullanıyorum. Son zamanlarda Linux’u daha çok kullanıyorum ama hâlâ acemi olduğum için aynı şekilde yapamadım. Linux’ta “ilişkilendirilmiş program” kavramı yok gibi; bu yüzden .py dosyasını doğrudan çağırıp kabuğun bunu Python ile çalıştırmasını sağlayamıyorum. Elbette betiğe chmod +x verebilirim, ama o zaman betiğin içine shebang koymam gerekiyor; bu da hardcode edilmiş gibi hissettirdiği için rahatsız ediyor. İleride .py betiklerini /usr/bin/python yerine /usr/bin/nohtyp ile çalıştırmak istersem ne olacak diye düşünüyorum. Üstelik betiği çağırırken .py kısmını atlamanın bir yolunu da bulamadım. Linux tasarımını eleştirmeye çalışmıyorum; pek çok avantajı olduğunu biliyorum, ama gerçekten $PATH içindeki hello.pyyi hello olarak çalıştırmak istiyorum

    • Linux’ta bu sorun için doğru aracın hâlâ shebang olduğunu düşünüyorum. Hafif bir çözüm için yolunuzda my_python adlı bir sembolik bağlantı bulundurup shebang’i /usr/bin/env my_python olarak yazabilirsiniz
      Daha ilkeli bir yaklaşım isterseniz update-alternatives aracına bakabilirsiniz. Bu tür soyutlamayı daha genel biçimde sağlar: https://linuxconfig.org/how-to-set-default-programs-using-up...
    • Çözümü başkaları zaten söylemiş, ama nedenine dair bir şey eklemek istiyorum
      Linux’ta, aslında Windows dışındaki çoğu platformda dosya uzantılarının anlamı çok daha zayıftır. Herhangi bir tür yürütülebilir dosyanın çalıştırılabilir olup olmadığı uzantıya göre değil, +x bayrağı gibi şeylere göre belirlenir. Bu sayede uygulama dilini değiştirseniz bile çağıran tarafı bozmadan yeniden yazabilirsiniz. .py uzantısı ancak içe aktarılıp kullanılan modüller için anlamlıdır; çalıştırılan bir betikse gerektiğinde shebang’e bakılır. Dışarı dağıtılan betikler genelde #!/usr/bin/env python kullanır, dağıtım paketlerine dahil betiklerin shebang’i ise #!/usr/bin/python vb. ile değiştirilir. Ayrıca shebang birden fazla argümanı desteklemez, ancak GNU env bunu taklit edebilen -S argümanını destekler. Yine de argüman uzunluğu sorunu kalır
    • Dosya adından .pyyi çıkarın yeter. Ona "hello" demek tamamen sorun değil
      Shebang’in aklıma gelen pek bir dezavantajı yok. Gerçekten farklı bir yorumlayıcıyla çalıştırmak istiyorsanız "nohtyp hello" diye açıkça belirtebilirsiniz. Yine de çok rahatsız ediyorsa kabuk başlangıç dosyanızda bir alias tanımlayabilirsiniz. Örneğin bash’te alias hello="python3 /path/to/hello.py" yapabilirsiniz. İsterseniz belirli bir dizinin içeriği için bu tür alias’ları otomatik oluşturan kısa bir betik de yazabilirsiniz
    • Böyle bir kavram var, ama kabuk sözdiziminin içinde değil. Genelde masaüstü/GUI’ye bırakılan uygulama düzeyi bir mesele
      Kabuk betiklerinde genellikle shebang eklenir ve dosya çalıştırılabilir yapılır; böylece çalıştırılacak program betiğin içinde bildirilmiş olur. Shebang’i bir tür dosya uzantısı gibi düşünebilirsiniz. chmod +x ./malware.py sonrası ./malware.py çalışmıyorsa shebang’in işaret ettiği yolu kontrol etmek gerekir. Yorumlayıcı betiği normal bir argüman olarak çalıştırabiliyorsa xdg-open malware.py gibi bir yöntemle de benzer davranış elde edilebilir. Bu, varsayılan dosya yöneticisinde çift tıklamakla aynı şey olur. Linux’u ana masaüstü işletim sistemi olarak kullandığım dönemde xop adlı bir alias’ım vardı, ama bunu yalnızca varsayılan davranışı zaten doğru olan resim veya belge gibi veri dosyalarında kullanıyordum. Çalıştırılabilir betiklerin varsayılan programını yorumlayıcı olarak ayarlamayı önermem. Varsayılan olarak betikleri çalıştırmak yerine bir düzenleyicide açmak isteyebilirsiniz. xdg-openun Gnome tarafına ait bir araç olduğunu düşünüyorum; ama bu başka masaüstlerinde kullanılamaz demek değil, Xubuntu’da da kullanmıştım. Gerçekten tüm Python dosyalarını GUI bağlamında da varsayılan olarak çalıştırmak istiyorsanız böyle bir varsayılan ayarlayabilirsiniz; man xdg-open yardımcı olabilir. Tekrar söyleyeyim, bu iyi bir tavsiye değil
    • Hedefinizi doğrudan sağlamaz ama shebang yalnızca yarı hardcode sayılır. Shebang kullanmanın “doğru” yolu, bazı dikkat noktaları için https://unix.stackexchange.com/a/29620 bağlantısına bakılsa da, #!/usr/bin/env python şeklindedir
      Böylece yolda ilk bulunan python çalıştırılır. İleride /usr/bin/python yerine /usr/bin/nohtyp ile çalıştırmak isterseniz, /usr/binden önce aranan bir dizinde /usr/bin/nohtypi gösteren bir python sembolik bağlantısı oluşturabilirsiniz. Örneğin ~/myCommandPreferencesi $PATHin başına ekleyebilirsiniz
  • $PATH çakışmalarından kaçınmanın başka bir yolu, başka yürütülebilir dosyaların kullanma olasılığı düşük olan çok uzun bir yürütülebilir dosya adı oluşturup bashrcye kısa bir alias koymaktır
    Alias, betik içinde çağrılan yürütülebilir dosyaları etkilemez; kendi betiklerimde uzun adla referans vermeye devam edebilirim. Dezavantajı aynı düzeyde Tab otomatik tamamlama kullanılabilirliği sağlamaması; o kısım gerçekten güzel. Ayrıca Python’ın venv etkinleştirme betiği gibi alt süreç olarak çalıştırılmayıp source edilmesi gereken betiklerde hâlâ çakışma olabilir, ama bu tür durumlar nadirdir

    • zshte o otomatik tamamlama da çalışıyor
  • Virgülle başlatma yöntemi metin genişletici/metin değiştirme topluluklarında da yaygın bir tekniktir

    • Doğru. vim alias’larımın çoğu da , ile başlıyor
  • Geçenlerde ~/.local/bin/ içine bakarken, koyduğumu hatırlamadığım onlarca yürütülebilir dosya olduğunu fark ettim
    Çoğu pyside ile ilgiliydi ama başka betikler de vardı. Hangi betiği kendim yazdım, hangisi başkasının yaptığıydı hatırlamak için tek tek açmam gerekti. Kendi betiklerimin adını virgülle başlatmış olsaydım çok daha hızlı olurdu; ayrıca her betiği neden oluşturduğumu açmadan önce hatırlamama da yardımcı olurdu

    • Genelde ~/.local/bin/ kurulu betikler içindir; yerelde bizzat yazdıklarım ise ~/bin/ altında durur
  • Reddederim. Kişisel bin dizinimi $PATH'in başına koyar, gölgede kalan programlara başvururken /usr/bin veya /bin kullanırım
    Kişiselleştirilmiş araç listesini ~/bin/[Tab] ile listeleyebilirim

    • Sistem yardımcı programlarını kendi sürümlerime yönlendirirken aynı adları kullanmak istememeyi, bu yüzden sürekli virgülü hatırlamak zorunda kalmayı anlamıyorum
      Sistemin grepinden, örneğin Solaris grepinden hoşlanmıyor ve tercih ettiğim GNU grepi kullanmak istiyorsam, neden onu doğrudan grep olarak bırakmayayım?
  • Bu fikirle 5 yıl önce karşılaşmam, kabuk ipuçları koleksiyonuma düzen getirdi. Takma adlar ve ~/bin birleşince 50'den fazla virgül komutu var ve kabukla hayatım eski karmaşık hâline göre çok daha akıcı oldu

  • 2020'de de tartışılmıştı: https://news.ycombinator.com/item?id=22778988 (90 yorum)

 
kayws426 2024-06-24

_ kullanmak nasıl olur?