Skip to main content

Command Palette

Search for a command to run...

Build Your Own Shell: Mình tìm lại cảm giác code giữa bão AI

Updated
7 min read
Build Your Own Shell: Mình tìm lại cảm giác code giữa bão AI

Dạo gần đây, lướt FB, Linked in, mình thấy bội thực vì content AI. Đâu đâu cũng thấy “mình mới vibe code 100% app này”, “antigravity làm cho mình từ A-Z”, “dev chuẩn bị ra chuồng gà”,…

Thú thật,mình cũng sử dụng AI rất nhiều, hằng ngày. Nó nhanh, nó tiện, nhưng nó khiến mình thấy... chán. Feature ship nhanh, UI đẹp nhưng không còn cảm thấy “đã cái nư” khi hoàn thành.

Cuối tuần vừa rồi, thay vì chạm cỏ, mình quyết tâm tìm lại cảm giác "chạm code”.

Tiêu chí đơn giản:
- Phải ngắndễ (mấy project vô thưởng vô phạt tốt nhất làm trong 1,2 ngày là đẹp, phức tạp quá là bỏ dở ngay. Kinh nghiệm sau khi mình đắp chiếu mấy con pet project 🪦)
- Gõ code thuần chay, tự tư duy, chỉ tra cú pháp (nói không với AI )
- Đủ thú vị nhưng phải "low-level" một chút để học được gì đó: no CRUD, task trên công ty quá đủ rồi 🤣

Rồi mình tìm được CodeCrafters.io. Họ cho phép build lại các công cụ kinh điển (Redis, Git, Docker...) và tháng này họ đang miễn phí khóa Build Your Own Shell.Chân ái đây rồi. Quất!

Đây là những gì mình học được sau vài tiếng "vật lộn" với Python để tạo ra một chiếc Shell của riêng mình.

1. Shell thực chất là gì?

Đừng để cái terminal đen ngòm đánh lừa. Chả có gì cao siêu cả.

Làm theo hướng dẫn của app, mình mới thấy. Về bản chất, Shell cũng chỉ là một chương trình bình thường. Nó chạy một vòng lặp vô tận (REPL - Read-Eval-Print-Loop) để chờ đợi và xử lý input từ người dùng.

Cấu trúc cốt lõi chỉ đơn giản thế này:

while True:
    sys.stdout.write("\( ") # Dấu \) huyền thoại của shell, trên window sẽ là PS - Power Shell
    user_input = input() # Đọc input
    parse(user_input): # Kiểm tra input, xem user muốn làm gì
    execute() # Thực thi
    print() # in output ra màn hình

Ví dụ cách shell hoạt động khi nhận input: echo “hello world”


2. Bài toán tìm kiếm: Lệnh nằm ở đâu?

Nếu bạn giống mình, là 1 web developer, thì khoảnh khắc wow đầu tiên của mình là chính là:

Mở terminal → gõ “code .” → VS Code hiện lên 😮→ hacker 😎

Nhưng mình tin là ít nhất trong đời dev, bạn cũng từng vò đầu bứt tai với cái màn hình này:

Python is not recognized as an internal or external command

Vậy có bao giờ bạn thắc mắc: “làm thế méo nào cái màn hình đen này nó hiểu được lệnh đó?”

Câu trả lời nằm ở một biến môi trường mang tên$PATH . Biến chứa list các folder mà Shell sẽ ưu tiên tìm kiếm file có thể execute được mỗi khi bạn gõ một lệnh bất kỳ.

ở window file execute là đuôi “.exe”, nôm na là double click thì chạy được. Ví dụ python.exe

Ví dụ, bạn gõ python —version , nếu $PATH không chứa folder dẫn tới python.exe, Shell sẽ chịu chết và trả về dòng lỗi "not recognized".

CodeCrafters.io bắt mình tự code chay logic tìm kiếm này. Từ đó mình mới hiểu từ gốc rễ tại sao có những lệnh chỉ cần gõ tên là chạy, còn có những lệnh lại không.

