> ## Documentation Index
> Fetch the complete documentation index at: https://ayakaleaf-pro.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# （v5.5.7 遷移）二進位檔案遷移

## 二進位檔案遷移

即將推出的 Server Pro 與社群版主要版本 `6.0` 將把二進位檔案的儲存空間用量減少一半。`5.5.7` 版本包含線上遷移，讓升級過程中的停機時間降到最低。

自 Server Pro `4.x` 起，二進位檔案會儲存兩份：一份在「filestore」的作用中檔案儲存區，另一份在完整專案歷史系統中。今後，每個檔案只會在完整專案歷史系統中儲存一份。

遷移至整合儲存系統包含兩個部分：一個用於控制遷移階段的新旗標，以及一個處理所有作用中與已軟刪除專案的指令碼。

階段：

* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=0`（預設）：檔案從 filestore 讀取並寫入 filestore。檔案會以非同步方式寫入歷史記錄。
* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1`：檔案從歷史記錄讀取，必要時退回 filestore，並同時寫入 filestore 與歷史記錄。可以降級至 `OVERLEAF_FILESTORE_MIGRATION_LEVEL=0`。
* `OVERLEAF_FILESTORE_MIGRATION_LEVEL=2`：檔案只從歷史記錄讀取並寫入歷史記錄。除非遷移是以「離線」方式執行，否則無法降級至 `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1`。

