Codex CLI để lại daemon chạy ngầm: bốn coding agent được kiểm tra
Bốn coding CLI để lại gì sau khi đóng terminal: daemon và updater của Codex, orphan của Gemini CLI, disk, kết nối, cách tắt và script kiểm tra.
✓ Đã duyệt độc lập · cập nhật 26/10/2026 · 11 min
1. Đóng terminal rồi, agent đã thật sự tắt chưa?
BigIron AI mở đầu bằng một câu hỏi: bạn đóng terminal, và coding agent của bạn biến mất. Hay là chưa? Theo BigIron AI (video đăng ngày 20/10/2026), kể từ version 0.157, Codex khởi động một background server ở mỗi lần mở chế độ interactive, và server này tiếp tục chạy sau khi mọi cửa sổ Codex đã đóng.

Bài guide của Big Iron đã kiểm tra chuyện đó, và kiểm tra luôn ba terminal agent khác, trên một máy ảo Debian mới tinh. BigIron AI đi qua từng tool: nó còn để lại thứ gì đang chạy, nó ghi gì xuống disk, và nó gọi về đâu (phoned home). Mọi con số dưới đây là số đo trên máy ảo test được mô tả trong video đăng ngày 20/10/2026.
2. Bản ngắn gọn: bốn tool để lại gì
Bản ngắn gọn, theo số đo trong video đăng ngày 20/10/2026: Codex để lại hai process đang chạy, khoảng 370 megabyte, cùng một updater lên mạng năm phút sau khi khởi động. Gemini CLI cũng để lại hai process, khoảng 400 megabyte, và theo BigIron AI thì trường hợp này trông giống một bug.

Claude Code và OpenCode thì thoát trong vòng 15 giây ở mọi lần chạy, và không gửi gì ra ngoài sau đó (số đo trong video đăng ngày 20/10/2026). Ngoài ra, không tool nào trong bốn tool cài một systemd unit, một cron job hay một mục auto-start, nên một lần reboot sẽ chấm dứt tất cả.
3. Vì sao đáng để ý trên homelab: uptime và máy dùng chung
Vậy tại sao phải bận tâm trên một homelab? Câu trả lời của BigIron AI (video đăng ngày 20/10/2026) là uptime. Một dev VM hay một jump host có thể chạy hàng tháng trời giữa hai lần reboot. Mỗi lần mở Codex ở chế độ interactive khi daemon chưa chạy sẽ khởi động một daemon, và mỗi session Gemini bị rớt sẽ để lại một cặp process.
Trên một máy dùng chung, theo số đo trong video đăng ngày 20/10/2026, mỗi user có daemon riêng của mình và bản copy riêng 432 megabyte của package Codex. Slide đi kèm ghi "432 MiB, a Codex package copy per user", kèm dòng "plus a daemon per user, on a shared box".
4. Bài test được chạy thế nào
Trước hết là cách chạy test, vì theo BigIron AI, chính các chi tiết quyết định kết quả có ý nghĩa gì. Máy test là một máy ảo Debian 13 dùng xong bỏ (throwaway) trên Proxmox, với bốn virtual CPU và sáu gigabyte RAM. Mỗi tool được cài theo cách vendor của nó khuyến nghị: Codex 0.162.1 và Gemini 0.63 qua npm; Claude Code 2.1.296 và opencode 1.19 qua install script của chúng. Mỗi tool có một Linux user mới riêng (thiết lập test trong video đăng ngày 20/10/2026).
Về model, Ollama chạy ngay trên máy ảo, serve model qwen3:1.7b (slide ghi Ollama 0.40.3). Gemini không nói chuyện được với Ollama, nên nó được cấp một API key cố tình không hợp lệ; slide ghi "Gemini CLI: an invalid key, prompt fails" (thiết lập test trong video đăng ngày 20/10/2026).
Quy trình như sau: khởi động agent bên trong tmux, chờ 25 giây, gõ một prompt, chờ 90 giây, rồi kill tmux server. Thao tác đó đóng terminal, y như khi bạn đóng cửa sổ hoặc khi một session SSH bị rớt: kernel gửi tín hiệu hang-up (SIGHUP). Sau đó kiểm tra process ở giây thứ 15 và mỗi phút một lần, tối đa 10 phút. Mọi kết nối outbound được log theo từng user bằng một firewall rule, và home directory được diff (quy trình trong video đăng ngày 20/10/2026).

