将过期的全局编录服务器重新联机后,可能会保留挥之不去的对象

本文介绍在使脱机 DC 恢复联机后,清理重新引入 AD 的对象的过程。

适用于:Windows Server 2019、Windows Server 2016、Windows Server 2012 R2
原始 KB 编号: 314282

症状

将域控制器 (DC) 或全局编录服务器脱机很长时间后将其联机。 联机后,观察以下一个或多个问题:

  • 电子邮件不会传递到用户对象在域之间移动的用户。 使过时的 DC 或全局编录服务器重新联机后,用户对象的两个实例将显示在全局目录中。 这两个对象具有相同的电子邮件地址,因此无法传递电子邮件。
  • 不再存在的用户帐户仍显示在全局地址列表中。
  • 不再存在的通用组仍显示在用户的访问令牌中。
  • 其他 DC 或全局编录服务器记录事件,例如 EventID 1084,服务器上 没有此类对象。 在受影响的 DC 或全局编录服务器上阻止进一步复制。

原因

如果 DC 或全局编录服务器脱机的时间超过用户对象的 Tombstone-Lifetime 属性值,则可能会出现这些问题。

有关 Tombstone-Lifetime 属性的详细信息,请参阅 Tombstone-Lifetime 属性

Tombstone-Lifetime 属性定义从目录服务中删除已删除对象之前的天数。 这有助于从复制的服务器中删除对象,并防止还原重新引入已删除的对象。 默认值为 180 天。 之后,Active Directory 不再需要记住更改。

如果 DC 或全局编录服务器脱机的时间超过 Tombstone-Lifetime 属性的值,则其 Active Directory (副本或全局编录) 可能包含已在其他 DC 上删除的对象。 但是,其他 DC 不再记得这些对象已被删除。 使脱机 DC 联机时,它会将其 Active Directory 副本与域的其余部分同步。 由于有关删除的信息已被丢弃,DC 会将受影响的对象 (称为“挥之不去的对象”) 复制回域的其余部分。

通常,AD DS 使用 松散一致性复制模型,其中某些命名上下文 (也称为目录分区) 是可读/写的,而其他命名上下文是只读的。 当接收属于读/写命名上下文的复制对象的 DC,并且该对象尚不存在于目录信息树 (DIT) 的本地副本中时,DC 会创建该对象。 随着复制过程的继续,对象将重新出现在域中的所有 DC 上。

DC 和全局编录服务器还可以使用严格的复制一致性模型。 在此模型中,当 DC 收到本地 DIT 中尚不存在的复制对象时,DC 停止接收或发送复制的数据,并记录事件,例如事件 ID 1084,“服务器上没有此类对象”。有关严格复制一致性的详细信息(包括 DC 在默认情况下可能使用此模型的情况),请参阅 KB 910205、有关Windows Server Active Directory林中延迟对象的信息。 有关逻辑删除问题的详细信息,请参阅 KB216993 Active Directory 系统状态备份的有用保质期

解决方法 1:确定 Active Directory 是否具有挥之不去的对象,并避免将来的挥之不去的对象

KB 910205 介绍了确定 Active Directory 系统是否累积了挥之不去对象的几种方法。 KB 910205还介绍了为防止挥之不去的对象而可以采取的步骤。

解决方法 2:删除挥之不去的对象

例如,如果对象根本不应该存在于 Active Directory (中,例如,如果对象是由过时的域控制器) 重新引入的,则可以使用标准工具 ((如 ADSIEdit 或 Active Directory 用户和计算机 管理单元) )删除对象。

可以轻松删除读取/写入命名上下文的挥之不去的对象。 在 Windows Server 2003 及更高版本中,可以使用 命令 repadmin /removelingeringobjects删除挥之不去的对象。 有关如何使用 RepAdmin 的信息,请参阅 Active Directory 复制事件 ID 1388 或 1988:检测到一个挥之不去的对象

