2 điểm bởi GN⁺ 2024-06-24 | 2 bình luận | Chia sẻ qua WhatsApp
  • Người dùng Unix thường đặt các script cá nhân vào ~/bin/ và thêm vào PATH, nhưng các tên lệnh ngắn có thể xung đột với lệnh hệ thống mới
  • Trong môi trường có nhiều lệnh được cung cấp như Debian/Ubuntu, rủi ro này còn lớn hơn; ví dụ trên một laptop Ubuntu, số lệnh trong /usr/bin được thống kê là 21.733
  • Nếu thêm dấu phẩy (,) vào trước lệnh cá nhân, shell và các công cụ sẽ coi đó là ký tự tên tệp thông thường, đồng thời dễ phân biệt với lệnh hệ thống
  • Dấu phẩy có thể gõ mà không cần Shift, và ít khả năng gây xung đột hơn ngoặc, dấu gạch chéo ngược, dấu hai chấm, dấu backtick, dấu nháy đơn, dấu gạch chéo và dấu chấm vốn mang ý nghĩa mạnh trong shell
  • Nhấn Tab sau , cho phép duyệt ngay danh sách lệnh cá nhân, giúp giữ cho tên lệnh trong ~/bin/ gọn gàng hơn

Vì sao tên lệnh cá nhân bị xung đột

  • Nhiều người dùng Unix tạo ~/bin/ trong thư mục home và thêm nó vào PATH để dùng các lệnh tiện ích cá nhân và shell script
  • Vấn đề là tên script cá nhân thường là các tổ hợp chữ thường ngắn, nên rất dễ giống với lệnh hệ thống mặc định
  • Khi bản phân phối Linux thêm lệnh mới, tên của nó có thể tình cờ trùng với lệnh cá nhân đang có
  • Trong môi trường họ Debian, số lượng lệnh được cung cấp rất lớn nên vấn đề này càng thực tế hơn
    • Trên một laptop Ubuntu mẫu, khi đếm số lệnh ngay dưới /usr/bin thì ra 21,733
    • apt-file search -x '^/usr/bin/[^/]*$' | wc -l

Lợi ích của tiền tố dấu phẩy

  • Giải pháp là đổi tên lệnh cá nhân sang một dạng vừa dễ gõ vừa khó bị chọn làm tên lệnh hệ thống
  • Tiêu chí về sự tiện khi gõ là không cần dùng phím Shift, và với điều kiện này thì không có nhiều ký tự an toàn để chọn
    • Chữ thường đã được dùng rất phổ biến trong lệnh hệ thống
    • Ngoặc, dấu gạch chéo ngược, dấu hai chấm, dấu backtick và dấu nháy đơn đều có ý nghĩa đặc biệt trong shell
    • Dấu gạch chéo là ký tự phân tách thư mục nên không thể nằm trong tên tệp
    • Dấu chấm ở đầu tên tệp biểu thị tệp ẩn, và ở vị trí khác cũng thường được dùng để phân tách phần mở rộng
  • Lựa chọn còn lại đơn giản là dấu phẩy (,), và các công cụ xung quanh cùng shell đều xử lý dấu phẩy như một ký tự thông thường trong tên tệp
  • Nếu thêm dấu phẩy làm tiền tố cho từng lệnh cá nhân, chúng sẽ được phân biệt rõ với lệnh hệ thống và dễ tránh xung đột tên hơn
  • Khi dùng cùng Tab completion, chỉ cần gõ , là có thể xem ngay danh sách lệnh cá nhân
    • Danh sách ví dụ gồm ,complete-scp, ,complete-ssh, ,coreoff, ,coreon, ,find, ,go-thpgp, ,gr, ,hss, ,mount-thpgp, ,mount-twt, ,range, ,svn-store-password, ,umount
  • Cách này đã được dùng trong khoảng 10 năm và được khuyến nghị như một phương pháp giữ cho các tên lệnh trong ~/bin/ sạch sẽ, ngăn nắp