若將資料儲存在 [S3](https://docs.overleaf.com/on-premises/configuration/overleaf-toolkit/s3) 中，且 filestore（`OVERLEAF_FILESTORE_S3_ACCESS_KEY_ID`）與 history（`OVERLEAF_HISTORY_S3_ACCESS_KEY_ID`）使用不同的服務帳號：請授予 filestore 使用者讀取歷史 blob bucket `OVERLEAF_HISTORY_PROJECT_BLOBS_BUCKET` 的權限。今後，filestore 服務將負責處理來自編譯器服務的讀取請求。

<Warning>
  強烈建議先在非正式／沙箱環境中執行二進位檔案遷移。
</Warning>

<Check>
  標準的 Server Pro 授權允許你在一個正式環境以及一個非正式／沙箱環境中執行本應用程式；強烈建議你準備一個非正式環境用於測試。
</Check>

<Info>
  若你升級至 Server Pro/CE `6.0` 版後決定降級至較早的版本，應從完整的系統備份還原。
</Info>

### 遷移程序

<Steps>
  <Step title="建立備份">
    為執行個體建立完整[備份](https://docs.overleaf.com/on-premises/maintenance/data-and-backups#performing-a-consistent-backup)，其中包含 **mongo**、**redis** 與 **sharelatex** 目錄的一致性快照。
  </Step>

  <Step title="更新">
    <strong>Toolkit：</strong> 使用 `$ bin/upgrade` 指令碼將 **toolkit** 升級至最新版本。出現提示 **Upgrade** image? 時，**不要**確認——而是手動編輯 **config/version** 檔案，將值設為 `5.5.7`。

    <strong>舊版 docker-compose.yml：</strong> 將 `sharelatex` 服務的版本更新為 `5.5.7`。
  </Step>

  <Step title="估計受影響的專案數量">
    ```bash wrap theme={null}
    # Overleaf Toolkit users:
    $ bin/docker-compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --report"

    # Legacy docker-compose.yml users:
    $ docker compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --report"
    ```

    輸出範例：

    ```text theme={null}
    Current status:
    - Total number of projects: 10
    - Total number of deleted projects: 5
    Sampling 1000 projects to estimate progress...
    Sampled stats for projects:
    - Sampled projects: 9 (90% of all projects)
    - Sampled projects with all hashes present: 5
    - Percentage of projects that need back-filling hashes: 44% (estimated)
    - Sampled projects have 11 files that need to be checked against the full project history system.
    - Sampled projects have 3 files that need to be uploaded to the full project history system (estimating 27% of all files).
    Sampled stats for deleted projects:
    - Sampled deleted projects: 4 (80% of all deleted projects)
    - Sampled deleted projects with all hashes present: 3
    - Percentage of deleted projects that need back-filling hashes: 25% (estimated)
    - Sampled deleted projects have 2 files that need to be checked against the full project history system.
    - Sampled deleted projects have 1 files that need to be uploaded to the full project history system (estimating 50% of all files).
    ```
  </Step>

  <Step title="清空專案歷史佇列">
    ```bash wrap theme={null}
    # Overleaf Toolkit users:
    $ bin/docker-compose exec sharelatex /overleaf/bin/flush-history-queues

    # Legacy docker-compose.yml users:
    $ docker compose exec sharelatex /overleaf/bin/flush-history-queues
    ```

    重複執行清空，直到所有專案都已清空（`"project_ids":0`）。

    ```text theme={null}
    found projects {"project_ids":0,"limit":100000,"ts":"2025-09-01T10:35:33.353Z"}
    total {"succeededProjects":0,"failedProjects":0}
    ```

    <Danger>
      若「failedProjects」不為零，請聯絡支援團隊，且不要繼續進行二進位檔案遷移。
    </Danger>
  </Step>

  <Step title="將遷移階段推進至 1">
    Toolkit：在 `config/variables.env` 中設定 `OVERLEAF_FILESTORE_MIGRATION_LEVEL=1`。

    舊版 docker-compose.yml：在 `sharelatex` 服務的 `environment` 區段中設定 `OVERLEAF_FILESTORE_MIGRATION_LEVEL: '1'`。
  </Step>

  <Step title="套用設定變更並啟動執行個體">
    Toolkit：`bin/up -d`

    舊版 docker-compose.yml：`docker compose up -d`
  </Step>

  <Step title="驗證二進位檔案的存取">
    在瀏覽器中以 Overleaf 編輯器開啟專案，並選取一個二進位檔案，例如圖片。
  </Step>

  <Step title="執行遷移指令碼">
    ```bash wrap theme={null}
    # Overleaf Toolkit users:
    $ bin/docker-compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --all"

    # Legacy docker-compose.yml users:
    $ docker compose exec sharelatex /bin/bash -c "source /etc/overleaf/env.sh && source /etc/container_environment.sh && cd /overleaf/services/history-v1 && /sbin/setuser www-data node storage/scripts/back_fill_file_hash.mjs --all"
    ```

    <Danger>
      若你將[日誌檔案持久化](https://docs.overleaf.com/on-premises/configuration/overleaf-toolkit/logging#persisting-logs)到 **sharelatex** 容器之外，請確認日誌目錄的擁有者設為 `www-data` 使用者（uid=33），以便寫入輸出的日誌檔案。
    </Danger>

    輸出應如下所示：

    ```bash theme={null}
    Set UV_THREADPOOL_SIZE=16
    {"name":"default","hostname":"c25e9faaeb53","pid":971,"level":30,"backend":"fs","msg":"Loading backend","time":"2025-07-25T15:00:58.166Z","v":0}
    Writing logs into /var/log/overleaf/file-migration-2025-07-25T15_00_58_199Z.log
    Starting project file backup...
    Loaded global blobs: 0
    Processing non-deleted projects...
    Processed 1 projects, elapsed time 0s
    Done updating live projects
    Processing deleted projects...
    The collection deletedProjects appears to be empty.

    Done updating deleted projects
    Done.

    ```

    若遷移成功，結束代碼會是 `0`，且最後幾行會顯示沒有失敗：

    ```bash theme={null}
    Done.
    ```

    日誌檔案會如下所示（請使用指令碼印出的路徑）：

    ```bash wrap theme={null}
    $ docker cp sharelatex:/var/log/overleaf/file-migration-2025-07-25T15_00_58_199Z.log .
    $ cat file-migration-2025-07-25T15_00_58_199Z.log
    {"name":"file-migration","hostname":"c25e9faaeb53","pid":971,"level":30,"end":"68839a8f577b9f009d947b27 (2025-07-25T14:54:07.000Z)","msg":"actually completed batch","time":"2025-07-25T15:00:58.379Z","v":0}
    {"name":"file-migration","hostname":"c25e9faaeb53","pid":971,"level":30,"time":"2025-07-25T15:00:58.383Z","LOGGING_IDENTIFIER":"4effa2000000000000000000","projects":1,"blobs":6,"filesWithHash":5,"filesWithoutHash":2,"filesDuplicated":0,"filesRetries":0,"filesFailed":0,"fileTreeUpdated":0,"badFileTrees":0,"globalBlobsCount":0,"globalBlobsEgress":0,"projectDeleted":0,"projectHardDeleted":0,"fileHardDeleted":0,"mongoUpdates":1,"readFromGCSCount":7,"readFromGCSIngress":28532,"writeToGCSCount":5,"writeToGCSEgress":300,"readFromGCSThroughputMiBPerSecond":0.14925639825786063,"eventLoop":{"idle":48.277844,"active":381.53244699971054,"utilization":0.8876763888372498},"diff":{"eventLoop":{"idle":48.223536,"active":134.04030200059555,"utilization":0.7354190687027976},"projects":1,"blobs":6,"filesWithHash":5,"filesWithoutHash":2,"filesDuplicated":0,"filesRetries":0,"filesFailed":0,"fileTreeUpdated":0,"badFileTrees":0,"globalBlobsCount":0,"globalBlobsEgress":0,"projectDeleted":0,"projectHardDeleted":0,"fileHardDeleted":0,"mongoUpdates":1,"readFromGCSCount":7,"readFromGCSIngress":28532,"writeToGCSCount":5,"writeToGCSEgress":300,"readFromGCSThroughputMiBPerSecond":0.14925639825786063},"deferredBatches":[],"msg":"file-migration stats","v":0}
    ```
  </Step>

  <Step title="停止執行個體">
    Toolkit：`bin/stop sharelatex`

    舊版 docker-compose.yml：`docker compose stop sharelatex`
  </Step>

  <Step title="讓應用程式無法存取舊檔案">
    現在可以將舊檔案移至次要儲存空間。建議保留這些檔案一段時間，以防日後出現問題。

    ```bash wrap theme={null}
    # Toolkit users:
    $ bin/docker-compose run --rm --entrypoint mv sharelatex --no-clobber --verbose /var/lib/overleaf/data/user_files /var/lib/overleaf/data/old_user_files

    # Legacy docker-compose.yml users:
    # We are assuming that you are using the default bind-mount in /var/lib/overleaf
    $ docker compose run --rm --entrypoint mv sharelatex --no-clobber --verbose /var/lib/overleaf/data/user_files /var/lib/overleaf/data/old_user_files
    # In case you are using selective bind-mounts, you can simply remove the bind-mount for /var/lib/overleaf/data/user_files inside the container.
    ```
  </Step>

  <Step title="將遷移階段推進至 2">
    Toolkit：在 `config/variables.env` 中設定 `OVERLEAF_FILESTORE_MIGRATION_LEVEL=2`。

    舊版 docker-compose.yml：在 `sharelatex` 服務的 `environment` 區段中設定 `OVERLEAF_FILESTORE_MIGRATION_LEVEL: '2'`。
  </Step>

  <Step title="套用設定變更並啟動執行個體">
    Toolkit：`bin/up -d`

    舊版 docker-compose.yml：`docker compose up -d`
  </Step>

  <Step title="驗證二進位檔案的存取">
    在瀏覽器中以 Overleaf 編輯器開啟專案，並選取一個二進位檔案，例如圖片。
  </Step>
</Steps>

#### 離線遷移

若要在二進位檔案遷移指令碼執行期間阻止使用者登入，請依照下列步驟操作：

* 以管理員帳號登入 Overleaf 執行個體
* 點選 **Admin** 按鈕並選擇 **Manage Site**
* 點選 **Open/Close Editor** 分頁
* 點選 **Close Editor** 按鈕
* 點選 **Disconnect all users** 按鈕

完成後，任何已登入的使用者都會被重新導向至維護頁面，而造訪登入頁面的新使用者會看到維護頁面且**無法**登入。

重新啟動執行個體時，你需要重複這些步驟。若要重新開放網站，只需重新啟動執行個體即可。

#### 線上遷移

你可以在應用程式仍在執行時執行遷移指令碼，但需要考量以下幾點：

* 遷移過程會大量使用 IO，指令碼執行期間應監控資源使用狀況。
* 若處理並行度較高，`filestore` 服務的事件迴圈可能會出現阻塞，導致使用者體驗下降。建議先使用預設值 `--concurrency=10` 與 `--concurrent-batches=1`。
* 你可以隨時停止指令碼。再次啟動時，會驗證先前的專案並略過已處理的檔案。若你偏好在較不忙碌的時段（例如夜間）執行遷移，這會很有用。

當專案數量少於 1000 個時（請參閱以 `--report` 執行遷移指令碼的輸出），我們建議關閉網站，並在維護時段內以離線方式執行遷移。若專案數量龐大，你可以先執行指令碼並監控進度，再依照實際情況決定要繼續以線上或離線方式執行。

#### 清除舊版二進位檔案資料

完成遷移並確認專案仍可存取所有檔案後，你可以移除 `/var/lib/overleaf/data/user_files` 中的舊檔案儲存區。我們強烈建議保留這些檔案一段時間——你可以先重新命名資料夾，讓應用程式無法存取它們。

### 疑難排解

我們會在此處加入疑難排解建議。請注意，雖然我們通常只為 Server Pro 客戶提供支援，但考量此遷移的性質，我們也會盡力協助遇到二進位檔案遷移特定問題的 CE 客戶。

若二進位檔案遷移指令碼失敗（即以錯誤結束，或印出的失敗專案數不為零），請透過電子郵件將下列詳細資訊寄給我們的支援團隊 [support+filestoremigration@overleaf.com](mailto:support+filestoremigration@overleaf.com?subject=Binary%20file%20migration%20problem\&body=Instance%20Type%3A%20CE%20or%20Server%20Pro%20%28delete%20as%20appropriate%29%0A%0AInstallation%20Type%3A%20Overleaf%20toolkit%20or%20docker-compose.yml%20or%20other%20%28delete%20as%20appropriate%29%0A%0AScript%20output%3A%0A%0Abin%2Fdoctor%20output%20%28if%20using%20toolkit%29%3A%0A)，內容包括：

主旨：Binary file migration problem

內文：

* 執行個體類型：CE 或 Server Pro（刪除不適用者）
* 安裝類型：Overleaf toolkit、`docker-compose.yml` 或其他（刪除不適用者）
* 版本：5.5.x（toolkit：`$ cat config/version`）
* 遷移指令碼輸出（應位於容器內的 `/var/log/overleaf` 底下）
* 報告：（以 `--report` 執行遷移指令碼）
* 已處理的專案：（依據最後一次執行指令碼的結果）
* 遷移所需時間：
* `bin/doctor` 輸出（使用 toolkit 時）
* Toolkit 版本：`$ git rev-parse HEAD`（使用 Toolkit 時）

建議在郵件中附上 `filestore` 服務的日誌檔案。你可以在 `sharelatex` 容器內的 `/var/log/overleaf/filestore.log` 找到它，並以下列方式匯出：

```bash theme={null}
$ docker cp sharelatex:/var/log/overleaf/filestore.log .
# replace <timestamp> with the timestamp as printed by the script
$ docker cp sharelatex:/var/log/overleaf/file-migration-<timestamp>.log .
```

附加日誌檔案前，請先遮蔽其中的任何敏感資訊。

#### 遺失的檔案

舊版的 Server Pro/CE 會在使用者上傳完成前建立檔案樹項目，因此上傳失敗時，檔案可能會顯示為遺失。在處理所有檔案樹時，你可能會發現少數此類情況被回報為錯誤。

若遺失的檔案數量不多，可以考慮手動檢查這些情況，並在瀏覽器的編輯器中刪除它們。

若遺失的檔案數量很多，請考慮聯絡支援團隊，郵件範本請見上方。

#### 找出損壞的檔案樹

對於檔案樹格式錯誤的專案（例如檔名為空），遷移可能會失敗。你可以使用 `find_malformed_filetrees` 指令碼檢查資料庫中的所有專案，找出這些問題的清單：

```bash wrap theme={null}
$ bin/docker-compose exec sharelatex /bin/bash -c "cd /overleaf/services/web && /sbin/setuser www-data node scripts/find_malformed_filetrees.mjs > /tmp/malformed-file-trees.json"
```

若要修正無效的路徑，請使用 `fix_malformed_filetree` 指令碼，針對每個有問題的路徑各執行一次指令：

```bash wrap theme={null}
$ bin/docker-compose exec sharelatex /bin/bash -c "cd /overleaf/services/web && /sbin/setuser www-data node scripts/fix_malformed_filetree.mjs --logs=/tmp/malformed-file-trees.json"
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.