本文介绍如何删除已出现在只读命名上下文(例如全局编录服务器上的目录分区或 Read-Only 域控制器 (RODC) )中的挥发对象。 更多信息部分讨论的功能仍存在于较新的操作系统中,并且可能仍可用于排查意外的 RepAdmin 行为。

更多信息

此过程需要具有对象的读/写副本的 DC 的 objectGUID ,以及对象本身的 objectGUID 。 如果必须删除多个对象,请确定任何对象是否处于父/子关系中, (可以从对象的可分辨名称) 确定这一点。 如果是这种情况,请对删除进行排序,以便在其父对象之前删除所有子对象。

此过程包含三个主要步骤,必须在有权访问林 (的计算机上执行这些步骤,并且必须使用对林) 具有管理权限的用户帐户:

  1. 获取 linging 对象的可分辨名称和 ObjectGUID。
  2. 标识对象域中的 DC。
  3. 删除挥之不去的对象。 选择以下方法之一:
    • 删除几个挥之不去的对象。
    • 删除大量挥之不去的对象。

重要

要在其中运行删除操作 (步骤 3) 的每个全局编录服务器都必须与 (步骤 2) 标识的域控制器建立网络连接。

有关故障排除信息,请参阅以下部分:

  • 运行 Walkservers.cmd 以修改环境中的许多挥之不去的对象时出现错误消息。
  • 删除环境中挥之不去的对象时出现错误消息 87。

获取 linging 对象的可分辨名称和 ObjectGUID

标识对象所在的域 (的最佳方法是检索对象的可分辨名称,从中确定具有对象读/写副本的 DC 的名称) 。 可以使用 Ldp.exe 工具搜索对象的名称 (或名称) 部分。 为此,请按照下列步骤操作:

  1. 启动 Ldp.exe。

    在大多数版本的 Windows 中,选择“ 开始>运行” 并输入 ldp.exe。 在较旧版本的 Windows ((如 Windows Server 2003 SP1) 此工具作为支持工具之一提供)。

  2. 选择“连接”>“连接”。 在“ 服务器 ”框中,键入全局编录服务器的名称。 在“ 端口 ”框中,键入 3268,然后选择“ 确定”。

  3. 选择“ 连接>绑定”。 如果当前凭据不足以查询所有全局目录内容,请键入有效凭据。 选择“确定”。

  4. 选择“ 视图>”。 输入林根的可分辨名称,然后选择“ 确定”。

  5. 在树列表中,右键单击林根,然后选择“ 搜索”。

  6. 在“筛选器”框中,键入使用属性> = <值>格式的<筛选器。

    在筛选器文本中, <属性> 表示要搜索的对象属性, <值> 表示要搜索的条件。 可以使用 ***** 作为值中的通配符,并且可以使用表达式。

    有关轻型目录访问协议 (LDAP) 筛选器语法的信息,请参阅 搜索筛选器语法

    例如,若要查找其 sAMAccountName 属性具有 testuser 值的对象,请在“筛选器”框中键入 (sAMAccountName = testuser) 。 若要搜索用户对象,以下属性最有用:

    • cn
    • userPrincipalName
    • sAMAccountName
    • 名称
    • mail
    • sn

    若要搜索组对象,以下属性最有用:

    • cn
    • sAMAccountName
    • 名称
  7. 在“ 范围”下,选择“ 子树”。

  8. 选择“ 属性 ”框,然后选择属性字符串的末尾。 键入 ;字符串末尾的 objectGUID

    “搜索”窗口的屏幕截图,其中在“属性”框中的字符串末尾键入了 ;objectGUID。

    在某些 Ldp 版本中,必须选择 “选项” 才能查看 “属性 ”框。

  9. 若要运行查询,请选择“ 运行”。

    结果将显示在 main Ldp 窗口中。

  10. 确定应从全局编录中删除结果中列出的对象(如果有)。 发现错误的对象的一个指示是,该对象不存在于命名上下文的读/写副本上。

  11. 如果要查找的对象未包含在查询结果中,请重新筛选并再次运行搜索。

  12. 如果已标识一个挥之不去的对象,请记下其 DNobjectGUID 属性的值。 稍后将需要这些值。

