4 puntos por GN⁺ 2024-03-01 | 1 comentarios | Compartir por WhatsApp
  • Para usuarios que quieren leer contenido web directamente desde la terminal, James' Coffee Blog también ofrece las entradas del blog en formato de páginas de manual de Linux
  • Incluso con la misma URL, si el cliente envía Accept: text/roff, recibe un documento roff en lugar de HTML usando negociación de contenido HTTP
  • El archivo .man de cada entrada se genera con una plantilla que tiene las secciones TITLE, AUTHOR, PUBLISHED, POST y URL
  • En el cuerpo se usa el Markdown original para que sea más fácil de leer que HTML, aunque el espaciado en la página de manual no siempre queda perfectamente alineado
  • NGINX detecta las solicitudes text/roff y reescribe la URL al archivo .man, por lo que se puede guardar con curl y luego abrir con man ./post.page

Leer una entrada del blog con man

  • Las páginas de manual de Linux son la forma básica de consultar el uso de comandos desde la terminal, y normalmente se abren con man <command>
  • Por ejemplo, el manual del comando tac se consulta así
man tac
  • James' Coffee Blog armó un flujo para que las entradas web del blog también puedan leerse de la misma manera, descargando la versión roff desde la URL de la entrada y abriéndola con man
  • Un ejemplo real de solicitud es el siguiente
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page

Elegir el formato con negociación de contenido HTTP

  • El núcleo de la implementación es la negociación de contenido HTTP, donde el cliente le indica al servidor el formato de respuesta que quiere
  • El encabezado Accept se usa para transmitir el tipo de contenido deseado
    • Por ejemplo, Accept: image/png significa que, si es posible, se envíe un archivo PNG
    • También se pueden especificar varios tipos de contenido y prioridades, pero aquí solo se usa la solicitud de un formato específico
  • Si se quiere recibir una entrada del blog en formato de página de manual, se envía el encabezado Accept: text/roff
  • El servidor revisa ese encabezado y devuelve una respuesta text/roff que se puede abrir en man, en lugar de HTML

Cómo se generan los archivos .man

  • Las páginas de manual de Linux se escriben con sintaxis roff
  • El sitio fue modificado para generar una versión de página man para cada entrada del blog
  • La estructura de la plantilla usada es la siguiente
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
  • La plantilla usa el nombre de dominio como encabezado y crea cinco secciones
    • TITLE
    • AUTHOR
    • PUBLISHED
    • POST
    • URL
  • En el cuerpo se usa el Markdown original
    • En la página de manual el espaciado no siempre queda del todo bien
    • Aun así, resulta más fácil de leer que HTML y pierde menos información sobre títulos y separación de párrafos que el texto plano

Descargar con curl y abrir con man

  • La versión roff de una entrada del blog se puede solicitar con el siguiente comando
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
  • El resultado guardado puede abrirse como una página de manual local
man ./post.page
  • Si un navegador común solicita la misma URL de la entrada, recibe la versión HTML
  • En cambio, el comando curl de arriba solicita explícitamente la versión text/roff para esa misma URL

Reescritura a archivos .man en NGINX

  • El servidor maneja por separado las solicitudes text/roff con unas pocas líneas de configuración en NGINX
  • En /etc/nginx/nginx.conf se declara una variable que activa una marca cuando se detecta un tipo de contenido específico
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
  • En el archivo de configuración del sitio, bajo /etc/nginx/sites-enabled, se agrega una regla para manejar las solicitudes de páginas roff
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
  • Esta configuración, cuando existe el encabezado Accept: text/roff, elimina la barra final de la URL y agrega .man
  • Como resultado, NGINX lee el archivo .man correspondiente en lugar del index.html de cada entrada
  • Así, la misma entrada del blog puede leerse como HTML en un navegador web y como una página de manual de Linux en la terminal