tmux new -d -s s 'cd ~/proj && codex', chờ 25 giây, gửi một prompt "Reply with the single word OK.", chờ 90 giây, rồi tmux kill-server để đóng pty bằng SIGHUP; sau đó kiểm tra process ở +15 giây rồi mỗi phút, nftables log kết nối outbound theo UID, cuối cùng diff home directory (video đăng ngày 20/10/2026).BigIron AI nêu hai lưu ý thẳng thắn (honest caveats) từ bài guide. Thứ nhất, một model nhỏ chạy chậm trên bốn core, nên ở vài lần chạy terminal bị đóng khi model vẫn đang trả lời; theo BigIron AI, đó là một bài test khó hơn. Thứ hai, một lỗi của dàn test ở giai đoạn đầu khiến session Codex và Claude Code đầu tiên không nhận được câu trả lời nào, nên cả hai được chạy lại với một back-end hoạt động bình thường. Những gì còn sót lại thì giống hệt (số đo trong video đăng ngày 20/10/2026).
5. Codex: daemon là mặc định, không phải bug
Codex được nói tới đầu tiên, vì theo BigIron AI (video đăng ngày 20/10/2026), hành vi của nó không phải bug. Đó là mặc định, và lý do OpenAI đưa ra là nó cho phép nhiều client, bao gồm desktop app và remote control, dùng chung một back-end.
Trong vòng ba giây sau khi mở, Codex sinh ra thêm hai process (số đo trong video đăng ngày 20/10/2026). Một là app server, khởi động dưới dạng managed daemon. Hai là một updater riêng tên là pid-update-loop. Cả hai chạy từ một bản copy riêng của binary, nằm trong thư mục packages bên trong .codex ở home directory. Mỗi process không có terminal, và mỗi process tự làm leader của session riêng.

node /usr/local/bin/codex đi xuống binary trong vendor, rồi hai process chạy từ ~/.codex/packages/.../bin/codex: app-server --managed-daemon và app-server daemon pid-update-loop; dòng chú thích ghi hai process cuối không có terminal và mỗi cái có session riêng (video đăng ngày 20/10/2026).15 giây sau khi terminal đóng, các process do npm cài đã biến mất, còn hai process này đã được PID 1 nhận nuôi (adopted). Mười phút sau, cả hai vẫn đang chạy, với 257 MB và 116 MB resident; slide ghi "~370 MB still resident after 10 minutes" (số đo trong video đăng ngày 20/10/2026). Không có gì trong cron, systemd user unit hay autostart trỏ tới chúng, và user đó không bật lingering. Vậy nên một lần reboot sẽ kết thúc chúng. Còn trước lúc đó, chúng ở lại.
6. Codex giữ những gì, và gọi ra ngoài lúc nào
Chúng giữ mở những gì? Theo số đo trong video đăng ngày 20/10/2026, app server lắng nghe trên một Unix socket dưới /tmp; slide ghi /tmp/codex-daemon-UID/hash. Updater lắng nghe trên socket riêng của nó bên trong thư mục .codex (slide ghi ~/.codex/.../daemon-updater.sock). Và trong lúc chính session Codex interactive còn mở, nó còn lắng nghe trên một TCP port ngẫu nhiên ở địa chỉ loopback. Chỉ loopback thôi, nhưng theo BigIron AI thì đáng biết trên một máy nhiều user.
Tiếp theo là network trace, theo số đo trong video đăng ngày 20/10/2026. Lúc khởi động có kết nối tới GitHub, chatgpt.com và npm registry. Thêm một kết nối ở giây thứ 62. Rồi tới giây thứ 303, khi terminal đã đóng hơn ba phút, có kết nối tới chatgpt.com và releases.openai.com. Lần chạy lại khớp tới từng giây.

