Bangun Penginstal Aplikasi Web Python Termasuk Apache, Django, dan PostgreSQL untuk Windows





Kiriman ini adalah kelanjutan dari bagian pertama artikel di Habré , di mana ia dijelaskan secara rinci tentang menyebarkan tumpukan Django pada MS Windows. Selanjutnya, kami akan memberikan petunjuk langkah demi langkah untuk membuat penginstal yang akan mengotomatiskan proses penginstalan tumpukan di komputer lain tanpa perlu bekerja di baris perintah, membuat mesin virtual, dll., Di mana seluruh urutan tindakan akan dikurangi menjadi tindakan Berikutnya -> Berikutnya -> Selesai.



Jadi apa yang harus dilakukan penginstal:



  1. Buka paket semua program dan komponen yang diperlukan ke dalam direktori yang ditentukan oleh pengguna.
  2. Lakukan pemeriksaan pra-instalasi.
  3. Daftarkan interpreter Python di registri Windows.
  4. Instal, jika belum diinstal, pustaka ketergantungan perangkat lunak.
  5. Buat layanan Apache dan PostgreSQL, lalu mulai.
  6. Nilai tambah tambahannya adalah pembuatan otomatis program uninstaller yang akan menghapus tumpukan yang diinstal jika pengguna menginginkannya.


Di antara opsi yang memungkinkan untuk penginstal, kami akan memilih penginstal gratis Inno Setup, karena ini memungkinkan Anda melakukan semua hal di atas, memungkinkan Anda membuat installer tanpa harus menjalankan banyak skrip. Dibandingkan dengan Wix, sintaks file setup adalah format ini, yang lebih mudah dibaca dan diubah daripada xml. Saat ini ia bersaing dengan dan bahkan melampaui banyak pemasang komersial dalam set fitur dan stabilitas.



Yang terbaik dari semuanya, tidak diperlukan skrip sama sekali untuk membuat penginstal dasar, karena Inno Setup dilengkapi dengan wizard grafis yang secara mengejutkan melakukan pekerjaan yang sangat baik untuk penginstal dasar.



Logika penginstalan dapat ditulis dalam Pascal daripada tindakan kustom yang berbelit-belit di Wix. Satu-satunya kelemahan adalah hanya membuat exe, format file msi tidak didukung.



Langkah 1. Tidak Ada Instalasi Pengaturan



Komentar tambahan tidak diperlukan di sini, karena mengunduh dan menginstal program penginstal itu sepele.



Langkah 2: Membuat Skrip Instalasi Pengaturan Inno



Mari buat sebuah rintisan Inno Setup script (file * .iss) menggunakan Wizard Script Instalasi.



















































Hasilnya, file * .iss akan dibuat dengan konten berikut:
; Script generated by the Inno Setup Script Wizard.

; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!



#define MyAppName "Severcart"

#define MyAppVersion "1.21.0"

#define MyAppPublisher "Severcart Inc."

#define MyAppURL "https://www.severcart.ru/"



[Setup]

; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.

; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)

