4 puan yazan GN⁺ 2024-03-01 | 1 yorum | WhatsApp'ta paylaş
  • Web yazılarını doğrudan terminalde okumak isteyen kullanıcılar için James' Coffee Blog, blog yazılarını Linux kılavuz sayfası biçiminde de sunuyor
  • Aynı URL için istemci Accept: text/roff gönderirse HTML yerine roff belgesi alacak şekilde HTTP içerik pazarlığını kullanıyor
  • Her yazının .man dosyası; TITLE, AUTHOR, PUBLISHED, POST ve URL bölümlerini içeren bir şablondan oluşturuluyor
  • Gövdede HTML'den daha okunabilir olması için özgün Markdown metni kullanılmış, ancak kılavuz sayfasında boşluklar her zaman kusursuz hizalanmıyor
  • NGINX, text/roff isteklerini algılayıp URL'yi .man dosyasına yeniden yazdığı için, curl ile kaydedip ardından man ./post.page gibi açmak mümkün

Blog yazılarını man ile okumak

  • Linux'ta kılavuz sayfaları, komut kullanımını terminalden kontrol etmenin temel yoludur ve genelde man <command> ile açılır
  • Örneğin tac komutunun kılavuzu şöyle görüntülenir
man tac
  • James' Coffee Blog, web blog yazılarını da aynı şekilde okunabilir hale getirmek için, yazı URL'sinden roff sürümünü indirip man ile açılan bir akış kuruyor
  • Gerçek istek örneği şöyle
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page

HTTP içerik pazarlığıyla biçim seçimi

  • Uygulamanın merkezinde, istemcinin istediği yanıt biçimini sunucuya bildirdiği HTTP içerik pazarlığı bulunuyor
  • Accept başlığı, istenen içerik tipini iletmek için kullanılıyor
    • Örneğin Accept: image/png, mümkünse PNG dosyası gönderilmesi anlamına geliyor
    • Birden fazla içerik tipi ve öncelik de belirtilebilir, ancak burada yalnızca belirli biçim isteği kullanılıyor
  • Blog yazısını kılavuz sayfası biçiminde almak istediğinizde Accept: text/roff başlığını gönderiyorsunuz
  • Sunucu bu başlığa bakıp HTML yerine man içinde açılabilen bir text/roff yanıtı döndürüyor

.man dosyaları nasıl üretiliyor

  • Linux kılavuz sayfaları roff sözdizimiyle yazılır
  • Site, her blog yazısı için bir man sayfası sürümü üretecek şekilde değiştirilmiş
  • Kullanılan şablon yapısı şöyle
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
  • Şablon, alan adını başlık olarak kullanıp beş bölüm oluşturuyor
    • TITLE
    • AUTHOR
    • PUBLISHED
    • POST
    • URL
  • Gövdede özgün Markdown metni kullanılıyor
    • Kılavuz sayfasında boşluklar her zaman düzgün hizalanmıyor
    • Yine de HTML'den daha okunabilir ve düz metne kıyasla başlıklar ile paragraflar arasındaki bilgi kaybı daha az

curl ile alıp man ile açmak

  • Blog yazısının roff sürümü şu komutla istenebilir
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
  • Kaydedilen sonuç, yerel bir kılavuz sayfası gibi açılabilir
man ./post.page
  • Normal bir tarayıcı aynı yazı URL'sini isterse HTML sürümünü alır
  • Buna karşılık yukarıdaki curl komutu, aynı URL için text/roff sürümünü açıkça ister

NGINX'te .man dosyasına yeniden yazma

  • Sunucu, NGINX yapılandırmasında birkaç satırla text/roff isteklerini ayrı işler
  • /etc/nginx/nginx.conf içinde, belirli bir içerik tipi algılandığında bayrak ayarlayan değişkenler tanımlanır
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
  • Site yapılandırma dosyasında, /etc/nginx/sites-enabled altında roff sayfa isteklerini işleyen bir kural eklenir
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
  • Bu ayar, Accept: text/roff başlığı olduğunda URL'nin sonundaki eğik çizgiyi kaldırıp .man ekler
  • Sonuç olarak NGINX, her yazının index.html dosyası yerine karşılık gelen .man dosyasını okur
  • Böylece aynı blog yazısı web tarayıcısında HTML olarak, terminalde ise Linux kılavuz sayfası olarak okunabilir hale gelir