INITIAL_UPDATE_DELAY = 5 min và DEFAULT_UPDATE_INTERVAL_MINUTES = 60 (số đo trong video đăng ngày 20/10/2026).Theo BigIron AI (video đăng ngày 20/10/2026), mốc thời gian đó nằm sẵn trong source code: một khoảng trễ update ban đầu 5 phút, rồi cứ 60 phút kiểm tra một lần, chừng nào máy còn chạy. Khi tìm thấy một release, nó tải release đó về home directory của bạn và khởi động lại back-end. Theo BigIron AI, chuyện tự update này quan trọng nếu bạn pin version: sau khi daemon tự update, back-end đang chạy các session của bạn là thứ nó đã tải về, không phải thứ npm đã cài.
7. 541 MB trên disk, và khi nào Codex bỏ qua daemon
Còn disk. Home directory của user test đi từ 4,6 kilobyte lên 541 megabyte sau một session, phần lớn là một bản copy đầy đủ của package và một bản clone plugin (số đo trong video đăng ngày 20/10/2026). Slide "541 MB, Codex home dir, after one session" ghi rõ: bản copy package 432 MiB cộng bản clone plugin 103 MB.
Khi nào Codex bỏ qua daemon? Theo BigIron AI (video đăng ngày 20/10/2026), source code liệt kê các điều kiện: chọn một profile, một override, hoặc đặt một exec server URL trong biến môi trường. Bài guide (đọc ngày 26/10/2026) ghi cụ thể đó là --profile, override config bằng -c và biến CODEX_EXEC_SERVER_URL.
Bài guide đã kiểm tra các kiểu khởi động sau, theo kết quả trong video đăng ngày 20/10/2026. Một lần khởi động interactive bình thường thì khởi động daemon. Cờ --oss, cờ --no-daemon, chế độ non-interactive exec, và việc tắt feature flag thì đều không. Danh sách features cũng cho thấy Daemon Auto Start ở trạng thái stable, và bật theo mặc định.

codex là yes; codex --oss, codex --no-daemon, codex exec "..." và codex sau khi features disable đều là no; lệnh codex features list in ra daemon_auto_start stable true (kết quả trên Codex 0.162.1, video đăng ngày 20/10/2026).8. Dừng daemon: updater vẫn ở lại
Dừng nó thì có một cái bẫy (a catch), được báo lần đầu trong issue upstream và được bài guide tái hiện y hệt (theo video đăng ngày 20/10/2026). Lệnh daemon stop chờ 60 giây, đúng bằng thời gian shutdown grace mặc định, rồi ép server tắt. Ở một lần chạy sau, khi không có turn nào đang dở, lệnh trả về trong khoảng một giây.

codex app-server daemon stop in ra shutdown_requested, rồi shutdown_forced 60 giây sau, rồi "status":"stopped"; 70 giây sau, ps -u cx2 -o pid,etimes,args vẫn thấy .../codex app-server daemon pid-update-loop (số đo trong video đăng ngày 20/10/2026).Nhưng 70 giây sau lệnh stop, updater vẫn đang chạy (số đo trong video đăng ngày 20/10/2026). Nó phải bị kill riêng.
9. Gemini CLI: orphan không chịu hang up
Gemini CLI thì khác. Theo BigIron AI (video đăng ngày 20/10/2026), không có gì ở đây là do thiết kế. Nó đơn giản là không hang up. Gemini chạy thành hai process node: một parent nhỏ, và một child được relaunch với heap lớn hơn.
Khi terminal đóng, cả hai tiếp tục chạy. Mười phút sau chúng vẫn còn đó, tổng cộng khoảng 400 megabyte, ở trạng thái idle, với hai giây CPU time (số đo trong video đăng ngày 20/10/2026). Input và output của chúng trỏ tới một terminal đã bị xoá. Và process status cho thấy cả hai đều bắt (catch) tín hiệu hang-up, thay vì làm hành động mặc định là thoát.