AppId={{4FAF87DC-4DBD-42CE-A2A2-B6D559E76BDC}

AppName={#MyAppName}

AppVersion={#MyAppVersion}

;AppVerName={#MyAppName} {#MyAppVersion}

AppPublisher={#MyAppPublisher}

AppPublisherURL={#MyAppURL}

AppSupportURL={#MyAppURL}

AppUpdatesURL={#MyAppURL}

DefaultDirName=c:\severcart

DefaultGroupName={#MyAppName}

; Uncomment the following line to run in non administrative install mode (install for current user only.)

;PrivilegesRequired=lowest

OutputDir=C:\Users\Developer\Desktop\Output

OutputBaseFilename=mysetup

Compression=lzma

SolidCompression=yes

WizardStyle=modern



[Languages]

Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"



[Files]

Source: "C:\severcart\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs

; NOTE: Don't use "Flags: ignoreversion" on any shared system files







Langkah 3. Pemeriksaan sebelum instalasi



Sebelum membongkar program ke direktori dan mengubah registri, Anda perlu memeriksa apakah port TCP gratis agar Apache dan PostgreSQL berfungsi, Anda juga perlu memeriksa persyaratan sistem minimum Windows, karena Seperti yang telah disebutkan di bagian pertama artikel ini, versi Python yang terinstal hanya akan berfungsi mulai dari versi MS Windows 8 (kernel versi 6.2) .



Untuk melakukan pemeriksaan yang diperlukan, mari gunakan bagian [Kode] dari file instalasi. [Kode] bagianMerupakan bagian opsional yang mendefinisikan skrip Pascal. Skrip Pascal dapat digunakan untuk menyesuaikan instalasi atau penghapusan instalasi dengan berbagai cara. Perhatikan bahwa membuat skrip Pascal tidaklah mudah dan membutuhkan pengalaman dengan Inno Setup dan keterampilan pemrograman di Pascal atau setidaknya bahasa pemrograman yang serupa. Untuk memeriksa ketersediaan port TCP, kami akan membuat fungsi berikut: Kami akan memanggil fungsi pengujian di fungsi InitializeSetup , yang dipanggil selama inisialisasi instalasi. Mengembalikan False untuk membatalkan penginstalan, jika tidak, True .



function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;

var

Version: TWindowsVersion;

begin

GetWindowsVersionEx(Version);

Result := (Version.Major > Major) or ((Version.Major = Major) and (Version.Minor >= Minor));

end;



function IsWindows8OrNewer: Boolean;

begin

Result := IsWindowsVersionOrNewer(6, 2);

end;







function CheckPortOccupied(Port:String):Boolean;

var

ResultCode: Integer;

begin

Exec(ExpandConstant('{cmd}'), '/C netstat -na | findstr'+' /C:":'+Port+' "', '',0,ewWaitUntilTerminated, ResultCode);

if ResultCode <> 1 then

begin

Log('this port('+Port+') is occupied');

Result := True;

end else

begin

Result := False;

end;

end;







function InitializeSetup(): Boolean;

var

port_80_check, port_5432_check: boolean;

begin

if not IsWindows8OrNewer() then begin

MsgBox(' . Windows 2012 Windows 8.0.',mbError,MB_OK);

Abort();

Result := False;

end;



port_80_check := CheckPortOccupied('8080');

if port_80_check then begin

MsgBox(' . TCP 8080 .',mbError,MB_OK);

Abort();

Result := False;

end;



port_5432_check := CheckPortOccupied('5432');

if port_5432_check then begin

MsgBox(' . TCP 5432 .',mbError,MB_OK);

Result := False;

Abort();

end;

Result := True;



Langkah 4. Daftarkan Python di registri Windows



Bagian opsional ini menentukan kunci / nilai registri yang harus dibuat atau dimodifikasi oleh penginstal pada sistem pengguna.



Untuk melakukan ini, tambahkan kunci PYTHONPATH dan PYTHONHOME dan perbarui variabel Path .



sys.path berisi daftar string yang menyediakan lokasi pencarian untuk modul dan paket untuk proyek Python di masa mendatang. Ini diinisialisasi dari variabel lingkungan PYTHONPATH dan pengaturan lainnya.



PYTHONHOME adalah direktori home Python.



PATH adalah variabel lingkungan yang digunakan OS untuk menemukan file yang dapat dieksekusi di baris perintah atau jendela terminal.



[Registry]



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\python;{app}\python\Scripts"



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "PYTHONPATH"; ValueData: "{app}\python"



Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \

ValueType: expandsz; ValueName: "PYTHONHOME"; ValueData: "{app}\python"



Langkah 5. Buat file konfigurasi untuk layanan Apache dan PostgreSQL



Untuk membuat file konfigurasi, kami akan menggunakan 2 skrip Python yang akan menghasilkan konfigurasi berdasarkan jalur instalasi yang ditentukan pengguna.



Skrip akan dipanggil di bagian [Jalankan] dari penginstal.



Bagian [Run] adalah opsional dan menentukan sejumlah program untuk dijalankan setelah program berhasil diinstal, tetapi sebelum penginstal menampilkan kotak dialog terakhir.



Selanjutnya, di bagian yang sama, tambahkan penginstalan tersembunyi Paket Visual Studio Redistributable yang tanpanya layanan Apache dan PostgreSQL tidak akan berfungsi. Isi dari file create_http_conf.py



[Run]



Filename: "{app}\common\VC_redist.x86apache.exe"; Parameters: "/install /passive"; Flags: waituntilterminated

Filename: "{app}\common\vcredist_x86pg.exe"; Parameters: "/install /passive"; Flags: runhidden;

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\create_http_conf.py"; Flags: runhidden

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\edit_pg_conf.py"; Flags: runhidden

Filename: "{app}\common\install.bat";Flags: runhidden

Filename: "{app}\common\services_start.bat"; Flags: runhidden







#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import sys, os


base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
base_path_un = base_path.replace('\\', '/')
apache_conf_path = os.path.join(base_path, 'Apache24', 'conf', 'extra', 'httpd-wsgi.conf')

print('base_path=',base_path)

CONF = """

LoadFile "%(base)s/python/python39.dll"
LoadModule wsgi_module "%(base)s/python/lib/site-packages/mod_wsgi/server/mod_wsgi.cp39-win32.pyd"
WSGIPythonHome "%(base)s/python"


Alias /static "%(base)s/app/static"

Alias /media "%(base)s/app/media"

<Directory "%(base)s/app/static">
    # for Apache 2.4
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

<Directory "%(base)s/app/media">
    # for Apache 2.4
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>


WSGIScriptAlias / "%(base)s/app/conf/wsgi_prod.py"
WSGIPythonPath "%(base)s/python/"

<Directory "%(base)s/app/conf/">
<Files wsgi_prod.py>
    Require all granted
</Files>   
</Directory>

"""
conf_content = CONF % {'base': base_path_un}

with open(apache_conf_path, 'w') as fp:
    fp.write(conf_content)


# Read in the file
apache_main = os.path.join(base_path, 'Apache24', 'conf', 'httpd.conf')
with open(apache_main, 'r') as file :
	filedata = file.read()

# Replace the target string
replace_pattern = 'Define SRVROOT "%(base)s/Apache24"' % {'base' : base_path_un}
find_pattern = 'Define SRVROOT "C:/severcart/Apache24"'

filedata = filedata.replace(find_pattern, replace_pattern)

# Write the file out again
with open(apache_main, 'w') as file:
	file.write(filedata)



Konten edit_pg_conf.py



#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import sys, os

"""
c:/djangostack/postgresql/bin/postgres.exe "-D" "c:\djangostack\postgresql\data"
"""


base_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
base_path_un = base_path.replace('\\', '/')
pg_conf_path = os.path.join(base_path, 'postgresql', 'data', 'postmaster.opts')


# Read in the file
pg_conf_path = os.path.join(base_path, 'postgresql', 'data', 'postmaster.opts')
with open(pg_conf_path, 'r') as file :
	filedata = file.read()


# Replace the target string
replace_pattern = base_path_un + '/'
find_pattern = "C:/severcart/"


filedata = filedata.replace(find_pattern, replace_pattern)

# Write the file out again
with open(pg_conf_path, 'w') as file:
	file.write(filedata)


File install.bat Berisi file services_start.bat



@echo off



..\Apache24\bin\httpd.exe -k install -n "Apache" > install.log 2>&1



..\postgresql\bin\pg_ctl.exe register -N "PostgreSQL" -D ..\postgresql\data > install.log 2>&1







@echo off



net start "Apache"



net start "PostgreSQL"



Langkah 6: Buat uninstaller



Untuk penginstal apa pun, Anda juga perlu menyediakan kemungkinan membuat program uninstaller. Untungnya, Inno Setup akan melakukan pekerjaan itu untuk kita, kecuali beberapa langkah yang perlu diambil untuk membersihkan jejak kehadiran program di OS.



Untuk melakukan ini, di bagian [UninstallRun] , kami akan mendaftarkan eksekusi skrip bat Windows untuk menghentikan layanan yang diinstal, serta menghapusnya. Isi skrip bat: Skrip menghentikan layanan, lalu menghapus layanan Apache dan PostgreSQL dari daftar layanan sistem Windows.



[UninstallRun]

Filename: "{app}\common\remove.bat"; Flags: runhidden







@echo off



SC STOP Apache

SC STOP PostgreSQL



SC DELETE Apache

SC DELETE PostgreSQL







Langkah 7. Menandatangani file yang dapat dijalankan dari penginstal ES pengembang



Sertifikat penandatanganan kode digunakan oleh pengembang perangkat lunak untuk menandatangani aplikasi dan program secara digital untuk membuktikan bahwa file yang diunggah oleh pengguna adalah asli dan tidak dirusak. Hal ini sangat penting terutama bagi penerbit yang mendistribusikan perangkat lunak mereka melalui situs unduhan pihak ketiga yang tidak dapat mereka kendalikan. Sistem operasi utama akan menampilkan pesan kesalahan kepada pengguna akhir jika perangkat lunak yang mereka coba instal tidak ditandatangani oleh otoritas sertifikasi tepercaya.



Anda dapat membeli sertifikat pengembang PFX, misalnya, di sini . Sertifikat dibeli selama satu tahun.



Langkah terakhir untuk bekerja dengan penginstal adalah secara otomatis meluncurkan program signtool.exe untuk menandatangani penginstal yang sudah selesai dalam format exe setelah program Pengaturan Inno menyelesaikan pekerjaannya. SignTool adalah program baris perintah yang menandatangani file secara digital, memverifikasi tanda tangan file dan cap waktu file. Secara default, program signtool.exe tidak disertakan dalam distribusi Windows, jadi kami mengunduh dan menginstal SDK Windows 10 .



Setelah penginstalan selesai, Anda akan menemukan signtool.exe di direktori:



  • x86 -> c: \ Program Files (x86) \ Windows Kits \ 10 \ bin \ x86 \
  • x64 -> c: \ Program Files (x86) \ Windows Kits \ 10 \ bin \ x64 \


Bagi mereka yang ingin mengenal program penandatanganan, kunjungi situs web resmi pengembang untuk lebih jelasnya . Ini mencantumkan semua opsi baris perintah dan contoh penggunaan. Ayo lanjutkan.



Selanjutnya, mari kita siapkan penandatanganan file secara otomatis. Pilih "Configure Sign Tools ..." dari menu "Tools" .







Selanjutnya, klik pada tombol "Add"







Beri nama alat tersebut. Ini adalah nama yang akan Anda gunakan saat merujuk ke alat di skrip penginstal. Saya menamai saya signtool karena saya menggunakan signtool.exe.







Tempel teks yang Anda gunakan untuk menandatangani file yang dapat dieksekusi dari baris perintah. Ganti nama file yang akan ditandatangani dengan $ f. Inno Setup akan mengganti variabel $ f dengan file yang ditandatangani.



"C: \ Program Files (x86) \ Windows Kits \ 10 \ bin \ x86 \ signtool.exe" sign / f "C: \ MY_CODE_SIGNING.PFX" / t timestamp.comodoca.com/authenticode / p MY_PASSWORD $ f







Setelah menekan OK Anda sudah selesai mengkonfigurasi alat tanda tangan.







Mari tambahkan skrip berikut ke bagian [Setup] untuk menggunakan alat tanda tangan yang baru saja kita konfigurasikan. Ini mengasumsikan Anda menamai alat Anda signtool.



SignTool=signtool



Langkah 8. Merakit penginstal



File pemasang Final InnoSetup
#define MyAppName «Severcart»

#define MyAppVersion «1.21.0»

#define MyAppPublisher «Severcart Inc.»

#define MyAppURL «www.severcart.ru»



[Setup]

; NOTE: The value of AppId uniquely identifies this application.

; Do not use the same AppId value in installers for other applications.

; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)

SignTool=signtool

AppId={{2CF113D5-B49D-47EF-B85F-AE06EB0E78EB}}

AppName={#MyAppName}

AppVersion={#MyAppVersion}

;AppVerName={#MyAppName} {#MyAppVersion}

AppPublisher={#MyAppPublisher}

AppPublisherURL={#MyAppURL}

AppSupportURL={#MyAppURL}

AppUpdatesURL={#MyAppURL}

DefaultDirName=c:\severcart

DefaultGroupName={#MyAppName}

OutputBaseFilename=setup

Compression=lzma

SolidCompression=yes

ChangesEnvironment=yes



; Uninstall options

Uninstallable=yes

CreateUninstallRegKey=yes

;WizardSmallImageFile=logo3.bmp



[Icons]

Name: "{userdesktop}\severcart"; Filename: «127.0.0.1:8080/»



[Languages]

Name: «russian»; MessagesFile: «compiler:Languages\Russian.isl»



[Files]

Source: «C:\severcart\*»; Excludes: "*.pyc"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs



[Registry]

Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «Path»; ValueData: "{olddata};{app}\python;{app}\python\Scripts"



Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «PYTHONPATH»; ValueData: "{app}\python"



Root: HKLM; Subkey: «SYSTEM\CurrentControlSet\Control\Session Manager\Environment»; \

ValueType: expandsz; ValueName: «PYTHONHOME»; ValueData: "{app}\python"



[Run]

Filename: "{app}\common\VC_redist.x86apache"; Parameters: "/install /passive"; Flags: waituntilterminated

Filename: "{app}\common\vcredist_x86pg"; Parameters: "/install /passive"; Flags: runhidden;

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\create_http_conf.py"; Flags: runhidden

Filename: "{app}\python\python.exe" ;Parameters: "{app}\common\edit_pg_conf.py"; Flags: runhidden

Filename: "{app}\common\install.bat";Flags: runhidden

Filename: "{app}\common\services_start.bat"; Flags: runhidden





[UninstallRun]

Filename: "{app}\common\remove.bat"; Flags: runhidden



[Code]

function IsWindowsVersionOrNewer(Major, Minor: Integer): Boolean;

var

Version: TWindowsVersion;

begin

GetWindowsVersionEx(Version);

Result :=

(Version.Major > Major) or

((Version.Major = Major) and (Version.Minor >= Minor));

end;



function IsWindows8OrNewer: Boolean;

begin

Result := IsWindowsVersionOrNewer(6, 2);

end;



function CheckPortOccupied(Port:String):Boolean;

var

ResultCode: Integer;

begin

Exec(ExpandConstant('{cmd}'), '/C netstat -na | findstr'+' /C:":'+Port+' "', '',0,ewWaitUntilTerminated, ResultCode);

if ResultCode <> 1 then

begin

Log('this port('+Port+') is occupied');

Result := True;

end else

begin

Result := False;

end;

end;



function InitializeSetup(): Boolean;

var

port_80_check, port_5432_check: boolean;

begin

if not IsWindows8OrNewer() then begin

MsgBox(' . Windows 2012 Windows 8.0.',mbError,MB_OK);

Abort();

Result := False;

end;



port_80_check := CheckPortOccupied('8080');

if port_80_check then begin

MsgBox(' . TCP 8080 .',mbError,MB_OK);

Abort();

Result := False;

end;



port_5432_check := CheckPortOccupied('5432');

if port_5432_check then begin

MsgBox(' . TCP 5432 .',mbError,MB_OK);

Result := False;

Abort();

end;

Result := True;



end;











Langkah 9. Memeriksa pekerjaan penginstal







































Sekian terima kasih atas perhatiannya.



All Articles