前两周有个 EPM 实施项目,客户是在厦门那边,我本以为过去一周内可以解决回来,没想到在操作系统部署这块踩了超多坑,最后待了两周才解决,这里记录一下
# 无 DHCP 服务器
上来面对的第一个坑就是客户端环境中没有 DHCP
服务器,所有的客户端都需要手动配置 IP 地址
正常情况下,操作系统部署是通过 PXE
网络引导加载 WinPE
, 然后在 WinPE
中跟服务器建立通信,读取服务器上的部署模板信息
在没有 DHCP
的情况下根本无法从网络中加载 WinPE
, 那就只能在服务器上生成 WinPE
的 ISO 镜像,通过刻录软件将其刻录到 U 盘,然后用 U 盘引导进入 WinPE
环境
# 修改 boot.wim 文件
在创建 WinPE
镜像之前,我们需要挂载 WinPE
文件,添加中文字体,让其支持中文显示,否则部署模板中的中文会显示乱码,并且修改 startnet.cmd
文件,让 WinPE
初始化的时候可以手动配置 IP 地址
WinPE
文件默认路径为 C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot
下的 boot.wim
和 boot_x64.wim
, 其中 boot.wim
为 32 位 BIOS
引导文件, boot_x64.wim
为 UEFI
64 位引导文件
我们先修改第一个 boot.wim
文件,以管理员权限打开 cmd
命令行
- 创建一个空目录用于挂载 WIM 文件
mkdir c:\mount |
- 挂载 boot.wim 到 c:\mount 目录
DISM.exe /mount-wim /wimfile:"C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot\boot.wim" /index:1 /mountdir:C:\mount |
- 修改 WinPE 初始化脚本
编辑 C:\mount\Windows\System32\startnet.cmd
脚本文件,在 @echo off 后面插入静态 IP 配置命令
echo. | |
echo If using static ip,press 1 | |
echo If using DHCP,press 2 | |
echo If exit,press 3 | |
echo. | |
set /p choice= your choice: | |
echo. | |
if "%choice%"=="1" goto ip1 | |
if "%choice%"=="2" goto ip2 | |
if "%choice%"=="3" goto end | |
goto end | |
:ip1 | |
netsh interface show interface | |
echo. | |
set /p name= please enter your NIC name: | |
set /p ldip= please enter your static ip address: | |
set /p ldmask= please enter your netmask: | |
set /p ldgw= please enter your gateway: | |
echo. | |
echo IP config starting.... | |
echo. | |
echo starting config ip and gateway | |
netsh interface ip set address name=%name% source=static addr=%ldip% mask=%ldmask% gateway=%ldgw% | |
echo config success! | |
goto end | |
:ip2 | |
echo IP auto config start.... | |
echo. | |
netsh interface ip set address name = %name% source = dhcp | |
echo starting DNS.... | |
netsh interface ip set dns name = %name% source = dhcp | |
echo config success! | |
:end |
- 添加 hosts 文件解析
为了减少用户的操作,上面的启动脚本我没有添加配置 DNS 的命令,而是直接将 EPM 服务器的解析记录添加到 WinPE
的 hosts
文件进行解析
用 notepad
打开 C:\mount\Windows\System32\drivers\etc\hosts
添加服务器解析记录
- 添加中文包
WinPE
默认是不支持中文的,如果部署模板中有中文字符会变成乱码,根据当前 WinPE
的版本下载对应的 ADK
安装到电脑中,执行下面的命令添加中文语言包
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-FontSupport-ZH-CN.cab" | |
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\zh-cn\lp.cab" | |
Dism.exe /image:C:\mount /Get-Intl | |
Dism.exe /image:C:\mount /Set-UILang:ZH-CN | |
Dism.exe /image:C:\mount /Set-AllIntl:ZH-CN |
- 保存镜像
完成上面的步骤后,关闭任何已打开的镜像相关文件包括目录,否则保存时会无法完全卸载挂载目录
Dism.exe /unmount-Wim /MountDir:c:\mount /Commit |
卸载后重复上面的 2 - 6 的操作,将第 2 歩的挂载镜像改成 boot_x64, 第 5 步的中文包路径又 x86 改成 amd64
DISM.exe /mount-wim /wimfile:"C:\Program Files\LANDesk\ManagementSuite\LANDesk\vboot\boot_x64.wim" /index:1 /mountdir:C:\mount | |
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs\WinPE-FontSupport-ZH-CN.cab" | |
DISM.exe /Add-Package /Image:C:\mount /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\amd64\WinPE_OCs\zh-cn\lp.cab" |
# 生成 ISO 镜像
修改好 WinPE
文件后,返回控制台,在操作系统部署这里创建一个镜像文件
创建好后用刻录软件将镜像文件写入到优盘,我这里为了方便演示就直接用虚拟机光驱加载镜像模拟优盘启动,测试该镜像是否能够在没有 DHCP
的环境下正常工作
开机进入引导菜单,选择 WinPE
的启动设备
进入初始化界面,选择 1
使用静态 IP,这里会列出所有网卡接口的信息,由用户输入对应的网卡接口名称进行配置
配置好 IP 地址信号后回车,如果网络能够正常跟服务器通信,此时便能看到部署程序
这里弹出需要身份认证,后续可以取消掉,先输入核心服务器的管理员账号密码登录
登录后弹出部署模板选择,但是目前我并没有配置部署模板,所以这里没有模板
目前看来 WinPE
跟核心服务器通信是正常的,我们先返回核心服务器配置部署模板
# 模板部署
在控制台操作系统部署界面选择 Preboot > PXE Boot Options
, 勾选上 Allow anonymous login for public templates
, 这样下次我们在 WinPE
进入模板选择的界面就不需要身份认证了
需要注意的是,需要将部署模板创建在 Public 分组才能让匿名用户查看并选择部署
- 由于用户希望部署时能够自动分配计算机名,这里需要添加设备名称规则,使用 LD+Mac 地址 确保设备名称的唯一性
- 编写分区脚本,由于用户目前还有 Windows 7 系统,所以需要写一个 GPT 分区脚本和一个 MBR 分区脚本
- GPT
rem == CreatePartitions-UEFI == | |
rem == These commands are used with DiskPart to | |
rem create five partitions | |
rem for a UEFI/GPT-based PC. | |
rem Adjust the partition sizes to fill the drive | |
rem as necessary. == | |
select disk 0 | |
clean | |
convert gpt | |
rem == 1. Windows RE tools partition =============== | |
rem create partition primary size=900 | |
rem format quick fs=ntfs label="Windows RE tools" | |
rem assign letter="T" | |
rem set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac" | |
rem gpt attributes=0x8000000000000001 | |
rem == 2. System partition ========================= | |
create partition efi size=260 | |
rem NOTE: For Advanced Format 4Kn drives, | |
rem change this value to size = 260 | |
format quick fs=fat32 label="System" | |
assign letter="S" | |
rem == 3. Microsoft Reserved (MSR) partition ======= | |
create partition msr size=128 | |
rem == 4. Windows partition ======================== | |
rem == a. Create the Windows partition size=102407(100GB) ========== | |
create partition primary size=102407 | |
rem == c. Prepare the Windows partition ========= | |
format quick fs=ntfs label="Windows" | |
assign letter="C" | |
rem === 5. User data partition ================ | |
create partition primary size=210000 | |
rem Use all remaining space to create user data partition=== | |
format quick fs=ntfs label="Data" | |
assign letter="D" | |
rem === 5. User document partition ================ | |
create partition primary | |
rem Use all remaining space to create user data partition=== | |
format quick fs=ntfs label="Document" | |
assign letter="E" | |
list volume | |
exit |
- MBR
select disk 0 | |
clean | |
convert mbr | |
create partition primary size=100000 | |
format fs=ntfs quick label="Windows" | |
assign letter="C" | |
create partition primary size=200000 | |
format fs=ntfs quick label="Data" | |
assign letter="D" | |
create partition primary | |
format fs=ntfs quick label="Document" | |
assign letter="E" | |
list volume | |
exit |
- 将相关脚本、镜像、部署工具、软件包放到共享目录
- 创建部署模板
- 开始测试
客户端开机进入 WinPE 环境
a. 选择部署模板
b. 部署执行阶段
c. 部署完成
安装完操作系统后重启会自动执行后续动作
# 问题总结
- DHCPless
第一次接触无 DHCP
的环境,刚开始毫无思绪,因为之前客户操作系统部署都是通过网络 PXE
引导部署,我知道可以通过控制台生成 ISO 镜像刻录到优盘,由优盘启动可以不需要 PXE
和 DHCP
,但是我们的 WinPE
不像网络上的第三方 WinPE
那样具备有图形化界面,所以我不知道在进入 PE 环境后如何给当前系统配置一个 IP 地址
后来问了群里的一些大佬,得知 WinPE 进入系统后默认执行 c:\windows\system32\startnet.cmd 进行初始化,可以通过修改这个脚本预先配置好 IP 信息,最终通过添加 netsh
命令解决这个问题
- 磁盘分区
一开始我用系统自带的分区模板进行分区测试,发现不是很好用,在创建第二个分区的时候很容易报错,我对自带的分区模板一些字段定义也不是了解,在官网也找不到相关的文档可以用于参考
最终决定用 diskpart
命令进行分区
- Win7 UEFI 引导
这个是最让我最奔溃的问题,用户主要的用的操作系统是 Win7
, 但是他们购买的新机器不支持 Legacy
引导,只能以 UEFI
方式引导,硬件上已经完全不支持 Win7
了
我尝试过从网上下载很多标题注明支持新机器的 Win7 镜像,并且自己也尝试封装了几个镜像,但是都有着各种各样的问题
- a. 安装完操作系统重启后不认盘
- b. 安装完操作系统重启后一直卡在 Windows Logo
- c. 安装完操作系统后进入登录界面,键盘鼠标无法使用
- d. 能够正常安装系统并进入到桌面,但是在安装完软件后执行 sysprep 进行二次封装,再部署又会出现卡 logo 的现象
最终为了进度,我只能跟用户商量如果新机器要安装 Win7
,就不能用 EPM
的部署方式,可以用网络上第三方 WinPE
系统进行安装,因为第三方 WinPE
可以解决 Win7
卡 Logo
这个问题
- 多硬盘如何区分系统盘
这个问题最终也没有办法完美解决,多硬盘的情况下,比较理想的是判断分区中是否存在 Windows 目录,如果有则认为是系统盘
但是实际上会有很多其它的情况,下面列出我当前已经遇到的情况:
- a. 用户之前的电脑是单硬盘,并且存在系统,后面加装了一个硬盘,但是前面的系统盘并没有格式化,就会出现一个以上分区存在 Windows 目录
- b. 系统盘损坏或被格式化,所有分区下都找不到 Windows 目录
- c. 后续新增硬盘,以新硬盘为系统盘,一般情况下新硬盘可能连格式化的步骤都没有做,连分区都没有,根本无法识别
最主要的是 WinPE
只支持少部分的 cmd
命令,不支持 Powershell
, 所以真的很难用 cmd 脚本去做判断,只能说即使有想法也很难仅靠 cmd
命令实现
最终是给出两个部署模板,由用户自行选择
-
一个是新硬盘部署,重新格式化并分区分配盘符,将操作系统安装在 C 盘
-
一个是重装系统,重装系统分为 GPT 和 MBR 两个模板,固定第 0 个磁盘为系统盘,GPT 分区下格式化第三个分区,并分配 C 驱动器号,MBR 分区下格式化第一个分区,并分配 C 驱动器号
最后再吐槽一下,操作系统部署的实施真的很折磨人,本来整个部署流程顺利跑下来都需要一个多小时,遇到问题就得修改后重新跑一遍,我虽然没有统计自己跑了多少遍部署流程,但是肯定不少于 50 次
在测 Win7 的时候真的感觉人要奔溃,我大部分的时间都浪费在这上面,当时真的很希望能够有个人可以一起分析研究这个问题
哎,就酱吧,无力吐槽
# 最后更新
八月底又去了一趟客户现场,主要是上次六月份部署完后客户一直没有使用,现在基本上已经忘记了如何使用,而且客户对目前的操作系统部署方案也不是很满意,尤其是硬盘分区这一块,我本次过去就是重新教他们使用并尽可能的优化部署方案
# 磁盘分区
分区的问题我之前是用脚本去执行的,脚本执行就无法避免可能会分错区造成数据丢失,上一次过来的时候因为被 Win7 UEFI 引导的问题搞得我没法静下心来思考其它的事情,我也不知道当初为什么死磕脚本来完成这个分区动作
这次过来,我已经明白靠脚本是无法满足用户的需求,这种情况只能用图形化的分区工具让用户自行选择磁盘进行分区
我在服务器下载了 DiskGenius 并解压放到共享目录,在 PE 映射服务器的共享目录,执行 DiskGenius 可以正常跑起来,这样分区的问题就解决了
不管用户有几个磁盘和分区,我只要求用户将需要安装操作系统的分区分配 C 盘符即可
现在回过头想想上次过来为什么会没有想到用图形化工具分区,真的被自己蠢哭了,看来人一着急就容易钻牛角尖
# 系统配置模板不生效
安装完操作系统第一次开机登录系统界面,连上网络后会自动执行系统配置后面的步骤,但是如果设备无法自动连接到网络,并且客户长时间没有操作导致设备进入休眠状态,唤醒后系统配置模板可能不会工作
正常情况下,在部署模板执行完 Configure Taget OS 便会自动重启 WinPE,进入操作系统安装配置步骤,要知道系统配置模板为什么不生效,就需要知道 Configure Taget OS 这一步具体做了什么事情
按照官方文档对 CTOS 的描述,执行 CTOS 步骤后会将后续需要的文件复制到客户端的 C:\ldprovisioning 目录,并在 %WINDIR%\Setup\Scripts\SetupComplete.cmd 脚本中调用 %WINDIR%\ldprovisioning\ldprovisioning.cmd, 下面简单描述一下 SetupComplete.cmd 和 ldprovisioning.cmd 这两个 CMD 批处理文件
# SetupComplete.cmd
SetupComplete.cmd 是 Windows 操作系统安装结束后,用户登录到桌面的时候立即启动,该脚本以 system 权限执行
- 执行顺序如下:
-
安装完 Windows 操作系统后,在显示登录屏幕显示之前,系统会在 %WINDIR%\Setup\Scripts 目录中搜索 SetupComplete.cmd
-
如果找到 SetupComplete.cmd 文件便会执行,并将执行操作记录在 %WINDIR%\Windows\Panther\UnattendGC\Setupact.log
-
设备在安装过程中加域,为了确保域策略不会干预脚本运行,在完成 SetupComplete.cmd 之前,域策略不会应用到于计算机
# ldprovisioning.cmd
前面的 SetupComplete.cmd 脚本调用 ldprovisioning.cmd 后 , ldprovisioning.cmd 会安装基本的 Ivanti CBA 代理服务并启动
启动代理服务后,客户端调用 C:\ldprovision\ldprovision.exe 程序向核心服务器报告 CTOS 步骤执行成功,接着继续执行后续部署模板
# 处理方法
知道 CTOS 的动作后事情便简单多了,已知 SetupComplete.cmd 在登录桌面时调用 ldprovisioning.cmd ,此时如果网络不通,则安装 Ivanti CBA 代理失败,客户端无法向服务器报告 CTOS 的状态,服务器的部署模板历史记录会一直停留在 CTOS ,另外, ldprovisioning.cmd 执行后会删除 C:\ldprovision 目录,这样用户就无法继续执行 ldprovisioning.cmd 安装 Ivanti CBA 代理
处理方案:
将客户端的 C:\ldprovision 目录文件拷贝到共享服务器,在系统安装模板中将共享服务器上的 ldprovision 目录复制到客户端上(不能放在系统盘根目录哦)
这样后续无论是什么原因导致系统配置模板没有生效,用户都可以在联网状态下,手动将 ldprovision 目录复制到 %systemdrive% 根目录下执行 ldprovisioning.cmd 继续后面的部署模板
# 其它问题
还有其它一些小问题也一并帮用户优化了,例如修改系统启动等待时间、关闭 UAC、激活 Windows、驱动安装等,这里就不一一列举了,最终的部署效果用户还是很满意的
经过本次的项目实施,自己也收获了许多系统部署的经验,EPM 操作系统部署这块后续不会再更新了
✿✿ヽ (°▽°) ノ✿✿