1 yorum

 
GN⁺ 2024-03-01
Hacker News yorumları
  • Blog aboneliği yöntemiyle bir deb deposu sunmak harika olabilir
    Tüm yazıları apt update ile alıp, man your-blog ile de en güncel yazıyı ve tüm yazıların dizin bağlantısını görmek gibi

    • Fikrin kendisi harika ama yaygınlaşırsa bu yöntemin doğasında bulunan kötü amaçlı yazılım dağıtma fırsatları da oldukça bariz görünüyor
      Abone olmaya çekinirdim
    • Bunun örnekleri var. Debian eskiden artık ortadan kalkmış olan Linux Gazette erişimini sunuyordu ve bugün de paket belgeleri, man sayfaları, info sayfaları, RFC’ler, Linux HOWTO’ları gibi çeşitli bilgilendirici paketler sunuyor
      Bunlar yerelde dwww paketiyle görülebiliyor: “Read all on-line documentation with a WWW browser”
      https://packages.debian.org/bookworm/dwww
      Joerg Jaspert eskiden Linux Gazette paket bakımcısıydı: https://people.debian.org/~joerg/ (2002)
      Bu, işletim sistemine bilgi aktarımı ve belgelendirmenin entegre edildiği örnekler arasında şimdiye kadar gördüklerimin en iyilerinden biriydi; özellikle de man/info belgelerini geleneksel terminal tabanlı arayüzlerden daha kullanışlı hale getiriyordu
      Debian’la ilgili bir blog olan Debian Planet de var ama Debian’ın kendi paketi olarak sunulmuş gibi görünmüyor
      Açıkçası blog aboneliği için RSS muhtemelen daha iyi bir seçimdir
    • Şu anda bunun üzerinde çalışıyorum
      https://github.com/capjamesg/jamesg.blog.deb adresinde aşağıdaki komutlarla yalnızca man sayfaları içeren bir deb dosyası oluşturmayı sağlayan içerik var
      git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>;)
      cd jamesg.blog.deb
      dpkg-deb --build --root-owner-group jamesg.blog
      sudo dpkg -i jamesg.blog.deb
      Ardından Processing triggers for man-db (2.9.1-1) ... gibi bir çıktı göreceksiniz; bu da man jamesg.blog için man sayfasının kullanılabilir olduğu anlamına gelir
      Şu an sadece yer tutucular var, muhtemelen yarın bitiririm
      Yakında bir blog yazısına da dönüşebilir
  • Fork’lamaya veya ara dosya kullanmaya gerek kalmadan doğrudan mane pipe edebilirsiniz
    curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>;) | man -l -

    • Bunu yapmamak daha iyi. İki saat önce yrro da benzer bir şey paylaşmıştı, şimdi yine {curl,wget} çıktısını komutlara pipe etme tartışması başlıyor
      Bir dost, akışı doğrudan komuta pipe etmenize izin vermez
      https://news.ycombinator.com/item?id=39554044
  • Bu arada curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>;) | man -l /dev/stdin benim ortamımda çalışıyor
    roff dosyasını yerelde kaydetmeye gerek yok

    • Görünüşe göre asıl yazının yazarı bunu özellikle bu şekilde yapmamış. İnternetten alınan komutları ya da içeriği doğrudan bash gibi bir şeye pipe etmek genelde kötü bir pratik sayılır
      Ben şahsen bunun sorun olmadığını düşünüyorum. Güvenlik açısından bunun ne anlama geldiğini bilen biri, bu dönüşüm yöntemini de neredeyse kesin biliyordur; o yüzden ayrıca anlatmaya gerek yok
      Ama yeni başlayanlara göstermek için iyi değil. Bir gün başlarına iş açabilir. Becerileri arttıkça bu tür işlevleri doğal olarak öğrenirler ve umarım o zamana kadar sonuçlarını da öğrenmiş olurlar
      Bunu ben yazmadım: https://www.seancassidy.me/dont-pipe-to-your-shell.html
    • Ne yazık ki bu komut macOS’ta çalışmıyor: /usr/bin/man: illegal option -- l
      Mac’te pipe kullanan tek satırlık bir komut oluşturmaya çalıştım ama sürekli hata aldım
      macOS’in man uygulamasında -l bayrağı yok. Man sayfasını kontrol ettim
    • bash kullanıyorsanız pipe yerine process substitution ile birkaç karakter kısaltabilirsiniz
      man -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)
  • Terminalde eğlenceli şeyler yapan URL’lerden söz açılmışken, yıllar önce textfiles.com’da gördüğüm bir şey vardı
    VT100 terminal kodlarıyla kısa bir animasyon filmi gösteriyordu ve her şey tek bir URI üzerinden sunuluyordu
    Modern sistemlerde hız sınırı koymayı deneyebilirsiniz
    curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>;) && reset
    Terminal bozulabildiği için reset eklenmiş
    Diğer terminal tabanlı URI’lere örnek olarak curl cheat.sh/tar komutundan / sonrasındaki program için kullanım örnekleri gelir; curl wttr.in/berlin ise terminal biçimlendirmesi uygulanmış hava durumu bilgisini getirir

    • Telnet üzerinden doğrudan ASCII video üretmek istiyorsanız, bunun için birkaç yıl önce Go ile yaptığım bir şey var: https://github.com/bfontaine/RickASCIIRoll
      Aslında oldukça basit; en zor kısım kareleri üretmek
      Bu da ffmpeg+img2txt.py ile yapılabiliyor: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...
    • Birkaç yıl önce modem hızı emülasyonu içeren bir ANSI art görüntüleyici yapmıştım
      https://16colo.rs/ için eski bir ayna var; şimdiye kadar yayımlanmış ANSI art çalışmalarının çoğunu görebilirsiniz
      Örnek: curl ansi.hrtk.in/ungenannt_1453.ans
    • Gerçekten harika, ama terminali de tamamen bozdu. Eğlenceliydi
    • Telnet üzerinden izlenen bir Star Wars da var
      https://itsfoss.com/star-wars-linux/
    • tritty kullanırsanız 1200/9600 BPS aktarım hızını taklit edebilirsiniz
  • Şimdi gereken tek şey Markdown’ı roff’a dönüştüren bir dönüştürücü; ama bakınca bunun zaten var olduğunu gördüm
    https://github.com/postmodern/kramdown-man
    https://rtomayko.github.io/ronn/ronn.1.html
    https://kristaps.bsd.lv/lowdown/

  • Emacs paketleri arasında Abelson ve Sussman’ın SICP kitabını Info dizinine kuran bir paket var
    Sadece M-x package-install sicp RET yazmanız yeterli
    Bunu görünce, değiştirilmiş bir feed okuyucuyla blog arşivlerindeki tüm kitap rafını da kurmanın mümkün olabileceğini düşündüm
    Emacs’te Info okurken yer imi de kullanabilirsiniz

    • chicken-scheme de kurulmalı. Sonra root olarak çalıştırın
      chicken-install srfi-203
      chicken-install srtfi216
      SICP için ~/.csirc şöyle olmalı
      (import scheme)
      (import (srfi 203))
      (import (srfi 216))
      (define (inc x) (+ x 1))
      (define (dec x) (- x 1))
      Sonrasında her zamanki gibi user geiser ve chicken için geiser kullanabilirsiniz
    • Bilgi olarak, SICP’nin sorumluları Abelson ve Sussman
  • İnternette ararsam cevabı bulabilirim belki ama bunu HN’ye sormak istedim
    Lisede HP-UX üzerinde birinin altı çizili bir sözcüğe, yani bir bölüm başvurusuna, belli bir tuş kombinasyonuyla atladığını gösterdiğini hatırlıyorum ama bunun hangi tuş olduğunu bir türlü çıkaramıyorum
    man(1) ve man(7) sayfalarına da baktım ama bulamadım. Sahte bir anı da olabilir

    • Eğer bu man içindeyse, man ohmanın özünde nroff -man /usr/share/man/man1/ohman.1 | $PAGER olduğunu düşünmek gerekir
      Yani man ya da nroff ile değil, pager ile etkileşime giriyorsunuz
      Günümüzde en yaygını less; more da fiilen less olabilir, ama eskiden başka seçenekler de vardı ve HPUX pg gibi bir şey kullanıyor olabilir
      pg AT&T kökenliydi, more BSD kökenliydi, less ise GNU kökenliydi
      Üçü de / ile regex aramayı başlatır; dolayısıyla altı çizili olup olmamasına bakmadan bulunabilir
      less, etiket dosyalarını da destekler; t ile bir sonraki etikete atlayabilirsiniz
    • Ayrı bir man görüntüleyici özelliği bilmiyorum ama aklınızda kalan şey, CDE yardım görüntüleyicisi olan dthelpview olabilir. Bu, man sayfalarını gösteriyor olabilir
    • Bu, info komutuyla açılan texinfo gibi geliyor
      İşin ironik yanı, groff belgelerinin önemli bir kısmı aslında texinfo ile yazılmıştır: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
  • Bunun neden benim kusur bulma içgüdümü tetiklediğini bilmiyorum. Belki de internette birisi hafifçe yanıldığı içindir
    En başından gereksiz yere Linux merkezli olması ya da başka bir şey bekleyip sonunda NGINX'in içerik uzlaşımı için kısa bir demosu çıkması da olabilir
    Her neyse, özellikle söylemek istediğim birkaç gereksiz nokta var
    Teknik olarak roff döndürmüyor. .TH gibi şeyler roff'un kendisi değil, man sayfası yazmak için kullanılan bir makro paketinin parçası
    Markdown-to-roff dönüşümü olmaması hayal kırıklığı yarattı. Yazının ilginç kısmının bu olacağını sanmıştım ve en azından mevcut araçlardan biri kullanılabilirdi
    Benzer şekilde, bu yüzden metin biçimlendirmesi de aslında tam olarak doğru değil. roff girdisi, cümle sonundaki . ile başka amaçla kullanılan . işaretini ayırt etmek için kasıtlı olarak cümle başına bir satır kullanır
    Ayrıca . ile başlayan tüm satırlar komut olarak yorumlanıp sorun çıkarabilir
    Ya da sadece huysuz bir yaşlı olabilirim

    • Bunu paylaştığın için teşekkürler. roff ile man arasındaki ilişkinin tam olarak nasıl yapılandığını bilmiyordum ve bu yazıyı birkaç kez düzeltirken bunu oturtmaya çalıştım
      groff, nroff gibi başka araçların olması da işi daha kafa karıştırıcı hale getirdi
      “roff/man page/nroff/diğer varyantlar nedir ve nasıl kullanılır” konusunu anlatan bir yazı tek başına gayet bir blog yazısı olurdu
      Kısa ve net bir açıklama olsa ben de memnun olurdum; başkalarına da faydalı olur gibi geliyor
      Markdown-to-roff'u v2 için düşünmüştüm. Ayrıştırıcıyı yazmayı düşünmeye başladığım sırada biri https://github.com/sunaku/md2man bağlantısını verdi ve bu sorunu çözüyor gibi görünüyor
      GitHub Pages üzerinde çalışan Python siteme bunu nasıl entegre edeceğimi bulmam gerekecek, o yüzden biraz kurcalamam lazım
    • Markdown-to-roff dönüşümünün olmaması beni de epey şaşırttı
      Pandoc Markdown'ı man-page roff'a çok kolay dönüştürebiliyor
      Bunu verilen şablona koyarsan gerçek bir man sayfası gibi daha iyi görünecektir
  • Doğru medya tipi RFC 4263'e göre text/troff: https://www.rfc-editor.org/rfc/rfc4263.html

  • Harika bir fikir. Şimdi sırada “blog yazılarımı oynanabilir bir DOOM WAD olarak sunmak” ne zaman gelecek diye kronometre tutabiliriz

    • Bunu, AI'nin gerçekten yardımcı olabileceği az sayıdaki havalı şeyler listesine ekleyebiliriz