标识对象域中的 DC

对象的 DN 属性的值包括 对象的域。 知道域后,可以标识域中的 DC 或全局编录服务器。 为此,请按照下列步骤操作。

  1. 检查 DN 值的 dc= 部分。 组合 dc= 部分以获取域名。

    例如,如果对象的 DN 值为 cn=FirstName LastName,cn=Users,dc=name1,dc=name2,dc=com,则对象位于 name1.name2.com 域中。

  2. 若要在此域中查找 DC (或全局编录服务器) ,请打开Active Directory 用户和计算机,打开域容器,然后打开域控制器容器。

  3. 打开提升的命令提示符窗口并输入 repadmin /showreps dc-name

    注意

    在此命令中, dc-name 表示在步骤 2 中标识的 DC 的计算机名称。

    在较旧版本的 Windows ((例如 Windows Server 2003 SP1) )中,RepAdmin 可用作支持工具之一。

    Repadmin 生成类似于以下内容的结果:

    Default-First-Site-Name\WS2016-DC-01 DSA 选项:IS_GC站点选项: (无) DSA 对象 GUID: <GUID> DSA invocationID: <invocationID>

  4. 请注意 DSA 对象 GUID 的值。 这是 DC 的 objectGUID 值。

删除挥之不去的对象

使用以下方法删除挥之不去的对象。

从几个全局编录服务器中删除几个挥之不去的对象

如果只有几个对象和全局编录,请按照以下步骤使用 Ldp.exe 删除对象:

  1. 使用企业管理员凭据登录到每个全局编录服务器,该服务器包含一个挥之不去对象的副本。

  2. 启动 Ldp.exe 并连接到本地域控制器上的端口 389, (将 “服务器 ”框留空) 。

  3. 选择“ 连接>绑定”。 将所有框留空, (已以企业管理员) 身份登录。

  4. 选择“ 浏览>修改”。

    “修改”窗口的屏幕截图,其中可以配置一些条目。

  5. 在“ 修改 ”对话框中配置以下条目:

    1. Dn 框留空。

    2. “属性 ”框中,键入 RemoveLingeringObject

    3. 在“ ”框中,键入使用以下格式的值:

      <GUID=dcGUID>: <GUID=objectGUID>

      在此值中, dcGUID 表示在本部分的步骤 2 中标识的 DC 的 GUID,而 objectGUID 表示在本部分的步骤 1 中标识的挥之不去对象的 GUID。

      该值应如下所示:

      <GUID=<GUID>>: <GUID=<GUID>>

      重要

      在 值中,不要省略冒号前后的空格。

    4. 选择“替换操作>”,然后选择 Enter。

      条目列表 ”框显示完整的命令。

    5. 选择“运行”。

      结果显示在 main Ldp 窗口中,应如下所示。

      调用修改...ldap_modify_s (ld,“ (null) ”,[1] attrs) ;修改了“”。

从多个全局编录服务器中删除大量挥之不去的对象

