在AEM 6.x中報告問題時如何偵錯SegmentNotFoundException

本文可協助您瞭解在AEM 6.x中報告問題時,如何透過回覆至區段存放區的最後一個已知良好修訂來偵錯SegmentNotFoundException。

說明 description

環境

Experience Manager6.x

問題/症狀

錯誤記錄會顯示SegmentNotFound例外狀況,如下列範例所示:

org.apache.jackrabbit.oak.segment.SegmentNotFoundException: Segment d2c720c4-c146-4ab1-ac37-542aad93c33f not found at

org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:602) at

org.apache.jackrabbit.oak.segment.file.FileStore$8.call(FileStore.java:542) at

org.apache.jackrabbit.oak.segment.SegmentCache.getSegment(SegmentCache.java:95) at

org.apache.jackrabbit.oak.segment.file.FileStore.readSegment(FileStore.java:542) at

org.apache.jackrabbit.oak.segment.SegmentId.getSegment(SegmentId.java:125) at

org.apache.jackrabbit.oak.segment.Record.getSegment(Record.java:70) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:424) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:391) at

org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at

org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148) at

org.apache.jackrabbit.oak.segment.MapRecord$3.childNodeChanged(MapRecord.java:442) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:490) at

org.apache.jackrabbit.oak.segment.MapRecord.compare(MapRecord.java:433) at

org.apache.jackrabbit.oak.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:608) at

org.apache.jackrabbit.oak.spi.commit.EditorDiff.process(EditorDiff.java:52) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.updateIndex(AsyncIndexUpdate.java:695) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.runWhenPermitted(AsyncIndexUpdate.java:543) at

org.apache.jackrabbit.oak.plugins.index.AsyncIndexUpdate.run(AsyncIndexUpdate.java:402) at

org.apache.sling.commons.scheduler.impl.QuartzJobExecutor.execute(QuartzJobExecutor.java:118) at

org.quartz.core.JobRunShell.run(JobRunShell.java:202) at

java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at

java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at

java.lang.Thread.run(Thread.java:745)

解決方法 resolution

解決步驟

有兩種方式可修正問題並移除存放庫中的不一致

還原到區段存放區的最後一個已知良好修訂。

首先,  使用oak run工具,這是可執行的jar[ 1],包含您進行簡單Oak安裝及執行oak相關作業所需的一切。

Oak-run的檢查執行模式可用於確定區段存放區的最後一個已知良好修訂。  這可用於手動將損壞的區段存放區恢復到其最新的良好修訂。

注意:此程式會將系統中的資料復原到之前的時間點。  如果您想要避免遺失系統中的變更,可以改為嘗試下面的選項B。

