通过制作 OEM 定制 ISO ,可将所需的预装软件、需预先执行的安装脚本等内容添加到安装镜像中,实现非 OEM 定制版镜像安装后手动配置安装的效果。特别适用于对预装软件有一定要求的批量安装场景,从而节省时间和方便搭建系统环境,可直接交付项目所用的定制母盘。

一、工具准备

1.1 环境准备

如需进行 OEM 定制,需满足以下硬件条件:

CPU:Intel Pentium 4,主频 2.0 GHz以上(或同等级别 CPU)

内存:4G 或以上

硬盘:120G 以上 HDD 或 SSD ,可用空间大于 10G

同时,还需要满足以下软件环境:

操作系统:UOS 20 SP1及以上版本

1.2 工具安装

首先,执行以下命令,将系统更新到最新版本:

sudo apt update && sudo apt full-upgrade

接着,执行以下命令,安装一些必要的依赖工具:

sudo apt install xorriso isolinux

最后,为了确保 OEM 定制工具的依赖关系都已满足,可执行以下命令补全未安装的依赖包:

sudo apt -f install

二、OEM 定制

2.1 解压标准版 ISO 镜像

首先,需要把标准版 ISO 镜像解压出来,以便对镜像内容进行修改:

7z x /path/to/iso -oiso-extract

iso-extract表示 ISO 的解压目录,必须位于当前工作目录。

然后,进入 ISO 解压目录,删除一个不必要的文件夹:

cd iso-extract
rm -r '[BOOT]'

最后,创建一些必要的目录,供后续 OEM 定制使用。

mkdir -p oem/hooks/{before,in,after}_chroot

准备工作到此结束。

2.2 基于 OEM 文件夹定制

对于一些基本的用户需求,可以通过 ISO 中的 oem 文件来实现定制,下面将目前可实现的 OEM 定制内容分开进行介绍。后续的脚本和配置文件内容需根据实际情况修改。

注意:如果在同一阶段(before_chroot、in_chroot和after_chroot)使用了多个自定义.job脚本,需要避免脚本文件名的前缀序号重复,且序号会体现执行顺序。序号越大,执行顺序越靠后。因此,脚本之间的依赖关系需要提前梳理好。

2.2.1 分区大小及策略

在全盘安装的情况下,可对安装程序自动划分的 EFI、boot 和根分区进行分区大小定制。要定制这些分区的大小,需要在oem/settings.ini配置文件中进行如下配置:

# 设置boot分区大小,以MiB为单位
partition_default_boot_space = 1536

# 设置EFI分区大小,以MiB为单位
partition_default_efi_space = 300

# 设置根分区大小
partition_full_disk_root_partition_usage = 30Gib

如果需要调整全盘安装的分区策略,需要在oem/full_disk_policy.json中进行设置,具体内容如下:

