Search
Write a publication
Pull to refresh

Chocolatey + PowerShell: как развернуть софт на 100 ПК за час

Level of difficultyEasy
Reading time7 min
Views4.5K

Представьте: ваша организация закупила 100 новых компьютеров, на каждый из которых нужно установить десяток различных программ (текстовые редакторы, браузеры, средства коммуникации, разработки и тд.). Ручная установка займёт огромное количество времени, а ошибки и человеческий фактор удвоят затраченное время вдвое.

Но есть способ лучше - автоматизация через Chocolatey и PowerShell. В этой статье разберём:

  1. Как развернуть ПО на всех машинах за кратчайший срок;

  2. Как создать собственные пакеты и управлять ими;

  3. Как внедрить данное решение в вашу организацию.

Если вы системный администратор, DevOps, ИТ-инженер или специалист ТП - постараюсь помочь сэкономить вам десятки часов рутинной работы.

Автоматизация установки ПО в корпоративной сети

Итак, основная проблема. Недавно моя организация закупила партию из 100 новых машин, которые требуют установку набора ПО в зависимости от отдела (бухгалтерия, юристы и тд.). Решать задачу вручную слишком долго, поэтому я выбрал Chocolatey для экономии времени, о котором уже был наслышан от коллеги.

Подводные камни:

  • Корпоративная сеть закрыта, поэтому нет доступа к официальному репозиторию Chocolatey.

  • Загрузка пакетов с мировой паутины запрещена политикой безопасности.

Исходя из этого, решение напрашивается само: развёртывание локального репозитория Chocolatey. Далее постараюсь расписать процесс максимально подробно. Приступим:

Подготовка инфраструктуры

Для реализации потребуется:

  1. Локальный сервер или общая сетевая папка для хранения пакетов.

  2. PowerShell 5+ с правами администратора.

  3. Пакеты .nupkg (в моём случае - собранные вручную).

Варианты локального репозитория:

  1. NuGet.Server - самый простой вариант для Windows.

  2. Nexus Repository - гибкое решение для больших сетей.

  3. Общая сетевая папка - быстрый и простой вариант, но со своими минусами.

В качестве итогового решения выбрал сетевую папку. Причины очень просты, оно не требует дополнительных серверных компонентов, которыми на данный момент я не располагаю. К минусам же могу отнести:

  • Низкая производительность при массовой установке (поэтому я буду устанавливать ПО, разбив установку на группы по 20-25 машин).

  • Отсутствие контроля версий как в полноценных репозиториях.

Начнем с установки Chocolatey в закрытой корпоративной сети. Для начала нам нужно скачать установочный файл (chocolatey.2.4.3.nupkg) с официального сайта Chocolatey. Далее выполняем перечень команд:

# Переходим в папку с .nupkg
cd "C:\Users\Admin\Desktop"

# Распоковываем .nupkg как архив 
Rename-Item -Path "chocolatey.2.4.3.nupkg" -NewName "chocolatey.2.4.3.zip"
Expand-Archive -Path "chocolatey.2.4.3.zip" -DestinationPath "C:\ChocoInstall" -Force

# Запускаем установку
Set-ExecutionPolicy Bypass -Scope Process -Force 
& "C:\ChocoInstall\tools\chocolateyInstall.ps1"

# Проверяем корректность установки
choco --version 

Создание собственного пакета для распространения

Перед созданием пакета потребуется:

  • Установленный Chocolatey на машине разработчика;

  • Доступ к установочным файлам в сетевой папке;

  • Права администратора на машине, где создаём пакет;

  • Текстовый редактор для изменения файлов пакета (VS Code, Notepad++, Блокнот).

Если все требования соблюдены - приступим к созданию:

  • Генерируем нашу заготовку .nuspec:

choco new buh

Команда создаст шаблон в папке buh (данный пакет мы направим на машины бухгалтеров):

Пример созданного командой шаблона
Пример созданного командой шаблона
  • Редактируем buh.nuspec в текстовом редакторе:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
  <metadata>
    <id>buh-software</id>
    <version>1.0.0</version>
    <title>ПО для бухгалтерии</title>
    <authors>Ваша организация</authors>
    <description>Пакет стандартного ПО для отдела бухгалтерии</description>
    <tags>бухгалтерия 1с контур office</tags>
  </metadata>
  <files>
    <file src="tools\**" target="tools\" />
  </files>
</package>
  • Редактируем chocolateyinstall.ps1:

# Политика обработки ошибок: выполняет остановку скрипта при любой ошибке
$ErrorActionPreference = 'Stop' 