node .../gemini) có PPID 1, process con 9158 chạy với --max-old-space-size=2965, cột TT là ?; hai dòng chú thích ghi stdin/out/err trỏ tới /dev/pts/0 (deleted) và cả hai bắt SIGHUP thay vì thoát (số đo trong video đăng ngày 20/10/2026).Theo số đo trong video đăng ngày 20/10/2026, mọi lần chạy Gemini không có bản sửa (fix) mô tả ở phần sau đều tái hiện được lỗi này, kể cả một lần qua một session SSH thật, không gõ prompt nào, và client bị kill. Cả hai process vẫn còn đó 24 phút sau. Slide "Reproduced Every Time" tóm lại: mọi lần chạy không có fix, kể cả SSH; vẫn chạy 24 phút sau qua SSH; issue upstream gemini-cli #25590 vẫn mở; thói quen an toàn lúc này là thoát bằng /quit.
Report upstream gần nhất là Gemini CLI issue 25590, mà video (đăng ngày 20/10/2026) nói là vẫn đang mở: wrapper relaunch không chuyển tiếp các tín hiệu termination xuống process con. Khi đọc ngày 26/10/2026, trang issue google-gemini/gemini-cli#25590 có tiêu đề "relaunchAppInChildProcess does not forward signals to child, orphaning it when parent is killed" và ở trạng thái closed. Lời khuyên trong video: cho tới khi được sửa, hãy thoát từ bên trong bằng /quit.
10. Claude Code và opencode: thoát sạch, nhưng vẫn có giá
Hai tool còn lại thì cư xử đúng mực. Đây là cái giá chúng vẫn tốn, theo số đo trong video đăng ngày 20/10/2026.
Claude Code chạy thành một process duy nhất, khoảng 265 tới 340 megabyte resident. 15 giây sau khi terminal đóng, không còn gì sót lại ở cả ba lần chạy, kể cả một lần đóng giữa chừng một turn. Lúc khởi động, nó liên lạc với Anthropic API và server tải về của nó (slide ghi api.anthropic.com và downloads.claude.ai), ngay cả khi model chạy trên Ollama local, và hoàn toàn không gửi gì sau khi thoát. Slide "Claude Code 2.1.296" còn ghi disk cho mỗi session là 15 đến 19 MB, chủ yếu là plugin (số đo trong video đăng ngày 20/10/2026).
Theo BigIron AI (video đăng ngày 20/10/2026), các release cũ hơn từng có bug orphan trên issue tracker của chính Claude Code, nhưng ở version này, bài guide không tái hiện được.
OpenCode nặng nhất khi đang chạy, khoảng 800 megabyte cho một process, và sạch nhất sau đó: không còn gì sau 15 giây, và không có kết nối nào (số đo trong video đăng ngày 20/10/2026). Phần nó để lại nằm trên disk. Bản cài đặt ghi 178 megabyte vào home directory, và một session thêm 214 megabyte nữa: một npm cache, một provider package được cài ở lần dùng đầu tiên, các runtime dependency và model catalog.

Theo BigIron AI (video đăng ngày 20/10/2026), trên một máy không có internet, hãy tính trước cho lần khởi động đầu tiên đó.
11. Tắt bớt kết nối, và tắt hẳn daemon của Codex
Vậy làm sao vặn nhỏ từng tool lại? Theo BigIron AI (video đăng ngày 20/10/2026), mỗi tool có một switch được document cho việc kiểm tra update và telemetry. Bài guide khởi động ba tool lần thứ hai, có và không có switch đó, rồi đếm số kết nối outbound mới trong phút tiếp theo.
Theo số đo trong video đăng ngày 20/10/2026: Claude Code đi từ hai xuống không, với biến môi trường mà video đọc là Claude Code Disable Non-Essential Traffic đặt bằng 1 (bài guide, đọc ngày 26/10/2026, ghi tên biến là CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1). Gemini đi từ bốn xuống một, chính là prompt, với ba setting trong settings file của nó. OpenCode đi từ 3 xuống 0 với hai biến môi trường. Không setting nào trong số này thay đổi chuyện có process nào bị bỏ lại hay không.