[ {
          "filesystem": "ext4",
          "mountPoint": "/boot",
          "label": "Boot",
          "usage": "1536Mib",
          "alignStart": true,
          "device": "",
          "platform": [ "loongson" , "x86", "arm"]
   },
   {
          "filesystem": "ext4",
          "mountPoint": "/boot",
          "label": "Boot",
          "usage": "3072Mib",
          "alignStart": true,
          "device": "",
          "platform": [ "sw" ]
   },
   {
          "filesystem": "linux-swap",
          "mountPoint": "swap",
          "label": "SWAP",
          "usage": "swap-size",
          "alignStart": false,
          "device": "",
          "platform": [ "x86", "sw", "loongson", "arm" ]
   },
   {
          "filesystem": "recovery",
          "mountPoint": "/recovery",
          "label": "Backup",
          "usage": "backup-size",
          "alignStart": false,
          "device": "",
          "platform": [ "x86", "sw", "loongson", "arm" ]
   },
   {
          "filesystem": "ext4",
          "mountPoint": "/",
          "label": "Roota",
          "usage": "root-size",
          "alignStart": true,
          "device": "",
          "platform": [ "x86", "sw", "loongson", "arm" ]
   },
   {
          "filesystem": "ext4",
          "mountPoint": "",
          "label": "Rootb",
          "usage": "root-size",
          "alignStart": true,
          "device": "",
          "platform": [ "x86", "sw", "loongson", "arm" ]
   },
   {
          "filesystem": "ext4",
          "mountPoint": "/data",
   },

其中一些关键字段的说明如下:
     
filesystem:指定分区所用的文件系统,除了Linux原生的文件系统,也支持 ntfs;
   
  mountPoint:分区挂载点,可自行新增分区,指定其挂载位置,或调整默认分区的挂载位置;
       
label:可指定分区的卷标,支持中文显示(系统盘卷标目前是写死的,不支持修改);
       
usage:分区大小,如果在此处指定了具体的大小,就不需要在oem/settings.ini里面进行重复设置。如果设置为100%,则表示使用硬盘全部剩余空间来创建分区。usage为100%的分区只能有一个;
       
alignStart:指定是否从硬盘开始位置开始分区,一般保持默认即可。

2.2.2 无人值守

如果需要实现自动化无人值守安装,需要在需要在oem/settings.ini配置文件中进行如下应答配置:

DI_LAYOUT=us
DI_PXE_INSTALL=true
DI_TIMEZONE=Asia/Shanghai
DI_UEFI=false
#双硬盘下指定sda为系统盘,sdb为数据盘
DI_FULLDISK_MULTIDISK_DEVICE="/dev/sda;/dev/sdb"
#是否全盘安装,影响备份还原功能
DI_FULLDISK_MODE=true
# 启用自动分区
partition_do_auto_part=true
# 大容量硬盘的根分区大小范围,以GiB为单位
partition_full_disk_large_root_part_range=20:60
# 设置默认安装组件
select_component_default_install_type=Environment
# 设置默认语言
select_language_default_locale=zh_CN
# 设置是否将用户密码应用于root密码
set_root_password_from_user=false
# 跳过网络配置页面
skip_network_page=true
# 跳过分区页面
skip_partition_page=true
# 跳过系统修复页面
skip_repair_system_page=true
# 跳过组件选择页面
skip_select_component_page=true
# 跳过语言选择页面
skip_select_language_page=true
# 跳过首次启动时的语言选择页面
skip_select_language_page_on_first_boot=true
# 不跳过系统信息页面(1020版开始必须设置为false,否则将无法自动创建设置好的用户)
skip_system_info_page=false
# 跳过系统键盘布局页面
skip_system_keyboard_page=true
# 跳过时区选择页面
skip_timezone_page=true
# 设置默认时区
timezone_default=Asia/Shanghai
# 跳过虚拟机检测提醒
skip_virtual_machine_page=true
# 是否打开审核模式,默认不打开
system_check_mode=false
# 设置默认主机名
system_info_default_hostname="uos-PC"
# 设置主机名后缀
system_info_hostname_auto_suffix=-PC
# 设置保留主机名
system_info_hostname_reserved=localhost
# 设置默认键盘布局
system_info_default_keyboard_layout=us
# 设置默认用户名
system_info_default_username="uos"
# 设置默认密码
system_info_default_password="uos123"
# 安装完毕重启后进行系统设置
system_info_setup_after_reboot=true
2.2.3 默认打开开发者模式

如果需要在系统安装完毕后默认打开开发者模式,可创建oem/hooks/in_chroot/99_enable_developer_mode.job文件,并进行如下配置:

#!/bin/bash
[ -d /var/lib/deepin/developer-mode ] || mkdir -pv /var/lib/deepin/developer-mode
echo -n -E 1 > /var/lib/deepin/developer-mode/enabled
2.2.4 关闭系统自动更新

如果需要在系统安装完毕后默认关闭系统的自动更新,可创建oem/hooks/in_chroot/99_disable_autoupdate.job文件,并进行如下配置:

#!/bin/bash
mkdir -p /var/lib/lastore
if [ -d /var/lib/lastore ];then
<span style="white-space:pre">        </span>cp ${OEM_DIR}/config.json /var/lib/lastore/
fi

同时,需要在 oem 目录存放一份 config.json 配置文件,具体内容如下:

{"Version":"0.1","AutoCheckUpdates":false,"DisableUpdateMetadata":false,"AutoDownloadUpdates":false,"AutoClean":false,"MirrorSource":"default","UpdateNotify":false,"CheckInterval":604800000000000,"CleanInterval":604800000000000,"CleanIntervalCacheOverLimit":86400000000000,"AppstoreRegion":"","LastCheckTime":"2020-09-04T13:16:23.794140531+08:00","LastCleanTime":"2020-09-04T21:25:17.32844793+08:00","LastCheckCacheSizeTime":"2020-09-04T21:25:17.32858307+08:00","Repository":"desktop","MirrorsUrl":"http://packages.deepin.com/mirrors/community.json"}
2.2.5 预装字体

如果需要将字体集成到系统中,首先需要将字体文件放到 oem 目录,然后创建oem/hooks/in_chroot/99_install_fonts.job文件,并进行如下配置(注意字体文件扩展名大小写):

#!/bin/bash
if [ -d /usr/share/fonts ];then
        mkdir /usr/share/fonts/oem
        cp ${OEM_DIR}/*.{ttf,ttc,otf} /usr/share/fonts/oem/
        cd /usr/share/fonts/oem
        mkfontscale
        mkfontdir
        fc-cache
fi
2.2.6 预装软件

如果需要将第三方软件集成到系统中,需要创建oem/deb目录,将需要集成的 deb 包及其依赖包放到此目录中,无需额外操作。

注意:

1、所有 deb 包都必须带有 UOS 签名且必须满足依赖关系,否则将会安装失败或安装后无法使用。

2、deb 包将按照包文件名的字母顺序依次安装,如果需要调整安装顺序,直接修改文件名,如添加数字前缀即可。

2.2.7 设置默认壁纸

如果需要设置系统的默认壁纸,首先需要将.jpg格式的壁纸文件放到 oem 目录,然后创建oem/hooks/in_chroot/99_set_background.job文件,并进行如下配置(壁纸文件名以background.jpg为例):

#!/bin/bash
if [ -d /usr/share/wallpapers ];then
        install -Dm644 ${OEM_DIR}/background.jpg 
fi
2.2.8 设置用户默认头像

如果需要设置用户的默认头像,首先需要准备80x80和200x200两种尺寸的.png格式头像图片,放到 oem 目录,两种尺寸的头像图片分别以user_80.pnguser_200.png为例,然后创建oem/hooks/in_chroot/99_set_avatar.job文件,并进行如下配置:

#!/bin/bash
if [ -d /var/lib/AccountsService/icons ];then
        rm /var/lib/AccountsService/icons/*.png
        rm /var/lib/AccountsService/icons/bigger/*.png
        install -Dm644 ${OEM_DIR}/user_80.png /var/lib/AccountsService/icons/1.png
        install -Dm644 ${OEM_DIR}/user_200.png 
fi
2.2.9 设置桌面应用图标

如果用户希望系统安装完成后,桌面上就有一些预装应用的图标,可以创建oem/hooks/in_chroot/99_set_desktop_launcher.job文件,并进行如下配置(以帮助手册和 UOS 浏览器的图标为例):

#!/bin/bash
DESK_APPS_ARR=('deepin-manual' 'uos-browser')
for DESK_APP_ITEM in ${DESK_APPS_ARR[@]}; do
if [ -f /usr/share/applications/${DESK_APP_ITEM}.desktop ]; then
            install -v -Dm644 /usr/share/applications/${DESK_APP_ITEM}.desktop /etc/skel/Desktop/
fi
done
2.2.10 默认关闭窗口特效

如果需要默认关闭窗口特效(如龙芯 3A3000 等配置较低的笔记本电脑),可以创建oem/hooks/in_chroot/99_disable_composite.job文件,并进行如下配置:

#!/bin/bash
if [ -f /etc/xdg/kwinrc ];then
       install -v -Dm644 ${OEM_DIR}/kwinrc /etc/xdg/
fi

同时,需要在 oem 目录存放一份kwinrc配置文件,具体内容如下:

[Plugins]
#默认使用com.deepin.blur
blurEnabled=false
enforcedecoEnabled=false
minimizeallEnabled=true
kwin4_effect_dialogparentEnabled=false
kwin4_effect_translucencyEnabled=false
kwin4_effect_windowapertureEnabled=false
#窗口打开和隐藏时的淡入淡出效果
kwin4_effect_fadeEnabled=false
#登录时淡入的效果
kwin4_effect_loginEnabled=false
#在Tool窗口或者通知窗口出现时的交叉淡入淡出的动画
kwin4_effect_morphingpopupsEnabled=false
#Popup类型窗口的展开动画
slidingpopupsEnabled=false

[Desktops]
Name_2=工作区 2
Number=2
Rows=1

[org.kde.kdecoration2]
BorderSize=Normal
ButtonsOnLeft=
ButtonsOnRight=HIAX
library=com.deepin.chameleon
theme=

[Effect-FlipSwitch]
TabBox=false
TabBoxAlternative=false

[Effect-CoverSwitch]
TabBox=false
TabBoxAlternative=false

[TabBox]
ActivitiesMode=1
ApplicationsMode=0
DesktopMode=1
HighlightWindows=true
LayoutName=thumbnail_grid
MinimizedMode=0
MultiScreenMode=0
ShowDesktopMode=1
ShowTabBox=true
SwitchingMode=0
BorderActivate=9
BorderAlternativeActivate=9

[Effect-Cube]
BorderActivate=9
BorderActivateCylinder=9
BorderActivateSphere=9

[Effect-DesktopGrid]
BorderActivate=9

[Effect-PresentWindows]
BorderActivate=9
BorderActivateAll=9
BorderActivateClass=9

[ElectricBorders]
Bottom=None
BottomLeft=None
BottomRight=None
Left=None
Right=None
Top=None
TopLeft=None
TopRight=None

[Compositing]
#窗口最小化后也保持map状态
HiddenPreviews=6
#动画速度调整为快
AnimationSpeed=2
Enabled=false

[Windows]
#设置焦点检测策略为最低级,防止由于kwin在窗口获取焦点时比较的严格的检查而导致的窗口无法获取到焦点
FocusStealingPreventionLevel=0
#禁止在inactive时自动隐藏Utilty类型的窗口,如Qt::Tool/Qt::Drawer类型的Qt窗口
#将导致窗口flags为
#Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint | Qt::Drawer | Qt::WindowStaysOnTopHint
#的窗口无法同时显示多个
HideUtilityWindowsForInactive=false

[MouseBindings]
#禁用Alt+鼠标左键移动窗口
CommandAll1=Nothing
#禁用Alt+鼠标中键改变窗口层叠顺序的功能
CommandAll2=Nothing
#禁用Alt+鼠标右键绑定的改变窗口大小的功能
CommandAll3=Nothing
2.2.11 跳过安装成功提示页面

如需跳过安装完成后的提示页面,希望自动重启,可以创建oem/hooks/after_chroot/99_after_finish.job文件,并进行如下配置:

#!/bin/bash
sync && sleep 5 && sync && sleep 5
echo 'b' > /proc/sysrq-trigger

如果希望安装后自动关机,将脚本中的echo 'b'替换为echo 'o'即可。

注意:此脚本的执行顺序必须晚于所有其他脚本。

2.2.12 在文件管理器中隐藏分区

如果需要在文件管理器中隐藏某些分区,可以创建oem/hooks/in_chroot/99_hide_part.job文件,并进行如下配置:

#!/bin/bash
if [ -d /lib/udev/rules.d ];then
     install -D -m644 ${OEM_DIR}/99-hidepart.rules /lib/udev/rules.d/
fi

同时在 oem 目录中创建99-hidepart.rules文件,进行以下设置:

KERNEL=="sdb1",ENV{UDISKS_IGNORE}="1"

其中sdb1需替换为具体需要隐藏的分区名。

2.3 基于 Live 文件系统定制

基于 OEM 文件夹的定制方式已经可以满足大部分的常用需求场景,而基于 Live 文件系统的定制方式除了可以满足 3.2.3 开始的需求之外,还可以进行对标准版系统本身进行精简,删除不必要的软件。

2.3.1 解压 Live 文件系统

首先需要把live/filesystem.squashfs解压出来,例如解压到/mnt,以便进行后续操作:

unsquashfs -f -d /mnt live/filesystem.squashfs
2.3.2 chroot 进入解压后的 Live 文件系统

解压完成后,首先需要挂载一些虚拟文件系统,然后chroot进入解压后的 Live 文件系统:

mount --bind /dev /mnt/dev
mount --bind /dev/pts /mnt/dev/pts
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt /bin/bash

接着就可以参照 3.2.3-3.2.14 章节的内容,进行相关定制工作。

定制内容完成后,需退出chroot环境,并将文件系统重新封装:

umount /proc
umount /sys
umount /dev/pts
umount /dev
exit
mksquashfs /mnt filesystem.squashfs

然后将封装完成的新文件系统复制到live文件夹,覆盖原来的文件系统。

三、生成新的定制版ISO镜像

定制工作全部完成后,在上一级目录生成新的定制版 ISO 镜像,命名为uos-new.iso。也可替换为其他名称,注意不要遗漏命令最后的点“.”。

x86 架构:

xorriso -as mkisofs -no-pad -joliet-long -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin -c isolinux/boot.cat -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -eltorito-alt-boot -e boot/efi.img -no-emul-boot -append_partition 2 0x01 boot/efi.img -isohybrid-gpt-basdat -isohybrid-apm-hfsplus -appid "UOS 20" -publisher "UOS <http://www.uniontech.com>" -V "UOS 20" -o ../uos-new.iso .

ARM64 架构:

xorriso -as mkisofs -r -J -R -joliet-long -c boot.cat -boot-load-size 4 -boot-info-table -eltorito-alt-boot --efi-boot boot/grub/efi.img -no-emul-boot -file_name_limit 250 -appid "UOS 20" -publisher "UOS <http://www.uniontech.com>" -V "UOS 20" -o ../uos-new.iso .

MIPS64 架构:

xorriso -as mkisofs -V "UOS 20" -R -r -J -joliet-long -l -cache-inodes -appid "UOS 20" -publisher "UOS <http://www.uniontech.com>" -V "UOS 20" -o ../uos-new.iso .