如果必须删除大量挥之不去的对象,则可以使用脚本比手动删除脚本更高效地删除它们。 若要生成此类脚本,请使用以下步骤:

  1. 创建一个新文件夹,并在该文件夹中创建具有以下名称的新文件:

    • Walkservers.cmd
    • Walkobjects.cmd
    • Modifyrootdse.vbs
    • Server-list.txt
    • Object-list.txt 文件
  2. 将以下文本粘贴到Walkservers.cmd:

    for /f %%j in (server-list.txt) do walkobjects %%j
    
  3. 将以下文本粘贴到Walkobjects.cmd:

    for /f "delims=@" %%i in (object-list.txt) do cscript //NoLogo MODIFYROOTDSE.VBS %1 "%%i" >>update-%1.log
    
  4. 将以下文本粘贴到 Modifyrootdse.vbs:

    '********************************************************************
    '*
    '* File: MODIFYROOTDSE.VBS
    '* Created: January 2002
    '* Version: 1.0
    '*
    '* Main Function: Writes Active Directory information to clean up
    '* objects as per: Q314282.
    '* Usage: Modifyrootdse.vbs <TargetServer> <GUID PAIR>
    '* Parameter are fed into the script using a pair of batch files.
    '*
    '* Copyright (C) 2002 Microsoft Corporation '*
    '********************************************************************
    OPTION EXPLICIT
    ON ERROR RESUME NEXT
    
    Dim objDomain
    Dim ObjValue, strServerName, adsLdapPath
    Dim i
    
    'Get the command-line arguments
    
    if Wscript.arguments.count <> 2 Then
        Print "Invalid Number of Parameters. Use with WalkServers.CMD and WalkObjects.CMD"
        WScript.quit
    End If
    
    strServerName = Wscript.arguments.item(0)
    ObjValue = Wscript.arguments.item(1)
    
    adsLdapPath = "LDAP://" & strServerName & "/RootDSE"
    
    Set objDomain = GetObject(adsLdapPath)
        If Err.Number <> 0 Then
        WScript.Echo "Error opening ROOTDSE. Error number is: " & Err.Number & ". Error description is: " & Err.Description & "."
        Set objDomain = Nothing
        WScript.quit
    End If
    
    objDomain.Put "RemoveLingeringObject", ObjValue
    objDomain.Setinfo
    
    If Err.Number = 0 Then
        WScript.Echo "Object " & ObjValue & " was removed."
    Else
        WScript.Echo "Object " & ObjValue & " could not be removed. Error number is: " & Err.Number & ". Error description is: " & Err.Description & "."
    End If
    
    WScript.Quit
    

    注意

    如果手动启动 Modifyrootdse.vbs,请确保将所有包含空格的参数括在引号中。

  5. 创建包含保留对象的全局编录服务器和 DC 的所有完全限定域名的列表,然后将该列表粘贴到 Server-list.txt。 使用完全限定的域名来避免 DNS 后缀搜索。

  6. 对于每个挥之不去的对象,请标识对象域中没有该 linging 对象副本的 DC。 通常,这是一个具有读取/写入命名上下文的 DC,在该上下文中手动删除了挥之不去的对象。 如本文其他部分所述,使用 RepAdmin 获取每个 DC 的 objectGUID 值。

  7. 在 Object-list.txt 中,使用以下格式创建 GUID 对列表:

    <GUID=dcGUID>: <GUID=objectGUID>

    注意

    在此值中, dcGUID 表示没有保留对象副本的 DC 的 GUID, 而 objectGUID 表示保留对象的 GUID。

    每对应如下所示:

    <GUID=<GUID>>: <GUID=<GUID>>

    重要

    在 值中,不要省略冒号前后的空格。

  8. 运行 Walk-servers.cmd 文件。

对于 Server-list.txt 中列出的每个 DC 或全局编录服务器,脚本将生成名为 Update-server-name.log 的日志文件。 每个日志文件包含要删除的每个对象的一行。

由于每个列出的服务器上都不存在挥之不去的对象,因此日志文件中的错误不一定表示存在问题。 但是,窗体 操作的错误消息被拒绝操作错误 指示 GUID 或值的语法存在问题。 如果发生这些错误,请验证以下事项:

  • 确保 DC GUID 是域控制器的正确 GUID,这些控制器包含包含 对象的域的读/写命名上下文。

  • 确保对象 GUID 标识 (全局编录服务器或 RODC) 只读命名上下文中的挥之不去的对象。

运行Walkservers.cmd修改环境中许多挥之不去的对象时出错

对象 <GUID=<GUID>>:<无法删除 GUID=<GUID>>。 错误编号为:-2147016672。 错误说明为:。

此错误的原因

如果脚本针对 DC 的 GUID 运行,该 DC 不包含与包含 linging 对象的命名上下文对应的读/写命名上下文,则会发生此错误。 通过 Ldp.exe 工具验证挥之对象的位置。

示例