Với daemon của Codex, switch là Daemon Auto Start (theo video đăng ngày 20/10/2026). Script của bài guide tắt nó, dừng daemon, kill updater, rồi xoá cả bản copy package lẫn state của daemon; nếu không xoá cả hai thì một lần bật lại sau này sẽ fail. Bốn lệnh cốt lõi của script codex-daemon-off.sh hiện trên màn hình:
codex features disable daemon_auto_start
codex app-server daemon stop
pkill -u "$(id -u)" \
-f '[a]pp-server daemon pid-update-loop'
rm -rf ~/.codex/packages/app-server-daemon \
~/.codex/app-server-daemonTheo số đo trong video đăng ngày 20/10/2026, script chạy trong 1,3 giây và để lại 109 megabyte trong ~/.codex. Lần khởi động tiếp theo không khởi động daemon nào.
12. Để logind dọn dẹp
Với Gemini, hay với bất cứ thứ gì khác, BigIron AI (video đăng ngày 20/10/2026) gợi ý để logind dọn dẹp. Một setting drop-in KillUserProcesses=yes khiến nó kết thúc mọi thứ mà một login session đã khởi động. Qua SSH, 20 giây sau khi ngắt kết nối, không còn process nào của Gemini, cũng không còn daemon và updater của Codex (số đo trong video đăng ngày 20/10/2026).

KillUserProcesses=yes trong một logind drop-in; qua SSH, cả hai tool biến mất 20 giây sau khi ngắt kết nối; đánh đổi là tmux và screen bị kill khi logout; nó chỉ tác động khi login session kết thúc (số đo trong video đăng ngày 20/10/2026).Cái giá phải trả, theo BigIron AI (video đăng ngày 20/10/2026): nó cũng kill các session tmux và screen khi bạn logout. Bài guide nêu hai cách tránh, một là loại trừ những user được chỉ định, hai là chạy các session dài dưới systemd manager riêng của user, nhưng không test hai cách đó. Và nó chỉ tác động khi session kết thúc.
13. Kiểm tra máy của chính bạn
Cuối cùng, kiểm tra máy của chính bạn. Theo video đăng ngày 20/10/2026, script read-only của bài guide liệt kê các process agent không có terminal, các socket chúng đang lắng nghe, các hook auto-start, và dung lượng disk mà state của agent đang dùng. Màn hình cho thấy kết quả với user Codex, 10 phút sau khi đóng.

.../codex app-server ... và .../codex ... pid-update-loop đã chạy 503 giây; một Unix socket dưới /tmp/codex-daemon-1008/; mục Autostart hooks trống; disk 540M cho ~/.codex và 432M cho ~/.codex/packages (kết quả trong video đăng ngày 20/10/2026).BigIron AI gợi ý chạy script đó từ cron hoặc từ một check monitoring (video đăng ngày 20/10/2026). Mục đầu tiên không rỗng chính là tín hiệu.
Lời kết của BigIron AI (video đăng ngày 20/10/2026): tắt daemon của Codex trên các máy dùng chung và trên bất cứ máy nào bạn SSH vào, để logind dọn các session, tính trước dung lượng disk, và thoát agent bằng lệnh quit của chính nó thay vì đóng cửa sổ.
Nguồn và liên kết 6 nguồn
- Tên gốc: Codex CLI Leaves a Daemon Running. Three Other Agents, Tested Too
- Sự kiện: YouTube
- Video gốc: https://www.youtube.com/watch?v=lYmtoHk6Hg4 youtube.com
- Kênh YouTube BigIron AI (BigIron AI): youtube.com/channel/UCHvsCXKsRnm_uRXfq72xZkA youtube.com
- Bài guide của Big Iron, nguồn của các số đo (đọc ngày 26/10/2026): What AI Coding CLIs Leave Running: Codex's Background Daemon, Audited bigiron.cc
- Issue Gemini CLI về wrapper relaunch không chuyển tiếp tín hiệu xuống process con (trạng thái closed khi đọc ngày 26/10/2026): google-gemini/gemini-cli#25590 github.com