若要執行檢查和還原:

  1. https://mvnrepository.com/artifact/org.apache.jackrabbit/oak-run 下載和您的 Oak 核心版本相符的 Oak-run 版本

  2. 若要將損壞的區段存放區恢復到其最新的良好狀態,請變更為CQ的工作目錄(包含crx-quickstartfolder的工作目錄)並在中備份所有檔案。/crx-quickstart/repository/segmentstore/。

  3. 執行一致性檢查,

    java -Xmx6000m -jar oak-run-*.jar check —bin=-1 /path/to/crx-quickstart/repository/segmentstore

    這會向後搜尋修訂,直到找到一致的修訂:

    查找如下訊息:

    code language-none
    main INFO o.a.j.o.p.s.f.t.ConsistencyChecker - Found latest good revision afdb922d-ba53-4a1b-aa1b-1cb044b535cf:234880
    
  4. 透過編輯將存放庫還原到此版本。/crx-quickstart/repository/segmentstore/journal.log ,並刪除包含最新良好修訂的行之後的所有行。

  5. 移除全部。/crx-quickstart/repository/segmentstore/*.bak檔案。

  6. 使用下列命令執行查核點清理以移除孤立的查核點:

    code language-none
    java -Xmx6000m -jar oak-run-*.jar checkpoints /path/to/crx-quickstart/repository/segmentstore rm-unreferenced
    
  7. 最後,壓縮存放庫:

    java -Xmx6000m -jar oak-run-*.jar compact /path/to/crx-quickstart/repository/segmentstore/

在某些情況下,Oak執行檢查詢不到良好的修訂,並且在執行檢查命令時我們收到「ConsistencyChecker — 找不到良好的修訂」。

如何修正一致性檢查中遇到「ConsistencyChecker — 找不到良好的修訂」時損毀

手動移除損壞的節點。

您可以在AEM、未設定FileDatastore的TarMK設定,以及二進位檔案中有損毀的情況中進行以下操作。

警告:下列程式適用於進階使用者。  刪除損壞的節點時,您需要確保它們不是系統節點(例如/home、/jcr:system等)。  如果它們是系統節點,您必須確定可將其還原。  如果您不確定,請向AEM客戶服務團隊尋求此處記錄的步驟的協助。

  1. 停止 AEM。

  2. 使用Oak run主控台並載入childCount groovy指令碼來識別區段存放區中的損壞節點:

    載入 Oak-run 主控台殼層:

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    在殼層中執行以下兩個命令來載入指令碼並執行:

    code language-none
    :load https://gist.githubusercontent.com/stillalex/e7067bcb86c89bef66c8/raw/d7a5a9b839c3bb0ae5840252022f871fd38374d3/childCount.groovy
    countNodes(session.workingNode)
    

    這會導致以下輸出指示損壞節點的路徑:

    code language-none
    21:21:42.029 main ERROR o.a.j.o.p.segment.SegmentTracker - Segment not found: 63ae05a4-b506-445c-baa2-cfa1b13b6e2f. Creation date delta is 3 ms.
    warning unable to read node /content/dam/test.txt/jcr:content/renditions/original/jcr:content
    

    在某些情況下,該問題與二進位屬性有關,並且childCount groovy指令碼無法找到任何損壞的節點。  在這些情況下,您可以改用以下命令,它將讀取周遊期間遇到的每個二進位檔案的前1024個位元組(請注意,此命令會較慢,並且僅應在上述命令未傳回預期結果時使用):

    code language-none
    countNodes(session.workingNode,true)
    
  3. 使用rmNodes.groovy移除最後一個命令輸出清單中所有已識別的損壞節點
    使用以下命令載入Oak-run主控台殼層:

    code language-none
    java -jar oak-run-*.jar console crx-quickstart/repository/segmentstore
    

    載入 groovy 指令碼:

    code language-none
    :load
    https://gist.githubusercontent.com/stillalex/43c49af065e3dd1fd5bf/raw/9e726a59f75b46e7b474f7ac763b0888d5a3f0c3/rmNode.groovy
    

    執行rmNode命令以移除損壞的節點,將/path/to/corrupt/node替換為您需要移除的損壞節點的路徑。

    code language-none
    rmNode(session, "/path/to/corrupt/node")
    

    其中損壞的節點路徑為步驟2中取得的路徑,例如:"/content/dam/test.txt/jcr:content/renditions/original/jcr:content/"

    注意:使用oak-run.jar版本1.6.13及更高版本時,設定 — 讀寫JVM引數,如果您遇到錯誤,例如:

    code language-none
    / rmNode(session,"/path/to/corrupt/node")    Removing node /path/to/corrupt/node    ERROR java.lang.UnsupportedOperationException:    Cannot write to read-only store    at org.apache.jackrabbit.oak.segment.SegmentWriterBuilder$1.execute (SegmentWriterBuilder.java:171)    at org.apache.jackrabbit.oak.segment.SegmentWriter.writeNode (SegmentWriter.java:318)    at org.apache.jackrabbit.oak.segment.SegmentNodeBuilder.getNodeState (SegmentNodeBuilder.java:111)    at org.apache.jackrabbit.oak.segment.SegmentNodeStore$Commit.init (SegmentNodeStore.java:581)    at org.apache.jackrabbit.oak.segment.SegmentNodeStore.merge (SegmentNodeStore.java:333)    at org.apache.jackrabbit.oak.spi.state.NodeStore$merge.call (Unknown Source)    at groovysh_evaluate.rmNode (groovysh_evaluate:11)
    
  4. 對步驟2中找到的所有節點重複步驟3

    上面這個rmNode命令應該會對損壞的路徑傳回true,這表示它刪除了它。 請確保透過重新執行這些路徑上的rmNode命令來刪除這些找到的三個損壞的路徑。 下次執行它應該會傳回false。
    如果您看到存放庫中仍然存在相同的路徑,則使用oak-run jar的 修補版本,即oak-run-1.2.18-NPR-17596。 此版本的jar在壓縮時會略過無法讀取的二進位檔案,將它們替換為0位元組的二進位檔案並記錄例外狀況和syserr的路徑。 如此產生的壓縮存放庫應該會通過Oak-run檢查和節點計數指令碼,並且您也應該能夠使用未修補的Oak-run再次壓縮它。

  5. 透過使用以下查核點清單來執行查核點清理。如果有多個查核點,則將其清除:

    code language-none
    nohup java -Xmx4096m -jar oak-run-1.2.18.jar checkpoints /app/AEM6/author/crx-quickstart/repository/segmentstore rm-allnohup.out
    
  6. 執行離線壓縮。 如果您不知道如何執行離線壓縮,請參閱這裡

  7. 啟動伺服器等待索引完成。

原因

錯誤記錄檔中的SegmentNotFoundException表示區段已不存在,儘管顯然有人仍嘗試存取它。 這大致有三個不同的根本原因:區段已由手動介入移除(例如rm -rf /)、區段已由修訂垃圾收藏集移除,或由於程式碼中的一些錯誤而找不到區段。

recommendation-more-help
3d58f420-19b5-47a0-a122-5c9dab55ec7f