在以下示例中,要删除的 linging 对象位于 corp.company.local 域中。 但是,<Objects-list.txt 文件中的 GUID=<GUID>> 条目与驻留在 company.local 域中的 DC 相关联。 此 DC 没有 corp.company.local 域的读/写命名上下文。

以下搜索会生成多个对象,这些对象表示同一用户 (Joe) ,并列出其 objectGUID 值。

ldap_search_s (ld, “DC=company,DC=local”, 2, “ (cn=User*) ”, attrList, 0, &msg) 结果 <0>: (null)
匹配的 DN:
获取 4 个条目:
>> Dn:CN=User,Joe,OU=Exec,OU=企业用户,DC=corp,DC=company,DC=local
1> canonicalName:corp.company.local/Corporate Users/Exec/User、Joe;
1> cn: User, Joe; 1> description: CEO;
1> displayName: User, Joe; 1> distinguishedName: CN=User, Joe,OU=Exec,OU=Corporate Users,DC=corp,DC=company,DC=local; 4> objectClass: top; person; organizationalPerson; user;
1> objectGUID: <GUID>; 1> name: User, Joe;
>> Dn: CN=User, Joe,OU=Migration,DC=corp,DC=company,DC=local 1> canonicalName: corp.company.local/Migration/User, Joe;
1> cn: User, Joe;
1> description: Disabled Account; 1> displayName: User, Joe; 1> distinguishedName: CN=User, Joe,OU=Migration,DC=corp,DC=company,DC=local;
4> objectClass:top;person;organizationalPerson;user;
1> objectGUID: <GUID>;
1> 名称:User、Joe;

在此示例中,假设 corp.company.local 域中有一个名为 CORP-DC-01 的 DC。 运行 命令 repadmin /showreps CORP-DC-01 将生成 objectGUID<GUID>。 此 GUID 替换 Objects-list.txt 文件中的上一个 GUID。 此挥之不去对象的条目现在如下所示:

<GUID=<GUID>> : <GUID=<GUID>>

第一个 GUID 是 corp.company.local 域中域控制器的 GUID。 第二个 GUID 是挥之不去对象的 GUID。 此更改后,Walk-servers.cmd脚本将成功运行。

删除环境中挥之不去的对象时出现错误消息 87

如果发现对象实际上未出现在托管命名上下文的所有 DC 上,但 repadmin /removelingeringobjects 未删除它们,则可能会出现此错误。 当中心 DC 复制它使用全局编录服务器创建的新对象,但在其自己的域中使用读/写副本 (replica) DC 时,就会出现这种情况。

此错误仅在两种情况下返回:

  • 对象存在于引用 DC 上。
  • 与当前 TSL 值相比,对象太年轻 () 无法挥之不去。

对于第二种情况的示例,请考虑具有以下元数据的全局编录服务器:

Loc.USN 源自 DC Org.USN Org.Time/Date Ver 属性
======= =============== ========= ============= === =========
143543261 d20f71f3-6147-4f80-a0c2-470541ef09e6 104742409 <DateTime> objectClass
RW-副本 (replica) 的最新向量:d20f71f3-6147-4f80-a0c2-470541ef09e6 @ USN 104583382 @ Time <DateTime>
GC 的最新向量:d20f71f3-6147-4f80-a0c2-470541ef09e6 @ USN 104762881 @ Time <DateTime>

在这种情况下,DC 在其自己的域中使用 DC 进行复制后创建对象开始失败,但仍使用其他域中的全局编录服务器进行复制。

若要解决此问题,请让这些对象成为实际挥之不去的对象, (超出 TSL) ,然后使用本文中的脚本将其删除。 若要确保数据继续复制,请在林中的所有 DC 上设置 “允许复制与发散伙伴和损坏伙伴 复制”。

如果使用这些方法无法解决日志文件中的错误,则可能遇到其他问题。 请联系 Microsoft 产品支持服务获取其他帮助。

数据收集

如果需要 Microsoft 支持方面的帮助,建议按照 使用 TSS 收集 Active Directory 复制问题的信息中所述的步骤收集信息。