命令列工具
edaywalid/undo avatar
edaywalid/undo

undo:給 Linux shell 的檔案系統改動加上指令級回退

專案速覽:撤銷最後一個 shell 指令對檔案系統所做的操作。鉤。 shell 鉤子(zsh、bash、fish)圍繞您執行的每個命令配備一個小型 LD_PRELOAD 庫 libundo.so。

396 個 Star13 個 ForkGoMIT

秒懂

它是什麼?
undo 通過 zsh、bash 或 fish 钩子和 libundo.so 記錄每条指令的檔案變化,可還原 rm、mv、截断、chmod 與腳本創建的內容。 聚焦本專案的實際功能、技術入口、部署條件、資料流、版本變化與授權邊界,並依官方 README 所列能力判斷適用工作情境和不適合的替代用途。
適合誰用?
適合 Linux glibc 主机上经常執行 shell 清理、構建或批處理指令的開發者;不適合替代备份、快照或 macOS 上的通用恢複工具。先執行 undo doctor,再在临時目錄執行 touch、rm、mv、截断和 chmod,檢查 undo、undo diff、undo redo 的結果,並确认自己的程序沒有落入静態二進製、mmap 或 setuid 等不可捕获边界。
可以商用嗎?
可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫最近一次提交在 35 天前。
用什麼語言寫的?
主要是 Go(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

edaywalid-undo-deep-analysis|它回退一条指令而不是一段時間

edaywalid-undo-deep-analysis|它回退一条指令而不是一段時間 的專案脈絡:undo 解决的是 shell 沒有撤销功能的问題,目標是恢複最近一条改變檔案系統的指令。README 特別把它和 btrfs/zfs 快照区分開:快照按時間点回滚整個树,undo 按指令只回滚那一条指令碰過的內容,不需要 root。它覆盖 rm、rm -rf、覆盖移動、重定向截断、誤用 chmod -R,以及失控腳本創建的檔案和目錄。

edaywalid-undo-deep-analysis|它回退一条指令而不是一段時間:撤销後可以執行 undo redo 重新應用,因而一個会话可以在撤销和已應用之間切换。這個特性適合審查誤操作,但不表示資料永远存在。README 明确提醒它是安全網而不是备份;重要檔案仍應有独立备份、快照或版本控製。

edaywalid-undo-deep-analysis|shell 钩子如何形成会话日志

edaywalid-undo-deep-analysis|shell 钩子如何形成会话日志 的專案脈絡:工具沒有常驻守護進程,zsh、bash 和 fish 钩子会在指令周围临時启用 LD_PRELOAD 庫 libundo.so。庫在指令執行期間拦截 unlink、rename、带寫標志的 open、rmdir、mkdir、chmod 等破坏性 libc 调用,在调用真正發生前保存受影响檔案,並把一行變更追加到該指令的 journal。指令結束後才形成可供 undo 操作的会话。

edaywalid-undo-deep-analysis|shell 钩子如何形成会话日志:刪除內容通過 hardlink 保存,所以刪除數 GB 的目錄不会立刻複製同樣大小的資料。重命名、截断、創建目錄和權限變化则按日志逆序重放:檔案重新链接、名稱移回、截断檔案换回备份、意外創建的內容移除、目錄按原始模式重建。實現依赖動態链接與调用路径,不能把拦截范围扩大解释為所有檔案寫入。

edaywalid-undo-deep-analysis|会话目錄是可檢查的普通檔案

edaywalid-undo-deep-analysis|会话目錄是可檢查的普通檔案 的專案脈絡:預設存储在 ~/.local/share/undo/sessions/,目錄權限為 0700。每個会话含 cmd、journal、pid、done、budget 和 data/:cmd 保存指令行,journal 記錄每次變化,pid 與 done 用於避免触碰仍在執行的指令,budget 記錄共享存储额度,data/ 保存硬链接或备份。文本格式讓操作者可以在使用前查看記錄。

edaywalid-undo-deep-analysis|会话目錄是可檢查的普通檔案:README 預設保留最近 30 個会话,总預算為 1 GiB,两個值都可設定;最新会话即使独自超過預算也会保留,因為它是預設撤销目標。原地覆盖檔案需要複製旧內容,預設上限由 UNDO_MAX_BYTES 控製,基線記載預設值為 256 MiB。undo purge 会清空存储,執行前應确认當前是否仍需 undo 最近一次指令。

edaywalid-undo-deep-analysis|指令集與一条重要 shell 陷阱

edaywalid-undo-deep-analysis|指令集與一条重要 shell 陷阱 的專案脈絡:單独輸入 undo 会撤销最近一次改變檔案的指令。undo -i 可選擇会话和条目,undo list 與 undo show 用於查看記錄,undo diff 显示內容差异,undo apply <id> 操作指定会话,undo redo [id] 重做,undo run -- cmd 為沒有钩子的場景武装一条指令。doctor 会真實刪除並恢複 canary 檔案,用於檢查安裝链路。

edaywalid-undo-deep-analysis|指令集與一条重要 shell 陷阱:README 特別警告不要把 undo 與待撤销指令用 && 串起來。shell 会把整行视為一条指令,undo 可能在包含它自己的会话中執行,而前一項尚未結束。正确做法是先執行 rm 或腳本,再在下一行單独執行 undo;CI 或腳本则使用 undo run -- ./sketchy-cleanup.sh,並檢查返回码與会话 ID。

edaywalid-undo-deep-analysis|它明确看不到哪些寫入

edaywalid-undo-deep-analysis|它明确看不到哪些寫入 的專案脈絡:LD_PRELOAD 只能影响動態链接程序通過 libc 發出的调用。README 列出静態二進製、直接系統调用、sudo 和 setuid 程序、指令開始前已经打開的檔案描述符、mmap 寫入,以及 chown 等其他元資料變化可能不可捕获。钩子 shell 外執行的內容同樣不可见,除非通過 undo run 启動。chmod 與相應的 ftruncate 则在文檔列出的覆盖范围內。

edaywalid-undo-deep-analysis|它明确看不到哪些寫入:這組限製决定了它不能代替备份,也不能保證撤回任意構建工具、容器或特權程序的結果。測試自己的工具時,應分別執行動態程序、静態程序、sudo 指令、重命名、重定向和 mmap 寫入,查看 journal 是否出現預期条目。若檔案已经被覆盖而备份超過預算,撤销能力也会受 UNDO_MAX_BYTES 影响。

edaywalid-undo-deep-analysis|平台、安裝與環境變量

edaywalid-undo-deep-analysis|平台、安裝與環境變量 的專案脈絡:一行安裝腳本是 curl -fsSL https://undo.edaywalid.com/install.sh | sh,預設安裝到 ~/.local,並询问是否修改 shell rc;非交互環境不会自行改檔案,可用 UNDO_MODIFY_RC=1 或 UNDO_NO_MODIFY_RC=1 明确回答。README 還列出 Homebrew、Debian/Ubuntu、Fedora/openSUSE、Arch、Nix 和 make install。钩子支援 zsh、bash 5 以上和 fish 3.4 以上。

edaywalid-undo-deep-analysis|平台、安裝與環境變量:平台要求是 Linux amd64 或 arm64、glibc 2.6 以上,WSL2 在支援說明中;Alpine/musl 需要源码構建,macOS 因 SIP 阻止庫注入而不支援,Snap 與 Flatpak 不在支援范围。設定變量包括 UNDO_KEEP、UNDO_MAX_STORE、UNDO_MAX_BYTES、UNDO_DATA_DIR 和 UNDO_IGNORE,應在加載钩子前設置。專案采用 MIT 許可。

edaywalid-undo-deep-analysis|把 doctor 結果當作采用門槛

edaywalid-undo-deep-analysis|把 doctor 結果當作采用門槛 的專案脈絡:undo 適合 Linux 開發机、構建机和需要降低 shell 誤刪風險的個人工作流;它不適合被部署成全系統恢複服務,也不適合承担备份、合规留存或安全刪除需求。刪除只被暂存,若要 secure deletion,README 另有专門說明,不能把 undo 的硬链接存储當作加密保险箱。

edaywalid-undo-deep-analysis|把 doctor 結果當作采用門槛:安裝後先執行 undo doctor,确认 canary 檔案能刪能還原。再在隔离目錄依次執行 touch x、rm x、undo,測試 undo diff 和 undo redo;對一個目錄執行 mv、重定向截断和 chmod 後檢查恢複的名稱、內容與模式。最後用目標構建工具執行 undo run,審閱 journal 和存储额度。只有測試結果覆盖自己的指令類型,才可把它加入日常 shell。

edaywalid-undo-deep-analysis|用边界程序驗證捕获范围

edaywalid-undo-deep-analysis|用边界程序驗證捕获范围 的專案脈絡:在临時目錄執行 undo doctor 後,分別測試 rm、mv、重定向截断、chmod 和腳本創建目錄,並用 undo show、undo diff 與 undo redo 檢查結果。再用静態二進製、sudo 指令和 mmap 寫入做對照,确认哪些變化沒有進入 journal。查看 ~/.local/share/undo/sessions/ 的 budget 和 data,再按 UNDO_MAX_BYTES、UNDO_DATA_DIR 與 UNDO_IGNORE 的實際值评估磁盘占用。對覆盖寫入的大檔案還要观察备份是否触及额度、undo 是否保留最新会话,以及硬链接刪除後磁盘空間何時释放。用 journal 的每一行對應實際變化,确认撤销顺序不会覆盖指令之後產生的新內容。對一個被腳本連续改名、截断和刪除的目錄,檢查 journal 的逆序重放是否保留指令之後的新檔案。平台測試還要确认 macOS 的 SIP、Alpine 的 musl 和 WSL2 的 glibc 差异,分別决定使用 hook、undo run 或独立备份。並記錄每条 journal 變化與撤销後的檔案状態,确认沒有把新檔案誤刪。並核對最新会话在預算边界下仍可被 undo 找到。並核對最新会话在預算边界下仍可被 undo 找到。

編輯結論

適合 Linux glibc 主机上经常執行 shell 清理、構建或批處理指令的開發者;不適合替代备份、快照或 macOS 上的通用恢複工具。先執行 undo doctor,再在临時目錄執行 touch、rm、mv、截断和 chmod,檢查 undo、undo diff、undo redo 的結果,並确认自己的程序沒有落入静態二進製、mmap 或 setuid 等不可捕获边界。測試报告還應標明 shell 類型、glibc 版本、CPU 架構和钩子檔案路径。對預設最近 30 個会话與 1 GiB 总預算進行寫入压力測試,确认 UNDO_KEEP、UNDO_MAX_STORE 和 UNDO_MAX_BYTES 的變化;執行 undo purge 前保存 session 目錄清單,並确认最新会话在超預算時仍然存在。

官方來源

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
社群筆記

社群筆記