# Параметры установки
$installers = @(
    @{ Name = '1C'; Path = "\\IT\software\buh\1C\setup.exe"; Args = "/S"; Shortcut = "C:\Program Files\1C\1CEStart.exe" },
    @{ Name = 'KonturExtern'; Path = "\\IT\software\buh\KonturExtern\install.msi"; Args = "/i `"$($_.Path)`" /qn"; Process = "msiexec.exe" },
    @{ Name = 'BankClient'; Path = "\\IT\software\buh\BankClient\setup.exe"; Args = "/S" },
    @{ Name = 'Office'; Path = "\\IT\software\buh\Office\setup.exe"; Args = "/configure configuration.xml" }
)

# Установка всех программ
foreach ($app in $installers) {
    try {
        $process = Start-Process -FilePath ($app.Process ?? $app.Path) -ArgumentList $app.Args -Wait -PassThru
        if ($process.ExitCode -ne 0) { throw "Exit code $($process.ExitCode)" }
        Write-Host "$($app.Name) установлен успешно" -ForegroundColor Green
    }
    catch {
        Write-Warning "Ошибка установки $($app.Name): $_"
    }
}

# Создание ярлыка (у меня только для 1С по просьбе бухгалтерии)
if (Test-Path $installers[0].Shortcut) {
    $WshShell = New-Object -ComObject WScript.Shell
    $Shortcut = $WshShell.CreateShortcut("$env:Public\Desktop\1C Предприятие.lnk")
    $Shortcut.TargetPath = $installers[0].Shortcut
    $Shortcut.Save()
}
  1. Собираем готовый пакет:

choco pack

Возможно потребуется использование:

cd C:\Users\Admin\Desktop\buh # После выполнения команды повторяем 'choco pack'

Наш пакет в расширении .nupkg готов, копируем в сетевую папку и проверяем работоспособность пакета на тестовой машине:

choco install buh-software -y --source="';\\IT\Software\choco'" --force

Возможные проблемы и их решения

В процессе внедрения автоматической установки пакетов в корпоративной среде я столкнулся с рядом нюансов, которые могут помешать развёртыванию. Далее перечислю самые распространённые проблемы и способы их обхода:

Ошибки доступа к общей папке: скрипт выдаёт ошибку "Access denied" или "Network path not found".

  • Необходимо проверить права УЗ, с которой выполняется скрипт. У неё должны быть права на чтение/запись;

  • Возможно потребуется добавить исключение в брандмауэр:

New-NetFirewallRUle -DisplayName "Allow SMB for Chocolatey" -Direction Inbound -Protocol TCP -LocalPort 445 -Action Allow

Долгая установка на некоторых машинах: логи показывают таймаут или скрипт вовсе зависает на отдельных машинах.

  1. Сократить список до 15-20 машин (пример с разбивкой указан ниже);

  2. Добавить -ThrottleLimit 10 в Invoke-Command чтобы ограничить параллельные сессии.

Развёртывание ПО на машинах

После подготовки пакетов необходимо развернуть ПО на всех машинах. Для себя выбрал установку через PowerShell Remoting, но есть и альтернативный вариант через GPO.

Альтернативный вариант через GPO
  1. Создание нового GPO;

  2. Настройка задания (обязательно установить галку на "run with higest privileges");

  3. Добавить триггер "at startup" (или по расписанию, если вам удобнее);

  4. Действия:

  • Действие: start a program

  • Программа: powershell.exe

  • Аргументы:

-NoProfile -ExecutionPolicy Bypass -Command "choco install buh-software -y --source='\IT\Software\choco' --cache-location='C:\Windows\Temp\choco'"
  1. Доп. параметры:

  • Включаем опцию "run task as soon as possible after a scheduled start is missed"

  • Устанавливаем "stop the task if it runs longer than" 2 часа

В примере установка только на 23 машины бухгалтеров. Для развёртывания на все машины разом (без разделения на отделы) можно использовать разбивку на группы (по 20 единиц):

$groups = $computers | Select-Object -First 100 | Select-Object -Skip 0 -First 20

Использовать для развёртывания будем скрипт:

# Импорт из .csv + фильтр для бухов
$computers = Import-Csv -Path "C:\IT\Deployment\computers.csv" | 
             Where-Object { $_.Department -eq "Бухгалтерия" } | 
             Select-Object -ExpandProperty ComputerName

# Проверяем компьютеры
if (-not $computers) {
    Write-Warning "Не найдено компьютеров отдела Бухгалтерия в CSV файле"
    exit
}

# Путь к ZIP-архиву с Chocolatey на сетевой шаре
$chocoZipPath = "\\IT\Software\choco\chocolatey.zip"
# Временный каталог для распаковки на машинах
$tempChocoPath = "C:\Temp\ChocolateyInstall"

foreach ($computer in $computers) {
    try {
        # Проверяем доступность машины
        if (-not (Test-Connection -ComputerName $computer -Count 1 -Quiet -ErrorAction SilentlyContinue)) {
            Write-Warning "$computer недоступен"
            Add-Content -Path "C:\IT\Deployment\failed.txt" -Value "$computer - недоступен по сети"
            continue
        }

        # Устанавливаем Chocolatey из архива
        $session = $null
        try {
            # Создаем сессию
            $session = New-PSSession -ComputerName $computer -ErrorAction Stop
            
            Invoke-Command -Session $session -ScriptBlock {
                param($zipPath, $installPath)
                
                # Создаем временный каталог
                if (-not (Test-Path $installPath)) {
                    New-Item -ItemType Directory -Path $installPath -Force | Out-Null
                }
                
                # Копируем архив на целевую машину
                $localZipPath = Join-Path $env:TEMP "chocolatey.zip"
                Copy-Item -Path $zipPath -Destination $localZipPath -Force
                
                # Распаковываем архив
                try {
                    Add-Type -AssemblyName System.IO.Compression.FileSystem
                    [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipPath, $installPath)
                } catch {
                    Write-Warning "Ошибка распаковки Chocolatey: $_"
                    throw
                }
                
                # Добавляем путь к Chocolatey в переменную PATH
                $chocoBinPath = Join-Path $installPath "tools"
                $envPath = [Environment]::GetEnvironmentVariable("PATH", "Machine")
                if (-not $envPath.Contains($chocoBinPath)) {
                    [Environment]::SetEnvironmentVariable(
                        "PATH", 
                        "$envPath;$chocoBinPath", 
                        "Machine"
                    )
                    $env:PATH += ";$chocoBinPath"
                }
                
                # Устанавливаем переменную окружения ChocolateyInstall
                [Environment]::SetEnvironmentVariable(
                    "ChocolateyInstall", 
                    $installPath, 
                    "Machine"
                )
                
                # Добавляем локальный репозиторий
                Start-Sleep -Seconds 5 # Даем время для инициализации
                &amp; choco source add -n="LocalRepo" -s="\\IT\Software\choco" --priority=1 -ErrorAction Stop
                
                # Устанавливаем пакет
                &amp; choco install buh-software -y --source=LocalRepo --force -ErrorAction Stop
                
                # Очищаем временные файлы
                Remove-Item $localZipPath -Force -ErrorAction SilentlyContinue
                
            } -ArgumentList $chocoZipPath, $tempChocoPath -ErrorAction Stop

            Write-Host "$computer : установка завершена успешно" -ForegroundColor Green
        } catch {
            Write-Warning "Ошибка на $computer : $_"
            Add-Content -Path "C:\IT\Deployment\failed.txt" -Value "$computer - ошибка установки: $_"
        } finally {
            if ($session) { Remove-PSSession -Session $session }
        }
    }
    catch {
        Write-Warning "Ошибка при обработке $computer : $_"
        Add-Content -Path "C:\IT\Deployment\failed.txt" -Value "$computer - ошибка обработки: $_"
    }
}

После успешного развёртывания ПО на всех машинах удалось достичь следующего:

  1. Временные показатели:

    • Ручная установка занимает ~40 минут на машину × 100 = ~66 часов;

    • Установка с помощью Chocolatey: ~10 часов (с подготовкой и созданием 5 пакетов для разных отделов);

    • Экономия: 56 часов рабочего времени.

  2. Масштабируемость:

    • Данное решение готово к развёртыванию на новых машинах/обновлению ПО на старых;

    • Процесс установки новых версий ПО упрощён в разы.

Итог

  1. Решение, описанное в статье, позволяет развёртывать и создавать собственные пакеты ПО для разных нужд и отделов на множестве корпоративных компьютеров с минимальными затратами труда.

  2. Данный подход не является совершенным, что было описано в начале статьи. Опыт показал, что решение хоть и легко масштабируется, но является не самым быстрым. Для себя решил, что обязательно буду рассматривать внедрение Nexus Repository или его аналогов.


В заключение, если у вас остались какие-то вопросы - буду рад помочь, обсудить. Если метод несовершенен - обязательно пишите комментарии, всё прочитаю, изучу, исправлю. Надеюсь, что моё решение натолкнёт вас на интересные мысли или поможет по аналогии автоматизировать работу в своей организации! Внедряйте, автоматизируйте, пусть рутина останется позади!

P.S. Я запустил свою группу в Телеграмм, буду рад видеть всех, кому интересен процесс написания скриптов и автоматизация в мире IT.

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+4
Comments14

Articles