/
gitVerseVVG
/
OfflineInstaller
Обзор
Документация
Войти
/
gitVerseVVG
/
OfflineInstaller
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/OfflineInstaller.lpr
288 строк
11 KB
gitVerseVVG
create: OfflineInstaller.lpi, OfflineInstaller.lpr, OfflineInstaller.lps, resources_create.sh, Factorial5, app_install.sh, rabbitmq_install.sh, postgresql_install.sh, redis_install.sh, read.me
05 май 2026, 10:14
Верифицирован
05 май 2026, 10:14
d2040ca
Код
Авторство
О чём код?
program OfflineInstaller; {$mode objfpc}{$H+} {$R installer_resources.res} // Подключение ресурсов uses Classes, SysUtils, StrUtils, Process, FileUtil; const VRSN = 'v08'; MIN_FREE_SPACE_MB = 2048; // Минимально необходимое место: 2 ГБ TEMP_DIR = '/tmp/offline_installer'; var _slPckgs: TStringList; ////////// // Проверка свободного места на диске function CheckFreeSpace(const Path: string): Boolean; var Proc: TProcess; Output: TStringList; FreeSpaceStr,sTmp: string; FreeSpaceMB: Int64; i: Integer; begin Result := False; Proc := TProcess.Create(nil); Output := TStringList.Create; try Proc.Executable := 'df'; Proc.Parameters.Add('-BM'); Proc.Parameters.Add(Path); Proc.Options := [poUsePipes, poWaitOnExit]; Proc.Execute; Output.LoadFromStream(Proc.Output); if Output.Count > 1 then begin FreeSpaceStr := ''; sTmp := ExtractWord(4, Output[1], [' ']); for i:=1 to Length(sTmp) do begin // Проверка, что символ находится в диапазоне '0'..'9' if (sTmp[i] >= '0') and (sTmp[i] <= '9') then FreeSpaceStr+=sTmp[i]; end; if TryStrToInt64(FreeSpaceStr, FreeSpaceMB) then begin if FreeSpaceMB >= MIN_FREE_SPACE_MB then begin WriteLn('Свободное место: ', FreeSpaceMB, ' МБ (достаточно)'); Result := True; end else WriteLn('Недостаточно места: требуется ', MIN_FREE_SPACE_MB, ' МБ, доступно ', FreeSpaceMB, ' МБ'); end else WriteLn('Ошибка: не удалось определить свободное место'); end; finally Output.Free; Proc.Free; end; end; // function CheckFreeSpace(..): Boolean; ////////// // Извлечение ресурса в файл function ExtractResourceToFile(const ResName: string; const OutputFileName: string): Boolean; var ResStream: TResourceStream; FileStream: TFileStream; begin Result := False; try // Открываем поток к ресурсу ResStream := TResourceStream.Create(HInstance, ResName, RT_RCDATA); try // Создаём файл для записи FileStream := TFileStream.Create(OutputFileName, fmCreate); try // Копируем данные из ресурса в файл FileStream.CopyFrom(ResStream, 0); if('CNFG_PACKAGE'<>ResName) then WriteLn('Ресурс ', ResName, ' успешно извлечён в ', OutputFileName); Result := True; finally FileStream.Free; end; finally ResStream.Free; end; except on E: Exception do begin WriteLn('Ошибка извлечения ресурса ', ResName, ': ', E.Message); end; end; end; // function ExtractResourceToFile(..): Boolean; ////////// // Распаковка архива в целевую директорию procedure ExtractPackage(const ArchivePath, TargetDir: string); var Proc: TProcess; begin WriteLn('Распаковка ', ExtractFileName(ArchivePath), ' в ', TargetDir, '...'); Proc := TProcess.Create(nil); try Proc.Executable := 'tar'; Proc.Parameters.Add('-xzf'); Proc.Parameters.Add(ArchivePath); Proc.Parameters.Add('-C'); Proc.Parameters.Add(TargetDir); Proc.Options := [poUsePipes, poWaitOnExit]; Proc.Execute; if Proc.ExitCode <> 0 then begin WriteLn('Ошибка распаковки ', ArchivePath); Halt(1); end else WriteLn('Успешно распаковано: ', ExtractFileName(ArchivePath)); finally Proc.Free; end; end; // procedure ExtractPackage(..); ////////// // Выполнение системной команды function ExecuteCommand(const Command: string; var Output: TStringList): Boolean; var Proc: TProcess; OutputString: string; Buffer: array[0..1023] of char; BytesRead: Integer; begin Result := False; if Output = nil then Output := TStringList.Create else Output.Clear; Proc := TProcess.Create(nil); try // Настройка процесса Proc.Executable := '/bin/sh'; Proc.Parameters.Add('-c'); Proc.Parameters.Add(Command); // Настройка для захвата вывода Proc.Options := [poUsePipes, poStderrToOutPut]; // Запуск команды Proc.Execute; // Чтение вывода из pipe OutputString := ''; while Proc.Running do begin // Проверяем, есть ли данные для чтения if Proc.Output.NumBytesAvailable > 0 then begin BytesRead := Proc.Output.Read(Buffer[0], 1024); OutputString := OutputString + Copy(Buffer, 0, BytesRead); end else Sleep(10); // Небольшая пауза, чтобы не нагружать процессор end; // Читаем оставшиеся данные после завершения процесса repeat BytesRead := Proc.Output.Read(Buffer[0], 1024); if BytesRead > 0 then OutputString := OutputString + Copy(Buffer, 0, BytesRead); until BytesRead <= 0; // Записываем результат в TStringList Output.Text := OutputString; Result := True; finally Proc.Free; end; end; // function ExecuteCommand(..): Boolean; ////////// // Общая функция по установке отдельного ПО procedure doInstallSoftware(const sSwNm,sPckgNm: String); var sOutputFile,sTargetDir,sShFile,sLogFile: String; Command: string; OutputList: TStringList; i: Integer; OutputFile: Text; begin WriteLn('*** Установка '+sSwNm+'...'); sOutputFile:= TEMP_DIR + '/'+sSwNm+'.tar.gz'; sTargetDir:= TEMP_DIR + '/'+sSwNm; sShFile:= '/'+sSwNm+'_install.sh'; sLogFile:= sSwNm+'_install.log'; // Создаём временную директорию if not DirectoryExists(TEMP_DIR) then ForceDirectories(TEMP_DIR); if not DirectoryExists(sTargetDir) then ForceDirectories(sTargetDir); // Извлекаем ресурс if ExtractResourceToFile(sPckgNm, sOutputFile) then begin ExtractPackage(sOutputFile, TEMP_DIR); // Распаковываем архив if DeleteFile(sOutputFile) then WriteLn('Успешно удален файл: '+sOutputFile) else WriteLn('Ошибка даления файла: '+sOutputFile); if RenameFile(sTargetDir+sShFile, TEMP_DIR+sShFile) then begin WriteLn('Успешно перемещен файл: "'+sShFile+'"'); Command:=TEMP_DIR+sShFile; OutputList := TStringList.Create; try if ExecuteCommand(Command, OutputList) then begin for i := 0 to OutputList.Count - 1 do WriteLn(OutputList[i]); // Вывод в консоль // Сохранение в файл AssignFile(OutputFile, sLogFile); Rewrite(OutputFile); // Запись заголовка в файл WriteLn(OutputFile, 'Команда: ', Command); WriteLn(OutputFile, 'Дата/время: ', DateTimeToStr(Now)); WriteLn(OutputFile, StringOfChar('-', 50)); // Запись содержимого в файл for i := 0 to OutputList.Count - 1 do WriteLn(OutputFile, OutputList[i]); CloseFile(OutputFile); WriteLn; WriteLn('Результат сохранен в файл "'+sLogFile+'"'); WriteLn('Всего строк: ', OutputList.Count); end // if ExecuteCommand(Command, OutputList) else begin WriteLn('Ошибка при выполнении команды: '+Command); end; // else: if ExecuteCommand(Command, OutputList) finally OutputList.Free; end; end // if RenameFile(TARGET_DIR+SH_FILE, TEMP_DIR+SH_FILE) else begin WriteLn('Ошибка перемещения файла: "'+sShFile+'". Установка прервана.'); Halt(1); end; // else: if RenameFile(TARGET_DIR+SH_FILE, TEMP_DIR+SH_FILE) end // if ExtractResourceToFile(sPckgNm, sOutputFile) else begin WriteLn('Не удалось извлечь ресурс '+sPckgNm+'. Установка прервана.'); Halt(1); end; // else: if ExtractResourceToFile(sPckgNm, sOutputFile) end; // procedure doInstallSoftware(..); ////////// procedure ShowUsage; var i: Integer; begin WriteLn('Использование: ', ExtractFileName(ParamStr(0))); for i:=0 to _slPckgs.Count-1 do WriteLn(format(' -%s',[LowerCase(_slPckgs[i].Substring(0,Pos('_',_slPckgs[i])-1))])); WriteLn('Пример: ', ExtractFileName(ParamStr(0)), ' -soft1 -soft2'); end; // procedure ShowUsage; ////////// function checkPrm(const sPrm: String): Boolean; var i: Integer; bRslt: Boolean = False; begin for i:=0 to _slPckgs.Count-1 do if _slPckgs[i]=UpperCase(sPrm.Substring(1))+'_PACKAGE' then bRslt:= True; Result:=bRslt; end; // function checkPrm(..): Boolean; ////////// const CNFG_FILE = '/tmp/OfflineInstaller.cnfg'; var i: Integer; begin WriteLn(format('*** %s (%s)',[ApplicationName,VRSN])); // Проверка свободного места if not CheckFreeSpace('/') then begin WriteLn('Установка прервана из‑за недостатка места.'); Halt(1); end; // Извлекаем ресурс if ExtractResourceToFile('CNFG_PACKAGE', CNFG_FILE) then begin _slPckgs:= TStringList.Create; try _slPckgs.LoadFromFile(CNFG_FILE); // Загрузка текста из файла if False=DeleteFile(CNFG_FILE) then Writeln('Не удалось удалить файл: '+CNFG_FILE); // Обработка аргументов if ParamCount = 0 then begin ShowUsage; _slPckgs.Free; // Освобождение памяти Halt(0); end; // if ParamCount = 0 for i := 1 to ParamCount do begin if checkPrm(ParamStr(i)) then begin doInstallSoftware(ParamStr(i).Substring(1),UpperCase(ParamStr(i).Substring(1))+'_PACKAGE'); end // if checkPrm(ParamStr(i)) else begin WriteLn('Неизвестный параметр: ', ParamStr(i)); end; // else: if checkPrm(ParamStr(i)) end; // for i := 1 to ParamCount do finally _slPckgs.Free; // Освобождение памяти после работы с объектом end; end // if ExtractResourceToFile(..) else begin WriteLn('Не удалось извлечь ресурс "CNFG_PACKAGE". Установка прервана.'); Halt(3); end; // else: if ExtractResourceToFile(..) end.