跳到正文
本頁目錄

lip 的工作原理

讀完本頁,你就知道你向 lip 提出要求時它對伺服器資料夾做了什麼、為什麼一次變更可以放心取消、lip 的背景處理程序是做什麼用的,以及為什麼有些事命令允許而介面拒絕。使用 lip 並不需要了解這些。遇到意料之外的情況時,它們會有幫助。

工作區

工作區是一個存放一個伺服器的資料夾。對命令來說,它是你目前所在的資料夾。對介面來說,它是目前工作區,也就是你在介面裡選取的那個。

工作區裡有兩類東西:

  • 伺服器:遊戲、載入器、你的模組、你的世界和設定。這些都是普通檔案,放在遊戲期望的位置。
  • .lip/:lip 對這個資料夾的瞭解。
.lip/ 裡的是什麼
state.json已安裝套件的清單:每個套件的版本、來源、是否由你安裝,以及它安裝的檔案。見狀態檔。
config.toml這個工作區的設定。見設定。
locklip 變更工作區期間佔用的檔案。
server.locklip 執行伺服器期間佔用的檔案。
journal正在進行的變更的記錄。只在變更期間存在,或者在變更被中斷之後存在。
logs/失敗報告。
wine/在 Linux 和 macOS 上,伺服器的 Wine 前綴。

lip 對一個伺服器的全部瞭解都在它的資料夾裡。移動或複製資料夾,伺服器就跟著走。工作區不相依任何登錄檔或中央清單;唯一的例外是介面顯示的資料夾清單,那只是為了方便。

每個檔案的說明見檔案和目錄。

遊戲、載入器、模組和相依

lip 安裝的一切都是套件:一組檔案,加上一份說明,也就是 lip.toml,其中寫明哪些檔案放到哪裡、這個套件還需要什麼。套件在工作區裡扮演四種角色:

角色是什麼數量
遊戲某個版本的 Minecraft 基岩版專用伺服器,Windows 版或 Linux 版。lip 從 Minecraft 官方網站下載它。最多一個
載入器LeviLamina,它改造遊戲,使之能載入模組。只用於 Windows 伺服器。最多一個
模組由 LeviLamina 載入的套件。安裝在 mods/<名字>/。任意多個
相依別的套件需要的套件。按需

由此得出兩條規則。

遊戲和載入器是模組立足的地基。 每個載入器版本都寫明瞭它支援哪些遊戲版本,每個模組也寫明瞭自己需要什麼。所以 lip install 和 lip update 不動遊戲和載入器;它們尋找與之相配的模組版本。只有伺服器安裝會更換地基,並隨之把每個模組換成與新地基相配的版本。伺服器安裝指的是 lip setup,或者點名 LeviLamina 或遊戲本身的 lip install。

lip 記得你要求過什麼。 你點名的套件屬於你:在你解除安裝之前,它一直都在。相依之所以存在,只是因為有套件需要它;沒有套件需要時,lip 就會移除它。

每個套件擁有它安裝的檔案。兩個套件不能擁有同一個檔案,lip 也絕不刪除不屬於任何套件的檔案,只有一個例外:套件可以聲明自己留下的一些東西,在它被移除時一併清除。遊戲對它的某些資料夾就是這樣做的。見保留什麼刪除什麼。

操作

一次操作是對工作區的一次變更:一條 lip setup、lip install、lip update 或 lip uninstall 所做的一切,包括它新增或移除的每個相依。一次操作要麼完整地發生,要麼完全不發生。

它經過這些步驟:

  1. 加鎖。 lip 佔用 .lip/lock。如果另一個 lip 佔著它,操作立刻失敗。所以兩次變更絕不會混在一起。
  2. 恢復。 如果之前有操作被中斷,lip 先把它理順。
  3. 決定。 lip 讀取已安裝的內容,向網路查詢有哪些版本,選出一組彼此相配的套件,下載它們,並檢查每個檔案都能放置。到這裡工作區裡還什麼都沒變。大多數失敗發生在這一步,工作區原封不動。
  4. 準備系統。 如果要執行 Windows 程式,lip 會確保系統能執行它們。
  5. 變更。 lip 刪除和寫入檔案,並執行套件要求執行的程式。每次變更之前,它先在 .lip/journal 裡記一筆。被取代或刪除的檔案,會先以一個隱藏的名字留在原處旁邊。
  6. 提交。 lip 寫入新的 state.json,把日誌標記為完成,然後刪除留在旁邊的舊檔案和日誌。
  7. 解鎖。