2 bình luận

 
GN⁺ 2024-06-24
Các ý kiến trên Hacker News
  • Chỉ nhìn tiêu đề thì tôi tưởng đây sẽ là một ý tưởng khủng khiếp, nhưng thực ra tôi lại khá thích. Đặc biệt tôi thích phần liệt kê toàn bộ công cụ của mình bằng phím Tab
    Gần đây tôi không gặp nhiều xung đột namespace, và đúng là sau khi chuyển sang vai trò quản lý thì cảm giác kỹ thuật của tôi cũng hơi lỏng đi. Tech stack của tôi có cảm giác lỗi thời khoảng 10 năm, nên tôi tự hỏi nên bắt đầu từ đâu để bắt kịp lại cảm giác hiện đại

    • Cách hay ho ngày nay có vẻ là tự làm thứ gì đó trong thời gian rảnh, rồi học một cách tự nhiên trong quá trình làm. Tự cung tự cấp, sáng tạo, thái độ tự khởi xướng là tinh thần hiện nay; càng làm nhiều, bạn càng có động lực tự tìm ra cách giải quyết vấn đề thực tế và các giải pháp hiện đại
    • Tôi cũng ở phía quản lý, và cảm thấy nếu không tiếp tục theo kịp thì kỹ năng kỹ thuật sẽ thoái hóa
      Cách tôi làm là tự tạo các công cụ giúp cuộc sống của mình dễ hơn. Ví dụ, nếu ở công ty có một web service tôi thường dùng cho các truy vấn đơn giản, tôi sẽ xem nó có API không và viết CLI để làm nhanh các tác vụ hằng ngày. Sau khi tinh chỉnh cho ưng ý, tôi chia sẻ với nhóm, nhưng thuyết phục người khác dùng thử thì khó thật. Dù vậy tôi dùng nó mỗi ngày nên cũng không quá bận tâm
    • Vì lý do tương tự, tôi đã làm một side project bằng một stack riêng đang thịnh hành hơn, thay vì stack quen thuộc trong công việc
      Mục đích là để thấy góc nhìn mới và có thể trò chuyện về các xu hướng; một phần trong số đó giờ cũng đã chuyển sang công việc. Nhờ vậy tôi cũng hiểu sâu hơn về các thành phần cũ
  • Tôi không thật sự hiểu vấn đề này. Chỉ cần đặt thư mục bin của tôi ở đầu $PATH thay vì cuối là được. Muốn xem các lệnh của mình thì cứ chạy ls ~/bin

    • Rồi có thể một công cụ nào đó kỳ vọng $0 nằm trong đường dẫn hệ thống, nhưng điều đó bị phá vỡ và bắt đầu một màn debug bực bội
      Cuối cùng chỉ là chọn loại độc nào thôi
    • Chỉ cần nhớ các tên mình đã đặt là được mà? Tôi không hiểu vì sao việc này lại được xem như một dạng hack
    • Một ưu điểm là có thể dùng tự động hoàn thành của fzf. Ví dụ trong fish, bạn có thể gõ chữ cái đầu của lệnh rồi nhấn Tab để mở fzf
      Khi đó chỉ với ,+Tab là có thể nhanh chóng lọc các lệnh tùy chỉnh. Trong khi đó ls ~/bin thì cần gõ nhiều ký tự đối với một việc làm thường xuyên, hoặc có thể phải dùng ls+mũi tên lên nhiều lần để tìm lại phần tự động hoàn thành trước đó
    • ls ~/bin chậm hơn , rất nhiều
  • Tôi dùng các tên lệnh tùy chỉnh ngắn như aa, st, di, dp, cm, le cho một wrapper mỏng quanh git
    Một trong số đó thực sự xung đột với một tiện ích được cài mặc định trên hệ thống nào đó. Nhưng vì thư mục bin của tôi đứng trước các thư mục hệ thống trong $PATH, cái của tôi thắng, và tôi cũng không mấy quan tâm đến công cụ bị xung đột đó. Nếu một công cụ khác hữu ích với tôi xung đột với công cụ của tôi, có lẽ tôi sẽ đặt cho công cụ kia một alias không xung đột hơn là đổi tên công cụ của mình. Những công cụ hai chữ cái này quá tiện

    • Cách này có thể dẫn tới những vấn đề kiểu apt-get upgrade lại chạy Dwarf Fortress
      https://askubuntu.com/questions/938606/dwarf-fortress-starti...
    • Đúng vậy. Các tên 1–3 ký tự nên được để dành cho alias, hàm, script của người dùng và các tiện ích chuẩn
    • Alias git của tôi thường là các tổ hợp hai chữ cái bắt đầu bằng g. Ví dụ gsgit status
      Nhưng đôi khi tôi thật sự cần GhostScript. Nó rất tuyệt trong những trường hợp như nhúng phông chữ vào file PDF. Thường khi đó tôi dùng env gs
    • Các lệnh cá nhân của tôi đều bắt đầu bằng j. Khi java xuất hiện thì chuyện trở nên khá thú vị. Dùng dấu phẩy là một ý tưởng khá thú vị
      Dù sao cũng may là tôi không bắt đầu bằng k, vì KDE :)
    • Đây là suy nghĩ hơi mạnh, nhưng tôi cho rằng lệnh hệ thống không nên dễ truy cập như lệnh người dùng. Nên có một dạng namespace nào đó
      Ví dụ tôi nghĩ mkfs nên được gọi kiểu như sys::mkfs. Ranh giới giữa lệnh hệ thống và lệnh người dùng có thể được định nghĩa theo nhiều cách và cũng sẽ có chỗ mơ hồ, nhưng nếu người dùng có thể vô tình chạy một lệnh mà họ thậm chí không biết vì sao nó tồn tại và cũng chưa từng cài đặt rõ ràng, thì lệnh đó không nên được phơi bày trực tiếp trong namespace toàn cục
  • Có một câu hỏi liên quan
    Tôi chủ yếu dùng Windows, và giống tác giả, tôi tạo nhiều script CLI xoay quanh Python rồi đặt ở nơi tương đương ~/bin/. Nếu đặt python.exe làm chương trình mặc định cho phần mở rộng .py và thêm .py vào %pathext%, thì từ bất kỳ đường dẫn nào tôi cũng có thể chỉ gõ hello để chạy ~/bin/hello.py, và tôi dùng như vậy hàng trăm lần mỗi ngày. Dạo này tôi dùng Linux nhiều hơn, nhưng vẫn còn là người mới nên chưa làm được theo cùng cách đó. Có vẻ Linux không có khái niệm “chương trình được liên kết”, nên không thể gọi thẳng file .py rồi để shell chạy nó bằng Python. Tất nhiên có thể chmod +x cho script, nhưng như vậy phải đặt shebang trong chính script, cảm giác như hard-code nên không thoải mái. Tôi tự hỏi sau này nếu muốn chạy script .py bằng /usr/bin/nohtyp thay vì /usr/bin/python thì sao. Hơn nữa tôi cũng không tìm được cách bỏ phần .py khi gọi script. Tôi không có ý phê phán thiết kế của Linux, và tôi biết nó có nhiều ưu điểm, nhưng tôi thật sự muốn chạy hello.py nằm trong $PATH bằng tên hello

    • Trên Linux, tôi vẫn cho rằng shebang là công cụ phù hợp cho vấn đề này. Nếu muốn làm nhẹ nhàng, hãy đặt một liên kết tượng trưng my_python trong một thư mục thuộc đường dẫn, rồi viết shebang là /usr/bin/env my_python
      Nếu muốn cách tiếp cận bài bản hơn, hãy xem công cụ update-alternatives. Nó cung cấp kiểu trừu tượng này một cách tổng quát hơn: https://linuxconfig.org/how-to-set-default-programs-using-up...
    • Cách giải quyết thì những người khác đã nói rồi, nhưng tôi muốn bổ sung một lý do vì sao lại như vậy
      Trên Linux, thật ra là trên hầu hết các nền tảng ngoài Windows, ý nghĩa của phần mở rộng file yếu hơn nhiều. Bất kỳ loại file thực thi nào cũng được xác định khả năng chạy không phải bằng phần mở rộng, mà bằng cờ như +x. Nhờ vậy, bạn có thể viết lại bằng ngôn ngữ triển khai khác mà không làm hỏng phía gọi. Phần mở rộng .py chỉ thật sự có ý nghĩa với các module được import để dùng; còn nếu là script được thực thi thì khi cần chỉ cần nhìn shebang. Script phân phối bên ngoài thường dùng #!/usr/bin/env python, còn script đi kèm gói của bản phân phối thì sẽ được ghi đè thành kiểu #!/usr/bin/python. Ngoài ra shebang không hỗ trợ nhiều đối số, nhưng GNU env hỗ trợ đối số -S để mô phỏng việc đó. Tuy nhiên vấn đề độ dài đối số vẫn còn
    • Chỉ cần bỏ .py khỏi tên file là được. Gọi nó là "hello" là hoàn toàn ổn
      Tôi không nghĩ ra nhược điểm nào đáng kể của shebang. Nếu thật sự muốn chạy bằng trình thông dịch khác thì có thể chỉ rõ như "nohtyp hello". Nếu vẫn thấy quá khó chịu, bạn có thể định nghĩa alias trong file khởi động shell. Ví dụ trong bash có thể làm alias hello="python3 /path/to/hello.py". Nếu muốn, bạn cũng có thể viết một script ngắn tự động tạo các alias như vậy cho nội dung của một thư mục chỉ định
    • Khái niệm đó đúng là có tồn tại, nhưng không nằm trong cú pháp shell. Thường đây là vấn đề ở tầng ứng dụng được giao cho desktop/GUI
      Trong script shell, thông thường ta thêm shebang và làm file có thể thực thi, tức là khai báo file thực thi ngay trong chính script. Có thể nghĩ shebang như một dạng phần mở rộng file. Nếu sau chmod +x ./malware.py./malware.py không chạy, hãy kiểm tra đường dẫn mà shebang trỏ tới. Nếu trình thông dịch có thể chạy script như một đối số thông thường, thì cũng có thể tạo hành vi tương tự bằng cách như xdg-open malware.py. Nó sẽ giống như nhấp đúp trong trình quản lý file mặc định. Khi dùng Linux làm hệ điều hành desktop chính, tôi từng đặt alias xop, nhưng chỉ dùng cho các file dữ liệu như ảnh hoặc tài liệu vốn đã có hành vi mặc định phù hợp. Tôi không khuyến nghị đặt chương trình mặc định của script có thể thực thi thành trình thông dịch. Theo mặc định, có thể bạn muốn mở script trong trình soạn thảo thay vì chạy nó. Tôi nghĩ xdg-open là công cụ phía Gnome, nhưng không có nghĩa là không dùng được trên desktop khác; tôi cũng đã dùng nó trên Xubuntu. Nếu thật sự muốn tất cả file Python mặc định chạy trong cả ngữ cảnh GUI, bạn có thể đặt mặc định như vậy, nhưng man xdg-open có thể hữu ích. Nhắc lại, đây không phải lời khuyên hay
    • Dù không đạt trực tiếp mục tiêu, shebang chỉ hard-code một nửa. Cách “đúng” để dùng shebang, dù có vài điểm cần chú ý như trong https://unix.stackexchange.com/a/29620, là #!/usr/bin/env python
      Như vậy python đầu tiên tìm thấy trong đường dẫn sẽ được chạy. Nếu sau này muốn chạy bằng /usr/bin/nohtyp thay vì /usr/bin/python, bạn có thể tạo một liên kết tượng trưng tên python trỏ tới /usr/bin/nohtyp trong một thư mục được tìm kiếm trước /usr/bin. Ví dụ thêm ~/myCommandPreferences vào đầu $PATH
  • Một cách khác để tránh xung đột $PATH là đặt tên file thực thi thật dài, rất ít khả năng file thực thi khác dùng tới, rồi tạo alias ngắn trong bashrc
    Alias không ảnh hưởng tới các file thực thi được gọi bên trong script, còn trong script của tôi thì tôi vẫn có thể tiếp tục tham chiếu bằng tên dài. Nhược điểm là không có được cùng mức tiện dụng của tự động hoàn thành bằng phím Tab, mà phần đó thì thật sự rất hay. Ngoài ra, với các script phải được source chứ không chạy thành tiến trình con, như script kích hoạt venv của Python, vẫn có thể xảy ra xung đột, nhưng những trường hợp như vậy hiếm

    • Trong zsh thì phần tự động hoàn thành đó cũng làm được
  • Cách bắt đầu bằng dấu phẩy cũng là một kỹ thuật phổ biến trong cộng đồng trình mở rộng văn bản/thay thế văn bản

    • Đúng vậy. Hầu hết alias vim của tôi cũng bắt đầu bằng ,
  • Gần đây khi xem ~/.local/bin/, tôi phát hiện có hàng chục file thực thi mà tôi không nhớ mình đã đặt vào
    Phần lớn liên quan đến pyside, nhưng cũng có các script khác. Tôi phải mở từng cái để nhớ script nào là do mình tự viết và cái nào là của người khác. Nếu tên script của tôi bắt đầu bằng dấu phẩy thì việc đó đã nhanh hơn nhiều, và cũng giúp tôi nhớ ra vì sao mình tạo từng script trước khi mở chúng

    • Thông thường ~/.local/bin/ dành cho các script đã được cài đặt, còn những thứ tự viết cục bộ thì đặt trong ~/bin/
  • Xin phép không dùng. Chỉ cần đặt bin cá nhân ở đầu $PATH, và khi tham chiếu đến chương trình bị che khuất thì dùng /usr/bin hoặc /bin là được
    Có thể liệt kê danh sách công cụ đã cá nhân hóa bằng ~/bin/[Tab]

    • Tôi không muốn dùng cùng tên trong khi trỏ các tiện ích hệ thống sang bản của mình, nên không hiểu vì sao lại phải tiếp tục nhớ dấu phẩy
      Nếu tôi không thích grep của hệ thống, ví dụ grep trên Solaris, và muốn dùng GNU grep mà tôi ưa thích, thì sao không cứ để nó là grep?
  • Nhờ biết ý tưởng này 5 năm trước mà tôi đã sắp xếp được bộ mẹo shell của mình có trật tự hơn. Gộp alias và ~/bin lại, tôi có hơn 50 lệnh dấu phẩy, và đời sống shell trở nên trơn tru hơn nhiều so với tình trạng lộn xộn trước đây

  • Năm 2020 cũng từng có thảo luận: https://news.ycombinator.com/item?id=22778988 (90 bình luận)

 
kayws426 2024-06-24

Dùng '_' thì sao?