Muốn tái hiện lại màn hình “python not recognized” phía trên không? vào Environment Variables → Path → Delete bất kỳ lệnh nào bạn muốn rồi gõ lại vào terminal xem 😅: nodejs, vscode, jdk,….

Lý thuyết là thế thôi, tới lúc code cái logic tìm $PATH này, mình mới va phải những trải nghiệm "đau thương" !

Window vs Linux: Cuộc chiến Path Separator

Mình thì code trên window nhưng ông CodeCrafters.io lại chạy test trên? Linux.
App thì báo input để chạy test là /usr/bin/grep.
Nhưng window làm méo gì có folder này mà test ở local.
Mình lại phải vào biến $PATH copy folder python ra test: D:\apps\Scoop\apps\python\current (mình cài bằng Scoop)

Code xong mỗi bài, CodeCrafters.io sẽ chạy test trên môi trường Linux

Khổ nỗi tới khâu cộng chuỗi để tìm full path cho file .exe: D:\apps\Scoop\apps\python\current + “\python.exe”.

Test local thì ngon ăn, nhưng subtmit và chạy test trên CodeCrafters thì fail. 🤡

Ra là ông Window thì dùng \, ông Linux thì dùng / . Hard code string thì đúng ăn hành luôn.
Bảo sao chạy test mãi ko qua.

Đọc comment thì thấy các pros bảo phải xử lý đặc biệt bằng thư viện os :
- os.pathsep : tự nhận path separator theo môi trường, khỏi lăn tăn \ hay /
- os.path.join: uỷ thác khâu join cho thư viện, nhàn.

Một bài học nhỏ thôi, nhưng nhắc nhở mình về tính tương thích của hệ thống.
Và đấy mới là thử thách dạo đầu thôi.

Cú lừa mang tên code.cmd

Vẫn là trong lúc code cái tìm $PATH. Thử lệnh python —version ngon rồi, mình hào hứng test thêm lệnh code.

Hí hửng tưởng mở được vscode trong cái shell tự chế thì ngon hơn HDPE luôn. Nhưng thứ nhận lại chỉ có Command not found 🤡

Hoá ra,trên Windows, khi tìm file thực thi, không phải lúc nào nó cũng là .exe.
Kiểm tra kỹ trong D:\apps\Microsoft VS Code\bin, mình mới thấy file thực thi thực chất tên code.cmd. Ok, giờ mới để ý có đuôi .cmd nữa.

Từ đó, mình rút ra logic: Khi tìm kiếm một lệnh, Shell phải check đồng thời cả bộ extension: [.exe, .bat, .cmd, ...]. List này dài lắm, mình ghi mấy cái phổ biến thôi.

Code trên Window thì đau đầu vậy, còn trên Linux thì đơn giản hơn. File có 3 quyền cơ bản: read, write, execute. Tương ứng rwx.

Muốn biết file nào chạy được thì chỉ cần gõ ls -la xem có quyền thực thi ( có chữ X) không:


3. "Wow Moment": Khi cái app biến thành Shell thật

Sau khi xong tính năng Execute, mình đọc được 1 comment ở dưới: “ê, sau bài này, chúng mày thử commit bằng chính cái Shell này đi, vì git nằm trong PATH mà. Đã lắm”

Ê hay nha, test thử git versiongit status. Ngon! dính liền

Terminal gốc của mình là phần màu mè, còn sau khi chạy file main là lên hình con Shell $ rồi đó.

Đoạn này là phê nhất luôn. Mình chắc chắn là bạn cũng từng trải nghiệm cảm giác này: fix đc con bug khó, chạy đc feature lần đầu,...

Chứ giờ có AI rồi, có khi cảm giác này lại hơi xa xỉ😁.


4. Kết luận

Dành ra một cuối tuần để build "đồ cổ" như Shell không hề lãng phí. Nó giúp mình củng cố lại kiến thức về Process, PATH, và cách OS vận hành bên dưới.

Nếu bạn là real dev cũng đang thấy "ngán" dùng AI, mất lửa với code dần, hãy thử dành 1 buổi với CodeCrafters để tìm lại cảm giác nhé.

Repo của dự án: https://github.com/vanbeonhv/my-own-shell