模組頁面上有一個標題為「解除安裝 github.com/LiteLDev/LegacyMoney」的對話方塊。它列出將要發生的事:解除安裝 LegacyMoney 0.16.1 和 LegacyRemoteCall 0.13.0。標註 1 指向計劃,標註 2 指向「套用」和「取消」按鈕。

在介面裡,你在「套用」之前看到的計劃就是第 3 步的結果,它是在不做任何變更的情況下得出的。

復原

因為每次變更都先記錄再執行,每個舊檔案都保留到最後,lip 總是能退回去:

  • 變更過程中某一步失敗:lip 按相反的順序復原變更。工作區和 state.json 恢復原樣。
  • 你取消了,用 Ctrl+C 或介面裡的「取消」:同上。
  • lip 被殺掉,或者斷電:日誌還在。那個資料夾裡的下一次操作,或者下一次 lip run,會讀取它。如果那次操作已經走到了提交,lip 就把清除做完。否則就復原那次操作。

有一樣東西無法復原:套件的程式在執行期間做過的事。我們要求套件的作者把這類程式寫成重複執行也無害的樣子。

失敗會在終端機或對話方塊裡得到說明,並被完整地記錄下來。見故障排查。

試執行

試執行是一次在第 5 步之前停下的操作。用 --dry-run 就能得到一次試執行;介面在每次變更之前也會做一次,好把計劃展示給你。

試執行是一項保證:

  • 它不變更任何檔案:工作區裡的、快取裡的、你的設定裡的,都不改。
  • 它不執行任何程式,也不往系統裡安裝任何東西。
  • 它不提問。操作會提問的地方,它只說明會問。
  • 它不加鎖,所以既不會等待也不會阻塞另一個 lip。
  • 它不修復被中斷的操作。它只告訴你有這樣一次操作。

它做的是第 3 步裡的一切,包括聯網和下載,所以它給出的計劃,就是工作區在目前狀態下的真實計劃。

用法見試執行。

常駐程式和客戶端

你執行 lip install 時,幹活的並不是你啟動的那個程式。它把請求交給一個背景處理程序,也就是常駐程式,再把常駐程式的反饋顯示給你。你啟動的那個程式是客戶端。

常駐程式的存在有兩個原因:

  • 讓伺服器比終端機活得久。 屬於某個終端機的處理程序會隨終端機一起結束。常駐程式不屬於任何終端機,所以它執行的伺服器會一直執行下去。
  • 共享同一個視圖。 你在任何終端機裡開啟的每個介面,都與同一個常駐程式通信。它們看到的是同樣的伺服器、同樣的工作區清單。

你不需要管理常駐程式:

  • 它會自己啟動。 沒有常駐程式在執行時,第一條 lip 命令會啟動它。
  • 每個使用者一個。 只有它所屬的使用者才能連線它:在 Windows 上通過命名管道,在其他系統上通過只有你能開啟的套接字檔案。
  • 命令的表現和 lip 直接執行時一樣。 它在你的資料夾裡工作,使用你終端機的環境變數,讀取你的鍵盤輸入,輸出到你的終端機,並以同樣的結束代碼結束。Ctrl+C 也能傳到它那裡。
  • 命令之間互不干擾。 常駐程式可以同時執行多個終端機的命令,每條命令都有自己的資料夾和設定。
  • 它會自己結束:沒有客戶端連線、也沒有伺服器在執行,持續 10 分鐘之後。只要它在執行伺服器,就絕不會結束。
  • 更新之後它會被取代。 較新的 lip 會請較舊的常駐程式結束,並啟動自己的。

lip daemon status 顯示它是否在執行,lip daemon stop 在它空閒時結束它。見 lip daemon。

沒有常駐程式時

如果客戶端無法啟動或連線常駐程式,或者常駐程式是個忙得走不開的舊版本,客戶端會說明情況,然後自己完成工作。命令做的事是一樣的。缺少的只是需要長期背景處理程序才能做到的東西:託管伺服器。

見 lip 自己執行了命令。

託管伺服器和伺服器鎖

伺服器有兩種執行方式。