1 comentarios

 
GN⁺ 2024-03-01
Opiniones de Hacker News
  • Estaría genial ofrecer un repositorio deb como forma de suscribirse al blog.
    Algo como traer todos los posts con apt update y poder ver el post más reciente y un enlace al índice de todos los posts con man your-blog.

    • La idea en sí es excelente, pero si se vuelve popular, las oportunidades de distribución de malware inherentes a este enfoque también parecen bastante obvias.
      Me daría miedo suscribirme.
    • Hay precedentes. Debian antes ofrecía acceso a la ya desaparecida Linux Gazette, y todavía ofrece varios paquetes informativos como documentación de paquetes, páginas de manual, páginas info, RFC, Linux HOWTO, etc.
      Se pueden ver localmente con el paquete dwww: “Read all on-line documentation with a WWW browser”
      https://packages.debian.org/bookworm/dwww
      Joerg Jaspert fue el antiguo mantenedor del paquete de Linux Gazette: https://people.debian.org/~joerg/ (2002)
      Es uno de los mejores ejemplos que he visto de integrar la entrega de información y documentación en el sistema operativo, y en particular hace que la documentación man/info sea más útil que las interfaces tradicionales basadas en terminal.
      También existe Debian Planet, un blog relacionado con Debian, pero creo que nunca se ofreció como paquete propio de Debian.
      Sinceramente, RSS probablemente sea una mejor opción para suscribirse a un blog.
    • Estoy trabajando en eso ahora.
      En https://github.com/capjamesg/jamesg.blog.deb hay material para crear un archivo deb que solo contiene la página man con los siguientes comandos:
      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
      Entonces deberías ver una salida como Processing triggers for man-db (2.9.1-1) ..., lo que significa que la página de manual para man jamesg.blog está disponible.
      Por ahora solo hay marcadores de posición, y probablemente lo termine mañana.
      Puede que pronto se convierta en un post del blog.
  • Se puede canalizar directamente a man sin necesidad de hacer fork ni usar un archivo intermedio.
    curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>;) | man -l -

    • Mejor no hacer eso. Hace 2 horas yrro publicó algo parecido, y ahora empieza otra vez la discusión sobre canalizar {curl,wget} a comandos.
      Un amigo no deja que otro amigo canalice streams directamente a comandos.
      https://news.ycombinator.com/item?id=39554044
  • Como referencia, 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 funciona en mi entorno.
    No hace falta guardar el archivo roff localmente.

    • Creo que el autor original evitó hacerlo así a propósito. Canalizar directamente comandos o contenido recibido de Internet a algo como bash suele considerarse una mala práctica.
      Personalmente me parece aceptable. Quien entiende las implicaciones de seguridad casi seguro también conoce este tipo de conversión, así que no hace falta explicárselo.
      Pero no es bueno enseñárselo a principiantes. Algún día podrían caer. A medida que mejoren, descubrirán naturalmente esta función, y espero que para entonces también hayan aprendido sus implicaciones.
      Este artículo no es mío: https://www.seancassidy.me/dont-pipe-to-your-shell.html
    • Lamentablemente, ese comando no funciona en macOS: /usr/bin/man: illegal option -- l
      Intenté crear un comando de una sola línea que use pipes en Mac, pero seguía dando error.
      La implementación de man en macOS no tiene la bandera -l. Revisé la página de manual.
    • Si usas bash, puedes ahorrar algunos caracteres con sustitución de procesos en lugar de un pipe.
      man -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)
  • Si hablamos de URLs que hacen cosas divertidas en la terminal, recuerdo algo que vi hace tiempo en textfiles.com
    Era una especie de cortometraje animado hecho con códigos de terminal VT100, y todo se servía desde un solo URI
    En sistemas modernos se puede verlo poniéndole un límite de velocidad
    curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>;) && reset
    reset está ahí porque la terminal puede quedar hecha un desastre
    Otros URI basados en terminal: curl cheat.sh/tar trae ejemplos de uso del programa después de /, y curl wttr.in/berlin trae información del clima con formato para terminal

    • Si quieres hacer directamente video ASCII con telnet, hice algo en Go hace unos años: https://github.com/bfontaine/RickASCIIRoll
      En realidad es bastante simple; la parte más difícil es generar los frames
      Eso se puede hacer con ffmpeg+img2txt.py: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...
    • Hace unos años hice un visor de arte ANSI con emulación de velocidad de módem
      Tiene un espejo antiguo de https://16colo.rs/, así que se puede ver la mayor parte del arte ANSI publicado hasta ahora
      Ejemplo: curl ansi.hrtk.in/ungenannt_1453.ans
    • Es realmente genial, pero también me destruyó por completo la terminal. Fue divertido
    • También existe Star Wars por telnet
      https://itsfoss.com/star-wars-linux/
    • Con tritty se pueden simular velocidades de transmisión de 1200/9600 BPS
  • Ahora lo único que hace falta es un convertidor de Markdown a roff; buscando, resulta que ya existen
    https://github.com/postmodern/kramdown-man
    https://rtomayko.github.io/ronn/ronn.1.html
    https://kristaps.bsd.lv/lowdown/

  • Hay un paquete de Emacs que instala SICP, de Abelson y Sussman, en el directorio Info
    Solo hay que escribir M-x package-install sicp RET
    Al ver eso, se me ocurrió que también podría instalar una biblioteca completa de archivos de blogs con un lector de feeds modificado
    Si lees Info en Emacs, también puedes usar marcadores

    • También se puede instalar chicken-scheme. Luego, ejecutarlo como root
      chicken-install srfi-203
      chicken-install srtfi216
      El ~/.csirc para SICP queda así
      (import scheme)
      (import (srfi 203))
      (import (srfi 216))
      (define (inc x) (+ x 1))
      (define (dec x) (- x 1))
      Después se usa geiser de usuario y geiser para chicken como de costumbre
    • Como referencia, SICP es obra de Abelson y Sussman
  • Quizá podría encontrar la respuesta buscando en internet, pero quiero preguntarlo en HN
    Recuerdo que en la preparatoria, en HP-UX, alguien me mostró cómo saltar a una palabra subrayada, es decir, a una referencia de sección, presionando alguna combinación de teclas, pero no logro recordar cuál era
    También revisé man(1) y man(7), pero no encontré nada. Tal vez sea un recuerdo falso

    • Si eso era man, hay que tener en cuenta que man ohman es esencialmente nroff -man /usr/share/man/man1/ohman.1 | $PAGER
      Es decir, no estás interactuando con man ni con nroff, sino con el paginador
      Hoy lo más común es less, y es muy probable que more en la práctica también sea less, pero antes había otros; HPUX quizá usaba algo como pg
      pg venía de la familia AT&T, more de la familia BSD y less de la familia GNU
      Los tres inician una búsqueda con expresión regular usando /, así que puedes encontrarlo esté subrayado o no
      less también soporta archivos de tags, así que con t puedes saltar al siguiente tag
    • No conozco bien una función separada de visor de man, pero quizá estás pensando en dthelpview, el visor de ayuda de CDE. Es posible que este mostrara páginas man
    • Esto suena a texinfo, que se abre con el comando info
      Irónicamente, buena parte de la documentación original de groff está escrita en texinfo: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
  • No sé por qué este detalle tan menor activó mi instinto de ponerme quisquilloso. Quizá porque alguien en internet estaba ligeramente equivocado.
    Puede que haya sido innecesariamente centrado en Linux desde el principio, o que yo esperara algo distinto y al final resultara ser una breve demo de negociación de contenido en NGINX.
    En fin, hay algunos puntos inútiles que igual quiero mencionar.
    Estrictamente hablando, no está devolviendo roff. Cosas como .TH no son roff en sí, sino parte de un paquete de macros para escribir páginas man.
    Me decepcionó que no hubiera conversión de Markdown a roff. Pensé que esa sería la parte interesante del artículo y, como mínimo, se podría haber usado alguna herramienta existente.
    De forma similar, por eso el formato del texto en realidad tampoco queda del todo correcto. La entrada roff espera una línea por oración para distinguir el . al final de una oración de otros usos de ..
    Además, cualquier línea que empiece con . se interpretará como un comando y puede causar problemas.
    O quizá simplemente soy un viejo gruñón.

    • Gracias por compartir esto. No sabía exactamente cómo era la relación entre roff y man, y traté de ajustarlo mientras corregía el artículo varias veces.
      La existencia de otras herramientas como groff y nroff me confundió todavía más.
      Un artículo que explique únicamente “qué son roff/man page/nroff/otras variantes y cómo se usan” ya sería suficiente para una publicación de blog.
      A mí me habría venido bien una explicación breve y clara, y creo que también le ayudaría a otras personas.
      Pensé en la conversión de Markdown a roff para una v2. Cuando empecé a pensar en implementar un parser, alguien me señaló https://github.com/sunaku/md2man, y parece que eso resuelve el problema.
      Tengo que averiguar cómo integrarlo en mi sitio en Python que corre sobre GitHub Pages, así que necesitará algo de ajuste.
    • A mí también me sorprendió bastante que no hubiera conversión de Markdown a roff.
      Pandoc puede convertir Markdown a roff de páginas man con mucha facilidad.
      Si lo metes en una plantilla dada, se verá más como una página man real.
  • El tipo de medio correcto según RFC 4263 es text/troff: https://www.rfc-editor.org/rfc/rfc4263.html

  • Es una idea genial. Ahora solo falta poner un temporizador hasta que aparezca “servir mis publicaciones de blog como un DOOM WAD jugable”.

    • Puedes agregarlo a la lista de las pocas cosas geniales en las que la IA realmente puede ayudar