Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Когда нужно массово переустановить ОС на компьютерах в корпоративной сети, мы привыкли использовать System Center Configuration Manager (SCCM) и все хорошо, если речь идёт про Windows, но с Linux немного все сложнее, т.к. нет готовых инструментов в SCCM.
К счастью, SCCM удобный и гибкий инструмент, чтобы решить любую задачу по переустановке ОС. Если у вас инсталляция SCCM не распределённая, где все ПК находятся в одной сети, то вам подойдёт вот эта статья для установки ОС Linux с сетевой папки.
Если у вас распределённая инсталляция SCCM, где много Distribution Point в отдалённых локациях (с «небыстрыми» каналами связи), а установку нужно проводить на 100 ПК одновременно, то с сетевой папки сделать это сложно. Именно эту задачу нам понадобилось решить, попутно улучшив и автоматизировав способ, описанный выше (идея взята из упомянутой статьи и доработана, спасибо fisher51 и моим коллегам, кто помогал).
Итак, приступим.
Создаём виртуалку с минимальным диском, это важно, т.к. от размера будет зависеть размер итогового образа (для Xubuntu достаточно 9Gb). Устанавливаем Xubuntu (для примера), выбирая стандартное разделение дисков:
Как видно на скриншоте, у нас один диск 9Gb со стандартной разбивкой, где /dev/sda1 – загрузочная партиция (FAT32), /dev/sda2 – логический диск, /dev/sda5 – партиция самого Linux (ext4).
Далее настраиваете операционную систему, как вам нужно, например, в корпоративной среде можно сразу прописать настройки прокси (PAC файл), временную зону и т.д.
Образ можно снять либо на подключённый дополнительный диск, либо подключить сетевой. В последнем случае нам понадобится ещё она компонента:
apt install cifs-utils
Мы помним, что диск у нас уменьшен для минимизации размера образа, но после его разворачивания на обычных компьютерах, где диск более 9Gb, нам нужно его автоматически расширить без привлечения администратора. Также в виде автоматизации можно сделать ввод в домен при запуске системы, либо запуск любых других скриптов, но этот вопрос подробно рассматривать не буду, оставлю для специалистов.
Итак, делаем автоматизацию расширения диска при первом запуске системы.
Создаём/изменяем в директории /etc файл rc.local - это конфиг службы rc-local, которая будет запускаться при запуске системы и стартовать наш/и скрипт/ы.
sudo nano /etc/rc.local
Листинг rc.local
#!/bin/sh -e
exec /usr/sbin/res1.sh
exit 0
где: #!/bin/sh -e - запуск консоли, exec /usr/sbin/res1.sh – запуск скрипта res1.sh
Через команду exec сюда можно дописывать и другие скрипты, главное не забывать их отсюда удалять, иначе они будут запускаться при каждом запуске (хотя это тоже полезно, но не в моем случае).
Делаем этот файл исполняемым chmod +x /etc/rc.local
Создаём в директории /usr/sbin/ файл, называем, например, res1.sh
sudo nano /usr/sbin/res1.sh
Листинг res1.sh
echo -e "resizepart\n2\nYes\n100%\nresizepart\n5\nYes\n100%\nquit" | parted /dev/sda ---pretend-input-tty
echo 1 > /sys/block/sda/device/rescan
resize2fs /dev/sda5
sed -i '/res1.sh/d' /etc/rc.local
rm -f /usr/sbin/res1.sh
reboot
где:
1 строчка – передаём через конвейерный input команду для утилиты parted выполняем resizepart 2 на 100% диска и resizepart 5 на 100% , т.е. раздвигаем логическую и основную партицию linux до 100% диска
2 строчка – делает обновление информации о диске
3 строчка – расширяется файловая до конца диска
4 строчка – удаление строчки запуска скрипта из службы rc.local
5 строчка – удаление скрипта res1.sh
6 строчка – перезагрузка
Делаем этот файл исполняемым: chmod +x /usr/sbin/res1.sh
Я буду снимать образ на сетевой диск, следовательно, подключим его:
mkdir /mnt/image
mount.cifs //имя_сервера/имя_сетевой_папки /mnt/image -o user=имя_пользователя,pass=пароль
Теперь запустим снятие образа на добавленную сетевую папку.
dd if=/dev/sda of=/mnt/image/sda.dd.img bs=8M
где:
if- указываем с какого диска снимаем копию
of – указываем куда копируем образ
bs- размер блока чтения 8Мб
В итоге на сетевой папке у нас лежит образ sda.dd.img размером 9Gb, сжимаем его архиватором 7z, в Zip-файл sda.dd.zip (при выборе максимального сжатия у меня файл получился 2.14 Gb, при минимальном быстром сжатии 2.22 Gb что в целом очень хорошо).
Далее создаём сетевую папку, доступную по всей сети компании, с правами подключения под определённым аккаунтом. В папку выкладываем скрипт SetupLinux.ps1, который будет запускать в Task Sequence с определёнными параметрами.
[CmdletBinding()]
Param(
[Parameter( Mandatory = $true, Position = 0 )]
[ValidateSet( 'ShowProgressLinuxInstall', 'StartShowProgressLinuxInstall', 'CreatePartition', 'SetVariable', 'ShowProgressLinuxDownload', 'StartShowProgressLinuxDownload' )]
[String]$Worktype
)
function Main ( $Worktype ) {
switch ( $Worktype ) {
'CreatePartition' {
$HardDisk = Get-Disk -Number 0
$HardDiskSize = $HardDisk.Size
if ($HardDiskSize -lt 20Gb) {
Write-Host "Small disk, Exit" , $HardDiskSize
Exit 1
}
Get-Disk -Number 0 | Where-Object PartitionStyle -EQ 'RAW' | Initialize-Disk
Write-Host "Initialize Disk complete"
#Start-Sleep -Seconds 5
Get-Disk -Number 0 | Clear-Disk -RemoveData -RemoveOEM -Confirm:$false
Write-Host "Clear Disk complete"
#Start-Sleep -Seconds 5
Get-Disk -Number 0 | Where-Object PartitionStyle -EQ 'RAW' | Initialize-Disk
#Start-Sleep -Seconds 5
Write-Host "Initialize Disk complete"
$Offset = $HardDiskSize-5Gb-10Mb
$NewPartition = Get-Disk -Number 0 | New-Partition -Size 5Gb -Offset $Offset -DriveLetter C
#Start-Sleep -Seconds 5
Write-Host "Create Partition complete"
Format-Volume -FileSystem NTFS -Force -Partition $NewPartition
#Start-Sleep -Seconds 5
Write-Host "Format Partition Disk complete"
}
'StartShowProgressLinuxInstall' {
Start-Process -WindowStyle Hidden -FilePath "powershell.exe" -ArgumentList "-WindowStyle Hidden -NoProfile -nologo -ExecutionPolicy Bypass -File T:\SetupLinux.ps1 -Worktype ShowProgressLinuxInstall"
Exit
}
'ShowProgressLinuxInstall' {
$TsProgressUI = New-Object -ComObject Microsoft.SMS.TsProgressUI
$TotalProgressCount = (Get-Item C:\_SMSTaskSequence\Packages\MVI00424\sda.dd.zip).Length
$CountAttempts = 10
while ($CountAttempts -gt 0) {
Start-Sleep -Seconds 5
$CountAttempts = $CountAttempts - 1
while (Get-WmiObject -Class win32_process -Filter {name = '7z.exe'}) {
$ProgressCount = (Get-WmiObject -Class win32_process -Filter {name = '7z.exe'}).ReadTransferCount
$Procent = $ProgressCount / $TotalProgressCount * 100
$TsProgressUI.ShowTSProgress("","","","Linux Install ($([math]::Round($Procent))% complete)",$Procent,100)
Start-Sleep -Seconds 5
}
}
}
'StartShowProgressLinuxDownload' {
Start-Process -WindowStyle Hidden -FilePath "powershell.exe" -ArgumentList "-WindowStyle Hidden -NoProfile -nologo -ExecutionPolicy Bypass -File T:\SetupLinux.ps1 -Worktype ShowProgressLinuxDownload"
Exit
}
'ShowProgressLinuxDownload' {
$TsProgressUI = New-Object -ComObject Microsoft.SMS.TsProgressUI
$CountAttempts = 10
while ($CountAttempts -gt 0) {
Start-Sleep -Seconds 5
$CountAttempts = $CountAttempts - 1
while (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}) {
$ProgressCount = (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}).ReadTransferCount
$TotalProgressCount = (Get-WmiObject -Class win32_process -Filter {name = 'OSDDownloadContent.exe'}).WriteTransferCount
if ($ProgressCount -gt 1048576) {
$Procent = $ProgressCount / $TotalProgressCount * 100
$TsProgressUI.ShowTSProgress("","","","Download Linux Package ($([math]::Round($Procent))% complete)",$Procent,100)
}
Start-Sleep -Seconds 5
}
}
}
'SetVariable' {
Get-Disk -Number 0 | Update-Disk
Get-Disk -Number 0 | Get-Partition | Where-Object -FilterScript {$_.Type -eq "FAT32"} | Set-Partition -NewDriveLetter C
$TSEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment
$config = [PSCustomObject]@{
OSDComputerName = $TSEnvironment.Value("OSDComputerName")
IN_DOMAIN = $TSEnvironment.Value("IN_DOMAIN")
}
Out-File -FilePath C:\config.json -InputObject ($config | ConvertTo-Json) -Encoding utf8
}
}
}
. Main $Worktype
Далее переходим в SCCM и создаём пакет.
В пакете у нас должны быть:
7z.dll , 7z.exe - программа 7z, чтобы распаковать архив (достаточно этих файлов)
ddrelease64.exe – утилита DD под Windows, берем отсюда, там есть 32- и 64-битная версия (я использую 64-битную, т.к. у меня boot образ x64)
sda.dd.zip – собственно сам файл архива.
install.cmd – пакетный файл установки.
Листинг install.cmd:
@echo off
cd C:_SMSTaskSequence\Packages\XXX00424
7z.exe e -so sda.dd.zip | ddrelease64.exe of=\?\Device\Harddisk0\Partition0 bs=8M
где:
XXX00424 – код текущего пакета, из которого производится запуск
с 3 строчкой поясню, распаковываем через 7z в консоль (параметр -so) файл sda.dd.zip далее передаём поток утилите ddrelease64.exe и сразу записываем его на диск \\?\Device\Harddisk0\Partition0 блоком 8Mb
Далее пакет распространяем на Distribution Point’ы.
Теперь создадим загрузочный Task Sequence
Выбираем Create a new custom task sequence, нажимаем далее.
Выбираем 64-битный загрузочный образ, нажимаем далее.
Добавляем шаг 1: перезагрузка, если при запуске задания введён неправильный пароль (защита от «дурака»)
Добавляем шаг 2: подключаем сетевую папку, доступную под определённым аккаунтом по всей сети, в которой лежит скрипт SetupLinux.ps1 (описанный выше).
Добавляем шаг 3: запуск PowerShell скрипта с параметром -WorkType CreatePartition для инициализации, очистки диска и создания временной NTFS партиции для загрузки образа.
Добавляем шаг 4: запуск PowerShell скрипта с параметром -WorkType StartShowProgressLinuxDownload для отображения прогресса скачки образа.
Добавляем шаг 5: скачивание пакета SCCM на созданный временный диск NTFS
Добавляем шаг 6: запуск PowerShell скрипта с параметром -WorkType StartShowProgressLinuxInstall для отображения прогресса установки образа.
Добавляем шаг 7: запуск командного файла install.cmd из скачанного на временный диск пакета SCCM.
Добавляем шаг 8: запуск PowerShell скрипта с параметром -WorkType SetVariable, в этом шаге на диске, куда уже записали Linux, находим загрузочный диск с FAT32 для сохранения JSON файла с параметрами Task Sequence. Через него можно передать переменные имя компьютера OSDComputerName, нужно ли вводить ПК Linux в домен IN_DOMAIN, либо любые другие параметры. На эту партицию также можно положить любые скрипты, которые вы хотите запустить при запуске ОС Linux.
Далее добавляем Deployment для Task Sequence, указываем необходимые переменные.
Далее загружаемся по сети PXE и наслаждаемся установкой Linux из SCCM за 5-7 мин.
В итоге получилась заливка ОС Linux и партиция раздвинута до конца диска 40gb.
Чтобы убедится, что мы передали файл конфига из SCCM в Linux, подключим временно партицию /dev/sda1, командой mount /dev/sda1 /mnt/cm
Параметры, переданные через JSON из Task Sequence
Вот и все, наслаждаемся работой Linux в корпоративной сети.
Удачи вам в ваших экспериментах.