普通:lip run託管:介面,或 lip run --managed
屬於啟動它的終端機常駐程式
終端機關閉時伺服器被要求停止伺服器繼續執行
它的主控台那個終端機每個接入它的客戶端,以及每個介面的伺服器頁面
誰能停止它那個終端機任何已接入的客戶端,以及任何介面

託管伺服器是常駐程式執行的、不專屬於任何人的伺服器。客戶端接入它來檢視輸出、向它輸入,之後再脫離,不會打擾它。常駐程式在一個工作區裡最多執行一個。

無論伺服器以哪種方式執行,執行它的處理程序都佔著伺服器鎖,也就是 .lip/server.lock。「一個工作區一個伺服器」正是靠它實現的:第二次啟動會發現鎖被佔用,於是失敗。lip 也是靠它得知有伺服器在執行,即使那不是它自己啟動的。

伺服器鎖和工作區鎖是分開的。執行伺服器不會鎖住工作區、阻止變更;變更工作區也不需要伺服器鎖。

見讓伺服器持續執行。

介面與命令

介面不是另一個有自己一套邏輯的程式。你在介面裡做的每件事,都是在目前工作區裡執行的一條命令,只是輸出顯示在對話方塊裡而不是終端機裡。命令做的事兩邊完全一樣。

介面只在一個地方更謹慎。目前工作區的伺服器執行期間,介面:

  • 不在那裡安裝、更新、解除安裝任何東西,也不在那裡安裝伺服器;
  • 不儲存 server.properties、allowlist.json 和 permissions.json。

它會請你先停止伺服器:

伺服器執行時的模組頁面。頂部有一行「伺服器執行中,停止後才能變更模組。」某個模組的選單開啟著,其中的更新和解除安裝項被禁用,原因是「請先停止伺服器。」

模組的設定它仍然會儲存,這些設定在下次啟動時生效。

不管伺服器是怎麼啟動的,都是如此:由這個介面啟動、由另一個介面啟動,還是由某個終端機裡普通的 lip run 啟動。介面是通過伺服器鎖得知的。

命令不會拒絕。 伺服器執行時 lip install 照樣工作,而且無論結果如何,變更都是安全的。如果某個檔案因為被執行中的伺服器開啟而無法取代,操作會失敗並被復原。如果成功了,伺服器會在下次啟動時用上變更。

伺服器執行期間介面命令
安裝、更新、解除安裝、安裝伺服器拒絕允許。可能因檔案被佔用而失敗,這時會被復原。
編輯遊戲的設定顯示但不儲存lip 沒有相應的命令。請自己編輯檔案。
編輯模組的設定允許同上。
檢視已安裝的內容允許允許

還有一點不同:介面把伺服器作為託管伺服器啟動,而不帶 --managed 的 lip run 不是。

頁面與命令的完整對應關係見介面參考。

使用者目錄

在工作區之外,lip 為每個使用者保留四個目錄。

目錄存放WindowsLinux 和 macOS
設定你的設定 config.toml%APPDATA%\lip$XDG_CONFIG_HOME/lip,預設 ~/.config/lip
快取從網上下載的檔案,留著以免重複下載%LOCALAPPDATA%\lip\Cache$XDG_CACHE_HOME/lip,預設 ~/.cache/lip
資料lip 為執行伺服器而安裝的東西:Linux 和 macOS 上是它的 Wine%LOCALAPPDATA%\lip\Data$XDG_DATA_HOME/lip,預設 ~/.local/share/lip
狀態介面的工作區清單 workspaces.json%LOCALAPPDATA%\lip\State$XDG_STATE_HOME/lip,預設 ~/.local/state/lip

哪些可以放心刪除:

  • 快取,任何時候都可以:lip cache clean。需要的東西 lip 會重新下載。
  • 資料目錄,在沒有 lip 執行時。lip 需要時會重新安裝 Wine。
  • 狀態目錄,在沒有 lip 執行時。丟失的只是介面裡的資料夾清單,不是資料夾本身。
  • 設定目錄裡只有你的設定。

在 Linux 和 macOS 上,常駐程式的套接字在 $XDG_RUNTIME_DIR/lip 裡;該變數未設定時在狀態目錄裡。在 Windows 上,常駐程式使用命名管道,它不是檔案。

除了這些目錄、套接字所在的目錄、工作區以及你給出的路徑,lip 還會寫一個地方:它自己的安裝目錄,在 lip self-update 取代 lip 的時候。它不使用系統的臨時目錄。

接下來