沙箱機制

回報問題 查看來源 夜間 7.2 7.1 7.0 6.5 6.4

本文會介紹 Bazel 中的沙箱機制和沙箱功能偵錯。 環境。

「沙箱」是一種權限限制策略,可將程序 或系統中的資源至於 Bazel,這代表系統會限制 系統存取權。

Bazel 的檔案系統沙箱會在僅工作目錄中執行處理程序 包含已知的輸入內容,因此編譯器和其他工具不會看到來源 使用者不得存取這些檔案,除非他們知道這些檔案的絕對路徑。

沙箱機制無法以任何方式隱藏主機環境。程序可自由地 存取檔案系統中的所有檔案。但在支援使用者的平台上 命名空間,程序無法修改工作目錄以外的任何檔案。 這可確保建構圖表沒有隱藏依附元件 會影響版本的可重現性

具體來說,Bazel 會為每個動作建構 execroot/ 目錄。 做為動作在執行時間execroot/ 包含動作的所有輸入檔案,且可做為任何 輸出內容Bazel 接著會使用作業系統提供的技術 Linux 和 macOS 上的 sandbox-exec 容器,以便限制在 execroot/

採用沙箱機制的原因

  • 如未宣告動作沙箱,Bazel 無法得知工具是否使用未宣告的 (在該檔案的依附元件中,沒有明確列出的檔案) 動作)。當其中一個未宣告的輸入檔案變更時,Bazel 仍會 認為建構是最新版本,不會重新建立動作。這可以 進而產生錯誤的漸進式建構作業

  • 若是以不正確的方式重複使用快取項目,將會在遠端快取期間發生問題。A 罩杯 如果共用快取中有錯誤的快取項目,會影響專案的每位開發人員, 並清除整個遠端快取並非可行的解決方案。

  • 沙箱機制會模仿遠端執行的行為 (如果建構能順利運作) 也支援遠端執行藉由 遠端執行上傳所有必要檔案 (包括本機工具),您可以 相較於 2018 年, 不必在每次安裝時 試用新的編譯器,或變更現有工具。

採用的沙箱策略

利用 策略標記。使用 sandboxed 策略會讓 Bazel 從下列一種沙箱實作項目中選擇一種 偏好作業系統專屬的沙盒,而不是普通的通用沙箱。 永久工作站會在您通過測試時,在一般沙箱中執行 --worker_sandboxing 旗標。

local (又稱為 standalone) 策略並非執行任何類型的沙箱作業。 它只會執行動作的指令列,並將工作目錄設定為 工作區的執行者

processwrapper-sandbox 是不需要任何測試機制的沙箱策略 「進階」功能 - 立即適用於任何現成的 POSIX 系統,這項服務 會建立沙箱目錄,包含指向原始版本的符號連結 來源檔案,使用工作目錄集執行動作的指令列 移至這個目錄 (而非 execroot),再移動已知的輸出構件 並刪除沙箱。這樣一來, 操作,導致您誤以為 減少輸出檔案的 execroot

linux-sandbox 更進一步,奠基於 processwrapper-sandbox。與 Docker 的功能類似 Linux 命名空間 (User、掛接、PID、網路和 IPC 命名空間) 以便隔離 動作。也就是說,這麼做會將整個檔案系統設為唯讀, ,因此該動作不會意外修改 主機檔案系統這可避免錯誤測試等情況意外觸發 -rf 是您的 $HOME 目錄。或者,您也可以防止動作 存取網路linux-sandbox 會使用 PID 命名空間防止動作 偵測其他處理程序及穩定終止所有程序 (即使是 Daemon 也不例外) 延伸至結尾。

darwin-sandbox 很類似,但適用於 macOS。使用 Apple 的「sandbox-exec」工具 執行的實作效果大致與 Linux 沙箱相同

linux-sandboxdarwin-sandbox 都不適用於「巢狀」 因作業平台所提供機制的限制 有些人會將 Cloud Storage 視為檔案系統 但實際上不是由於 Docker 也會使用 Linux 命名空間來發揮容器神奇效果 無法在 Docker 容器中執行 linux-sandbox,除非您使用 docker run --privileged。在 macOS 上,您無法在 sandbox-exec 已加上沙箱的處理程序因此,在這類情況下 會自動改回使用 processwrapper-sandbox

這樣會發生建構錯誤,例如避免不小心使用 執行策略較不嚴格的執行策略 — 明確修改執行清單 Bazel 嘗試使用的策略 (例如 bazel build --spawn_strategy=worker,linux-sandbox)。

動態執行通常需要在本機執行時採用沙箱機制。如要停用, 傳遞 --experimental_local_lockfree_output 標記。動態執行,不發出任何通知 沙箱的永久工作站

採用沙箱機制的缺點

  • 沙箱作業需要額外的設定及拆解成本。這筆費用有多大 實際速度取決於許多因素,包括構建形狀 也能確保主機 OS 的效能對 Linux 來說,沙箱版本極少發生 因此運作速度會減慢一些設定--reuse_sandbox_directories可 可減少設定及成本

  • 沙箱機制實際上會有效停用工具的所有快取。你可以 使用永久工作站即可減少這種情況, 以及效能低弱的沙箱保證成本

  • 多重工作站」需要明確的工作站支援 沙箱模式不支援多工沙箱的工作站將 動態執行下的單面工作站,可能會耗用額外的記憶體。

偵錯

請按照下列策略對沙箱機制問題進行偵錯。

已停用的命名空間

在某些平台上,例如 Google Kubernetes Engine 叢集節點或 Debian,使用者命名空間會預設為停用,這是因為 安全疑慮。如果 /proc/sys/kernel/unprivileged_userns_clone 檔案 且包含 0,您可以執行下列指令來啟用使用者的命名空間:

   sudo sysctl kernel.unprivileged_userns_clone=1

規則執行失敗

由於系統設定,沙箱可能會無法執行規則。如果看到 類似 namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory 的訊息,請嘗試使用 --strategy=Genrule=local 停用沙箱: genrules,--spawn_strategy=local 則適用於其他規則。

建構失敗的詳細偵錯資訊

如果建構失敗,請使用 --verbose_failures--sandbox_debug Bazel 會顯示建構失敗時的確切執行指令,包括 用來設定沙箱

錯誤訊息範例:

ERROR: path/to/your/project/BUILD:1:1: compilation of rule
'//path/to/your/project:all' failed:

Sandboxed execution failed, which may be legitimate (such as a compiler error),
or due to missing dependencies. To enter the sandbox environment for easier
debugging, run the following command in parentheses. On command failure, a bash
shell running inside the sandbox will then automatically be spawned

namespace-sandbox failed: error executing command
  (cd /some/path && \
  exec env - \
    LANG=en_US \
    PATH=/some/path/bin:/bin:/usr/bin \
    PYTHONPATH=/usr/local/some/path \
  /some/path/namespace-sandbox @/sandbox/root/path/this-sandbox-name.params --
  /some/path/to/your/some-compiler --some-params some-target)

您現在可以檢查產生的沙箱目錄,並查看 Bazel 有哪些檔案 並再次執行指令,看看其運作方式。

請注意,使用 Bazel 並不會刪除沙箱目錄 --sandbox_debug。除非您正在主動偵錯,否則應停用 --sandbox_debug,因為它會隨著時間填滿磁碟。