- Để phục vụ người dùng muốn đọc bài viết web trực tiếp trong terminal, James' Coffee Blog cũng cung cấp bài viết blog ở định dạng trang hướng dẫn Linux
- Dù cùng một URL, nếu client gửi
Accept: text/roff thì sẽ nhận về tài liệu roff thay vì HTML bằng cách dùng cơ chế thương lượng nội dung HTTP
- Mỗi tệp
.man của bài viết được tạo từ một mẫu có các phần TITLE, AUTHOR, PUBLISHED, POST và URL
- Phần nội dung chính dùng Markdown gốc để dễ đọc hơn HTML, nhưng khoảng cách trong trang hướng dẫn không phải lúc nào cũng được căn thật gọn gàng
- NGINX phát hiện yêu cầu
text/roff và viết lại URL sang tệp .man, nên có thể lưu bằng curl rồi mở như man ./post.page
Đọc bài viết blog bằng man
- Trang hướng dẫn của Linux là cách cơ bản để xem cách dùng lệnh trong terminal, thường có thể mở bằng
man <command>
- Ví dụ, có thể xem hướng dẫn của lệnh
tac như sau
man tac
- James' Coffee Blog cũng dựng quy trình để bài viết blog trên web có thể được đọc theo cùng cách đó: tải phiên bản
roff từ URL bài viết rồi mở bằng man
- Ví dụ yêu cầu thực tế như sau
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page
Chọn định dạng bằng thương lượng nội dung HTTP
- Trọng tâm của cách triển khai là thương lượng nội dung HTTP, nơi client báo cho server biết định dạng phản hồi mà nó muốn
- Header
Accept được dùng để truyền loại nội dung mong muốn
- Ví dụ
Accept: image/png có nghĩa là nếu có thể thì hãy gửi tệp PNG
- Cũng có thể chỉ định nhiều loại nội dung và mức ưu tiên, nhưng ở đây chỉ dùng yêu cầu một định dạng cụ thể
- Khi muốn nhận bài viết blog dưới dạng trang hướng dẫn, hãy gửi header
Accept: text/roff
- Server sẽ nhìn vào header này và trả về phản hồi text/roff có thể mở bằng
man thay vì HTML
Cách tạo tệp .man
- Trang hướng dẫn Linux được viết bằng cú pháp roff
- Trang web đã được chỉnh sửa để tạo phiên bản trang
man cho từng bài viết blog
- Cấu trúc mẫu được dùng như sau
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
- Mẫu này dùng tên miền làm header và tạo năm phần
- TITLE
- AUTHOR
- PUBLISHED
- POST
- URL
- Phần nội dung chính dùng Markdown gốc
- Khoảng cách trong trang hướng dẫn không phải lúc nào cũng khớp đẹp
- Tuy vậy, nó vẫn dễ đọc hơn HTML và ít làm mất thông tin về tiêu đề, đoạn văn hơn so với văn bản thuần túy
Tải bằng curl và mở bằng man
- Có thể yêu cầu phiên bản
roff của bài viết blog bằng lệnh sau
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
- Kết quả đã lưu có thể mở như một trang hướng dẫn cục bộ
man ./post.page
- Nếu trình duyệt thông thường yêu cầu cùng URL bài viết đó, nó sẽ nhận phiên bản HTML
- Ngược lại, lệnh
curl ở trên yêu cầu rõ ràng phiên bản text/roff cho cùng URL đó
Viết lại sang tệp .man trong NGINX
- Server xử lý riêng các yêu cầu
text/roff chỉ với vài dòng cấu hình NGINX
- Trong
/etc/nginx/nginx.conf, có khai báo các biến đặt cờ khi phát hiện loại nội dung cụ thể
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
- Trong tệp cấu hình site dưới
/etc/nginx/sites-enabled, thêm quy tắc xử lý yêu cầu trang roff
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
- Cấu hình này sẽ bỏ dấu gạch chéo cuối của URL và thêm
.man khi có header Accept: text/roff
- Kết quả là NGINX sẽ đọc tệp
.man tương ứng thay vì index.html của từng bài viết
- Nhờ đó, cùng một bài viết blog có thể được đọc dưới dạng HTML trên trình duyệt web và dưới dạng trang hướng dẫn Linux trong terminal
1 bình luận
Các ý kiến trên Hacker News
Sẽ rất hay nếu cung cấp một kho lưu trữ deb theo kiểu đăng ký theo dõi blog
Kiểu như dùng
apt updateđể tải về toàn bộ bài viết, rồi dùngman your-blogđể xem bài mới nhất và liên kết tới chỉ mục toàn bộ bài viếtCó lẽ sẽ thấy sợ khi đăng ký theo dõi
Có thể xem chúng cục bộ bằng gói dwww: “Read all on-line documentation with a WWW browser”
https://packages.debian.org/bookworm/dwww
Joerg Jaspert từng là người bảo trì gói Linux Gazette: https://people.debian.org/~joerg/ (2002)
Đây là một trong những ví dụ hay nhất tôi từng thấy về việc tích hợp truyền tải thông tin và tài liệu vào hệ điều hành, đặc biệt làm cho tài liệu man/info hữu ích hơn so với giao diện truyền thống dựa trên terminal
Cũng có blog liên quan đến Debian là Debian Planet, nhưng có vẻ nó chưa từng được cung cấp dưới dạng gói của chính Debian
Thành thật mà nói, RSS có lẽ là lựa chọn tốt hơn cho việc đăng ký theo dõi blog
Ở https://github.com/capjamesg/jamesg.blog.deb có nội dung để tạo một file deb chỉ chứa trang man bằng các lệnh sau
git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>)cd jamesg.blog.debdpkg-deb --build --root-owner-group jamesg.blogsudo dpkg -i jamesg.blog.debKhi đó bạn sẽ thấy đầu ra kiểu
Processing triggers for man-db (2.9.1-1) ..., nghĩa là trang manual choman jamesg.blogđã sẵn sàng dùng đượcHiện giờ chỉ mới có nội dung giữ chỗ, có lẽ ngày mai tôi sẽ hoàn thiện
Có thể sắp thành một bài blog
Không cần fork hay ghi file trung gian, có thể pipe thẳng vào
mancurl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l -{curl,wget}vào lệnh lại bắt đầuBạn bè thì không để bạn mình pipe stream trực tiếp vào lệnh
https://news.ycombinator.com/item?id=39554044
Để tham khảo,
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/stdinchạy được trong môi trường của tôiKhông cần lưu file roff cục bộ
bashthường được coi là thói quen xấuCá nhân tôi thì thấy ổn. Ai hiểu ý nghĩa bảo mật thì gần như chắc chắn cũng biết cách biến đổi này, nên không cần phải chỉ ra
Nhưng nói cho người mới thì không hay. Một ngày nào đó họ có thể dính đòn. Khi kỹ năng tăng lên, họ sẽ tự nhiên biết các tính năng như vậy, và hy vọng lúc ấy họ cũng đã học được các hệ quả đi kèm
Không phải bài do tôi viết: https://www.seancassidy.me/dont-pipe-to-your-shell.html
/usr/bin/man: illegal option -- lTôi đã thử tạo một lệnh một dòng dùng pipe trên Mac nhưng liên tục gặp lỗi
Triển khai
mancủa macOS không có cờ-l. Tôi đã kiểm tra trang manualman -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)Nếu nói về các URL làm những thứ thú vị trong terminal, tôi từng thấy một cái trên textfiles.com
Nó có dạng chiếu một phim hoạt hình ngắn bằng mã terminal VT100, và toàn bộ được cung cấp từ một URI duy nhất
Trên các hệ thống hiện đại có thể đặt giới hạn tốc độ để xem
curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>) && resetresetđược thêm vào vì terminal có thể bị hỏngCác URI dựa trên terminal khác gồm
curl cheat.sh/tar, lấy ví dụ sử dụng chương trình sau dấu/, vàcurl wttr.in/berlin, lấy thông tin thời tiết đã được định dạng cho terminalThực ra nó khá đơn giản, phần khó nhất là tạo frame
Việc này có thể làm bằng
ffmpeg+img2txt.py: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...Vì có một mirror cũ của https://16colo.rs/, nên có thể xem phần lớn ANSI art đã được công khai cho đến nay
Ví dụ:
curl ansi.hrtk.in/ungenannt_1453.anshttps://itsfoss.com/star-wars-linux/
trittycó thể mô phỏng tốc độ truyền 1200/9600 BPSGiờ thứ cần có chỉ là một bộ chuyển đổi Markdown sang roff, mà tìm thử thì đã có sẵn rồi
https://github.com/postmodern/kramdown-man
https://rtomayko.github.io/ronn/ronn.1.html
https://kristaps.bsd.lv/lowdown/
[0]: https://pandoc.org/
md2groffđã tồn tại từ lâu trong các cộng đồng kiểu suckless/2f30/cat-vhttps://codeberg.org/nereusx/md2roff
Có một gói Emacs cài SICP của Abelson và Sussman vào thư mục Info
Chỉ cần nhập
M-x package-install sicp RETThấy vậy, tôi nghĩ cũng có thể cài cả một giá sách archive blog bằng feed reader đã chỉnh sửa
Đọc Info trong Emacs thì cũng dùng được bookmark
chicken-schemelà được. Sau đó chạy với quyền rootchicken-install srfi-203chicken-install srtfi216~/.csirccho SICP như sau(import scheme)(import (srfi 203))(import (srfi 216))(define (inc x) (+ x 1))(define (dec x) (- x 1))Sau đó cứ dùng geiser user và geiser cho chicken như bình thường là được
Có lẽ tìm trên Internet là ra câu trả lời, nhưng tôi muốn hỏi HN
Tôi nhớ hồi trung học trên HP-UX, có ai đó đã chỉ cách nhấn một tổ hợp phím nào đó để nhảy tới một từ được gạch dưới, tức là một tham chiếu section, nhưng tôi không tài nào nhớ đó là phím gì
Tôi đã kiểm tra cả
man(1)vàman(7)nhưng không tìm thấy. Có thể đó là ký ức giảman ohmanvề bản chất lànroff -man /usr/share/man/man1/ohman.1 | $PAGERTức là bạn không tương tác với man hay nroff, mà đang tương tác với pager
Ngày nay
lesslà phổ biến nhất, vàmorethực tế cũng nhiều khả năng là less, nhưng ngày xưa còn có các thứ khác, và HPUX có thể đã dùng thứ nhưpgpgthuộc dòng AT&T,morethuộc dòng BSD, cònlessthuộc dòng GNUCả ba đều bắt đầu tìm kiếm regex bằng
/, nên có thể tìm bất kể có gạch dưới hay khônglesscũng hỗ trợ file tag, nên có thể nhảy tới tag tiếp theo bằngtdthelpview, trình xem trợ giúp CDE. Nó có thể đã hiển thị man pageinfoTrớ trêu là khá nhiều tài liệu groff gốc được viết bằng texinfo: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
Không hiểu sao chi tiết nhỏ nhặt này lại kích hoạt bản năng bắt bẻ của tôi. Có lẽ vì ai đó trên Internet hơi sai
Có thể vì ngay từ đầu nó đã quá thiên về Linux một cách không cần thiết, hoặc vì tôi kỳ vọng điều gì đó khác nhưng rốt cuộc lại chỉ là một demo ngắn về content negotiation của NGINX
Dù sao thì cũng có vài điểm vô bổ mà tôi cứ muốn nói ra
Nói nghiêm túc thì nó không trả về roff. Những thứ như
.THkhông phải bản thân roff, mà là một phần của gói macro để viết trang manTôi hơi thất vọng vì không có chuyển đổi Markdown-to-roff. Tôi tưởng đó mới là phần thú vị của bài này, và ít nhất cũng có thể dùng một công cụ sẵn có nào đó
Tương tự, vì vậy mà định dạng văn bản thực ra cũng không hẳn đúng. Đầu vào roff chủ ý dùng mỗi câu một dòng để phân biệt dấu
.ở cuối câu với dấu.dùng cho mục đích khácNgoài ra, mọi dòng bắt đầu bằng
.đều có thể bị diễn giải là lệnh và gây vấn đềHoặc đơn giản là tôi chỉ là một ông già khó tính
Có những công cụ khác như
groff,nroffnên lại càng rối hơnChỉ riêng một bài giải thích “roff/man page/nroff/các biến thể khác là gì và dùng như thế nào” cũng đủ thành một bài blog rồi
Nếu có một phần giải thích ngắn gọn, rõ ràng thì tôi cũng sẽ thích, và có lẽ cũng hữu ích cho người khác
Markdown-to-roff thì tôi nghĩ để dành cho v2. Khi tôi bắt đầu cân nhắc triển khai parser, có người chỉ cho tôi https://github.com/sunaku/md2man, và có vẻ vấn đề này đã được giải quyết
Tôi cần tìm cách tích hợp nó vào site Python của mình chạy trên GitHub Pages, nên sẽ phải chỉnh sửa đôi chút
Pandoc có thể chuyển Markdown sang roff dạng man page rất dễ dàng
Nếu đưa nó vào template đã cho thì trông sẽ giống một trang man thật hơn
Media type đúng theo RFC 4263 là text/troff: https://www.rfc-editor.org/rfc/rfc4263.html
Ý tưởng hay đấy. Giờ chỉ cần bấm giờ xem bao lâu nữa sẽ có “cung cấp bài blog của tôi dưới dạng DOOM WAD có thể chơi được”