Liigu peamise sisu juurde

6 postitust sildistatud "varia"

Vaata Kõiki Silte

Mitme .NET 10 rakenduse paigaldamine ühte kausta ilma DLL-konfliktideta

· 10 min lugemine
Infokiir OÜ

1. Probleem

.NET 10 rakenduse tavaline raamistikupõhine (framework-dependent) Release-ehitus tekitab kausta hulga faile, mis näivad jagatavatena, kuid enamasti seda ei ole:

AlamkollektsiooniKopeerimineValikuga.deps.json
AlamkollektsiooniKopeerimineValikuga.dll
AlamkollektsiooniKopeerimineValikuga.exe
AlamkollektsiooniKopeerimineValikuga.pdb
AlamkollektsiooniKopeerimineValikuga.runtimeconfig.json
AlamkollektsiooniKopeerimineValikugaLib.dll / .pdb
BouncyCastle.Crypto.dll
Google.Protobuf.dll
K4os.Compression.LZ4.dll
K4os.Compression.LZ4.Streams.dll
K4os.Hash.xxHash.dll
MySql.Data.dll
System.CommandLine.dll
cs\ de\ es\ fr\ it\ ja\ ko\ pl\ pt-BR\ ru\ tr\ zh-Hans\ zh-Hant\ (satelliit-ressursiteegid)
runtimes\ (natiivteegid)

Kui teise rakenduse ehitustulemus paigutada samasse kausta, tekib klassikaline DLL-põrgu: kui kaks rakendust viitavad sama NuGet-paketi eri versioonidele (nt MySql.Data 8.0.33 vs 8.4.x), jääb peale see, kelle failid viimasena kopeeriti. Iga rakenduse deps.json sisaldab täpselt seda versiooni, millega rakendus kompileeriti, mistõttu „kaotanud" rakendus võib käivitumisel anda teegi laadimise vea või – veelgi halvem – töötada vaikselt valesti.

Milleks iga väljundfail on

FailOtstarveRakenduste vahel jagatav?
*.deps.jsonTäpne sõltuvuste graaf (teegid + versioonid), mida host käivitumisel loebEi – rangelt rakendusepõhine
*.runtimeconfig.jsonSihtruntime'i versioon ja seadedEi – rangelt rakendusepõhine
*.exe (apphost)Natiivne käivitaja, mis on kõvasti seotud rakenduse põhi-DLL-igaEi – definitsiooni järgi rakendusepõhine
Rakenduse .dll / .pdbRakenduse kompileeritud IL-kood ja silumissümbolidEi
NuGet-sõltuvuste DLL-idKopeeritakse ehitamisel NuGet-vahemälustAinult siis, kui kõik rakendused kasutavad täpselt samu paketiversioone
Keelekaustad (cs, de, …)Satelliit-ressursiteegid (lokaliseeritud sõnumid, siin MySql.Data omad)Sama versioonisõltuvuse probleem
runtimes\Platvormispetsiifilised natiivteegid NuGet-pakettidestSama versioonisõltuvuse probleem

.NET runtime ise raamistikupõhise ehituse puhul selles kaustas ei ole – see on paigaldatud masinaüleselt ja on niikuinii jagatud. Kõik väljundkaustas olev on rakenduse enda pagas.

Viide: .NET-rakenduste avaldamise ülevaade – https://learn.microsoft.com/en-us/dotnet/core/deploying/


2. Samm 1 – tarbetute satelliit- (keele-) teekide eemaldamine

Kolmteist keelekausta pärinesid MySql.Data lokaliseeritud veateadetest. Kui ingliskeelsetest sõnumitest piisab, piirab MSBuild-atribuut SatelliteResourceLanguages väljundisse kopeeritavaid satelliitteeke:

<PropertyGroup>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>

Praktikas selgunud olulised detailid:

  1. Atribuut peab olema seatud käivitatava projekti failis. Iga projekt otsustab ise, millised satelliitteegid ta oma NuGet-sõltuvustest väljundisse kopeerib, seega ainult viidatud klassiteegis seadmine käivitatava projekti väljundit ei puhasta. Mõlemas projektis seadmine on ohutu.
  2. Lahendusülene alternatiiv: paiguta atribuut üks kord lahenduse juurkausta faili Directory.Build.props – MSBuild rakendab selle automaatselt kõigile allolevatele projektidele:
<Project>
<PropertyGroup>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
</PropertyGroup>
</Project>
  1. Clean ega Rebuild vanu kaustu ei eemalda. dotnet clean / VS Clean kustutab ainult faile, mis on kirjas eelmise ehituse jälgimislogis. Kui uus ehitus satelliitteeke enam ei tooda, muutuvad vanad kaustad orbudeks, mida ükski ehitussamm ei „oma". Õnnestumist saab kontrollida deps.json faili suuruse vähenemisest (antud juhul 7 756 → 6 191 baiti); seejärel kustuta bin-kaust käsitsi üks kord. Kaustad enam tagasi ei teki.

Viited:


3. Samm 2 – ühefaililine avaldamine (single-file publish)

Ühefaililine avaldamine pakendab rakenduse DLL-i ja kõik hallatavad (managed) NuGet-sõltuvused exe-faili sisse. Hallatavad teegid laaditakse otse pakendist mällu (kettale midagi lahti ei pakita). See kõrvaldab peaaegu kõik jagatud failidest tulenevad konfliktid.

Töötav avaldamisprofiil (Properties\PublishProfiles\FolderProfile.pubxml):

<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net10.0-windows7.0\publish\win-x64\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net10.0-windows7.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>

Sama käsurealt:

dotnet publish -c Release -r win-x64 --self-contained false ^
-p:PublishSingleFile=true ^
-p:IncludeNativeLibrariesForSelfExtract=true ^
-p:DebugType=none -p:DebugSymbols=false

Atribuutide selgitused

PublishSingleFile=true Pakendab rakenduse ja kõik hallatavad sõltuvused üheks käivitatavaks failiks. Nõuab RuntimeIdentifier-i, sest apphost on platvormispetsiifiline. Dokumentatsioon: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview

SelfContained=false (raamistikupõhine) .NET 10 runtime'i pakendisse ei lisata; see peab olema sihtmasinas paigaldatud. Nii jäi exe suuruseks ~7 MB. Väärtus true pakendaks kogu runtime'i (~70+ MB exe kohta), kuid kaotaks runtime'i paigaldamise nõude. Dokumentatsioon: https://learn.microsoft.com/en-us/dotnet/core/deploying/

RuntimeIdentifier=win-x64 Valib sihtplatvormi natiivse apphost'i ja natiivsõltuvuste jaoks. RID-kataloog: https://learn.microsoft.com/en-us/dotnet/core/rid-catalog

IncludeNativeLibrariesForSelfExtract=true Vaikimisi (alates .NET 5-st) jätab ühefaililine avaldamine natiivsed DLL-id lahtiste failidena exe kõrvale. Selles projektis olid nendeks MySql.Data Kerberos/GSSAPI teegid: comerr64.dll, gssapi64.dll, k5sprt64.dll, krb5_64.dll, krbcc64.dll – viimane allesjäänud konfliktipind. Selle atribuudiga pakitakse natiivteegid exe sisse ja pakitakse käivitumisel lahti rakendusepõhisesse ajutisse kausta, mistõttu erinevad rakendused ei puutu kunagi üksteise natiivfaile. Exe kasvas umbes 1,8 MB võrra. Dokumentatsioon (sama leht, jaotis „Include native libraries"): https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview (Lahtipakkimise asukohta saab vajadusel suunata keskkonnamuutujaga DOTNET_BUNDLE_EXTRACT_BASE_DIR – kirjeldatud samal lehel.)

DebugType=none + DebugSymbols=false Keelab .pdb-failide genereerimise Release/publish puhul täielikult. Tähelepanu: avaldamisprofiil mõjutab ainult käivitatavat projekti; viidatud klassiteek kompileerub oma seadetega ja tekitab endiselt .pdb faili. Töökindel lahendus on seada need atribuudid projektipõhiselt (või üks kord failis Directory.Build.props), tingimusega Release-konfiguratsioonile, et Debug-ehitused säilitaksid täielikud sümbolid:

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>

Teadmist väärt alternatiiv: DebugType=embedded paigutab sümbolid exe sisse – lahtist .pdb-d pole, kuid stack trace'id säilitavad faili- ja reainfo. Kasulik, kui välidiagnostika on paarisaja kilobaidi kokkuhoiust olulisem. Dokumentatsioon: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/code-generation

PublishReadyToRun=false ReadyToRun kompileerib IL-koodi ette natiivkoodiks, mis kiirendab käivitumist suurema faili hinnaga. Siin välja lülitatud; lülita sisse rakendusepõhiselt, kui käivituskiirus on oluline. Dokumentatsioon: https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run

Tulemus

Pärast vana publish-kausta ühekordset kustutamist (publish, nagu ka clean, ei eemalda eelmiste konfiguratsioonide orvuks jäänud faile) ja uuesti avaldamist:

AlamkollektsiooniKopeerimineValikuga.exe (~7 MB, üks fail)

Muud midagi. Hallatavad sõltuvused, satelliitteekide käsitlus ja natiivsed Kerberos-teegid on kõik exe sees.


4. Mitme rakenduse paigaldamine ühte kausta

Ülaltoodud seadistusega võib ühte jagatud kausta paigutada ükskõik kui palju rakendusi:

  1. Iga rakendus on üks unikaalse nimega exe – jagatud faile pole, seega on versioonikonfliktid välistatud.
  2. Natiivteegid pakitakse käivitumisel lahti rakendusepõhistesse ajutistesse kaustadesse, seega ei teki ka käitusaegseid kokkupõrkeid.
  3. Iga rakendus võib kasutada MySql.Data või mis tahes muu paketi erinevat versiooni, mõjutamata teisi.

Üks praktiline soovitus: ära suuna mitme projekti PublishDir-i otse samasse jagatud kausta. Publish-samm võib kustutada faile, mida ta peab aegunuks, ja nii võib kaduma minna teise rakenduse exe. Ohutum muster:

avalda iga projekt oma kausta (nagu ülal seadistatud)

└──► kopeeri valminud exe-failid ühisesse paigalduskausta

Kopeerimise saab teha väikese skriptiga või MSBuildi publish-järgse sammuna, näiteks:

<Target Name="CopyToDeployFolder" AfterTargets="Publish">
<Copy SourceFiles="$(PublishDir)$(AssemblyName).exe"
DestinationFolder="E:\LenneApps\Deploy\" />
</Target>

5. Ühefaililise paigalduse kompromissid ja tähelepanekud

  • Raamistikupõhine ühefaililine exe nõuab endiselt .NET 10 runtime'i igas sihtmasinas. Ettevõttesisese paigalduse puhul, kus runtime'i hallatakse tsentraalselt, on see enamasti õige valik: exe-d jäävad väikeseks ja runtime'i turvapaigad rakenduvad kõigile rakendustele korraga.
  • Mõned API-d käituvad ühefaililises rakenduses teisiti. Assembly.Location tagastab tühja stringi; kood, mis selle põhjal teid koostab, peab kasutama hoopis AppContext.BaseDirectory-t. Kolmandate osapoolte paketid komistavad selle otsa aeg-ajalt. Täielik ühilduvustabel: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview (jaotis „API incompatibility").
  • Valikuline suuruse vähendamine: EnableCompressionInSingleFile=true pakib pakendatud teegid kokku väikese käivitusaja hinnaga. Trimmimine (PublishTrimmed=true) on saadaval ainult self-contained rakendustele ja vajab testimist refleksioonirohkete teekidega nagu MySql.Data.
  • Rusikareegel aegunud failide kohta: kui ehitus- või avaldamisseaded muudavad, mida toodetakse, kustuta vana bin-/publish-kaust üks kord. Ei Clean ega Publish ei eemalda faile, mida uus konfiguratsioon enam ei genereeri.

6. Ühefaililise avaldamise ajalugu ja Windowsi tugi

Kuidas võimalus arenes

  • .NET Core 3.0 (september 2019)PublishSingleFile ilmus esimest korda. Toona oli see sisuliselt isepakkiv arhiiv: käivitumisel pakiti kõik failid (nii hallatavad kui natiivsed) kettale ajutisse kausta lahti ja käivitati sealt.
  • .NET 5 (november 2020) – praegune „päris" ühefaililine mudel: hallatavad teegid laaditakse otse exe seest mällu, kettale ei pakita midagi. Samas versioonis tuli ka IncludeNativeLibrariesForSelfExtract, sest natiivteegid jäeti nüüd vaikimisi pakendist välja (varem pakiti kõik kaasa). Just seda kombinatsiooni käesolev juhend kasutabki.
  • .NET 6 (november 2021) – lisandus EnableCompressionInSingleFile pakendatud teekide kokkupakkimiseks ning mudel stabiliseerus tänasel kujul.

Seega on selles dokumendis kirjeldatud tehnika (mällu laadimine + natiivteekide kaasapakkimine) olemas alates .NET 5-st, novembrist 2020.

Millised Windowsi versioonid tulemust jooksutavad

.NET 10 on ametlikult toetatud Windows 11 (23H2, 24H2, 25H2, 26H1) ja Windows 10 peal alates versioonist 1607 (Enterprise/LTSC kanalid: 1607, 1809, 21H2). Praktikas tähendab see Windows 10 (1607+) ja Windows 11. Tavaline Windows 10 22H2 langes ametlikust toest välja koos Windowsi enda toe lõppemisega oktoobris 2025, kuigi rakendused seal endiselt töötavad. Windows 7 ja 8.1 peal .NET 10 ei tööta üldse – nende tugi kadus juba .NET 7/8 ajal.

Märkus TFM-i net10.0-windows7.0 kohta: „7.0" ei tähenda Windows 7 tuge. See on lihtsalt vaikimisi deklareeritav minimaalne Windowsi API versioon, mille MSBuild paneb, kui <TargetFramework>net10.0-windows</TargetFramework> on kirjutatud ilma versioonita. Tegelik miinimum-OS on see, mida runtime ise toetab.

Ajakohane .NET 10 toetatud operatsioonisüsteemide nimekiri: https://github.com/dotnet/core/blob/main/release-notes/10.0/supported-os.md


7. Natiivmaailm: kuidas teha C++ rakendusest üks .exe fail

Natiivrakendustel puudub .NET-i laadne bundle-mehhanism, mida runtime oskaks mälust laadida, seega on lähenemised teistsugused.

Variant 1 – staatiline linkimine (soovitatav)

Sõltuvused lingitakse kompileerimisel .lib staatiliste teekidena otse exe sisse, DLL-e ei tekigi. MSVC puhul tähendab see runtime'i lülitit /MT (/MD asemel) ja kolmandate osapoolte teekide staatilisi variante. vcpkg teeb selle lihtsaks: triplet x64-windows-static ehitab kõik sõltuvused staatilistena. Tulemus on üksainus exe ilma käitusaegse maagiata – kiireim käivitus ja kõige töökindlam variant. Miinused: suurem exe, iga teegi uuendus nõuab uuesti linkimist, ja mõned litsentsid (nt LGPL, sh Qt) seavad staatilisele linkimisele piiranguid.

Variant 2 – DLL-ide pakkimine valmis exe sisse

Tööriistad nagu Enigma Virtual Box (tasuta) või BoxedApp Packer võtavad valmis exe + DLL-id ja teevad neist ühe faili, mis virtualiseerib failisüsteemi kutsed – DLL-id eksisteerivad ainult mälus. Töötab ka siis, kui lähtekoodi või staatilisi teeke pole (suletud lähtekoodiga DLL-id). Miinused: viirusetõrjed suhtuvad pakitud exe-desse kohati kahtlustavalt ning COM-registreerimist vajavad DLL-id ei pruugi töötada.

Variant 3 – DLL ressursina ja mälust laadimine

DLL-id paigutatakse exe ressurssidesse ja laaditakse käivitumisel kas ajutisse kausta tavalise LoadLibrary-ga (nagu .NET Core 3.0 omal ajal tegi) või otse mälust MemoryModule teegiga, mis implementeerib oma PE-laadija. Kõige paindlikum, aga ka kõige rohkem käsitööd nõudev tee; MemoryModule'il on piirangud (erandikäsitlus x64-l, mõned DLL-id eeldavad failitee olemasolu).

Järeldus

GUI-rakenduste puhul on staatilise linkimisega natiivset exe-d tegelikult harva vaja: .NET raamistiku kasutamine on hästi hallatav, arendus on kiirem ning jõudlus ei jää natiivrakendusele oluliselt alla. Ühefaililine .NET-avaldamine (peatükid 3–4) annab sama paigaldusmugavuse – üks exe, null DLL-konflikti – ilma natiivmaailma linkimis- ja litsentsimuredeta. Natiivne staatiline linkimine tasub end ära peamiselt siis, kui runtime'i paigaldamine sihtmasinasse pole võimalik, rakendus peab olema minimaalse mälujäljega või tegu on niikuinii C++ koodibaasiga (nt riistvaralähedased tööriistad).


8. Kiirviited – dokumentatsiooni lingid

TeemaLink
Ühefaililine paigaldus (PublishSingleFile, IncludeNativeLibrariesForSelfExtract, lahtipakkimine, API piirangud)https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview
.NET paigaldusmudelid (raamistikupõhine vs self-contained)https://learn.microsoft.com/en-us/dotnet/core/deploying/
SDK-projektide MSBuild-atribuudid (SatelliteResourceLanguages, publish-atribuudid)https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props
Directory.Build.props / ehituse kohandamine kaustapõhiselthttps://learn.microsoft.com/en-us/visualstudio/msbuild/customize-by-directory
DebugType / DebugSymbols kompilaatoriseadedhttps://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/code-generation
ReadyToRun kompileeriminehttps://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run
Runtime identifier (RID) katalooghttps://learn.microsoft.com/en-us/dotnet/core/rid-catalog
Self-contained rakenduste trimmiminehttps://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained

Uus koduleht 2026

· Ühe min lugemine
Infokiir OÜ
  1. aasta lõpus sai siinsamas kirjutatud, et vana koduleht oli liiga kaua muutumatuna püsinud. Ajalugu kordub — vahepeal möödus kaheksa aastat ja nüüd oli jälle aeg uuenduseks.

MacBook Pro Ubuntu Desktop 20.04 LTS Linux ja USB klaviatuur

· Ühe min lugemine
Infokiir OÜ

Kuidas installida Ubuntu Desktop 20.04 LTS Linux MacBook Pro sülearvutile USB mälupulgale?

macbook-ubuntu

Selle kohta sai tehtud 2 videot:

https://www.youtube.com/watch?v=mo440sAe2dQ

https://www.youtube.com/watch?v=F7ZHVNVBuN8

Selleks, et GRUB käsureal oleks kergem tööd teha, sai tehtud ka USB klaviatuur, mis saadab klahvivajutused järjestikpordi kaudu:

https://www.youtube.com/watch?v=ZbuvjBGOJGg

Vastavad github leheküljed:

https://github.com/asjadenet/macbook-ubuntu-usb

https://github.com/asjadenet/serial2keyb

https://github.com/asjadenet/serial2keyb-byline

Mitte keegi ei taha rohkem tarkvara…

· Ühe min lugemine
Infokiir OÜ

tarkvara

Photo by Fotis Fotopoulos on Unsplash

Mitte keegi ei taha rohkem tarkvara… See on täitsa tõsi. Tarkvara ei ole vaja lihtsalt tarkvara pärast. Kellele meeldiks iga päev paigaldada oma arvutisse aina uusi programme või proovida internetis üha uusi ja uusi teenuseid?

Kui meil ei ole vaja uut tarkvara, siis mida meil siiski vaja on? Eelkõige soovime lahendusi tüütutele ja keerulistele probleemidele, soovime vältida vigu, mis tulenevad sellest, et meil ei ole asjad hästi organiseeritud, puudub ülevaade, eksime sisestamisel, unustame jne.

Hea tarkvara aitab lahendada probleeme ja kes seda ei tahaks? Hea tarkvara justkui peidab probleemid ja keerukuse meie eest ja näitab meile midagi lihtsat, ilusat ja mugavat.

Seega selle asemel, et öelda "meil on vaja rohkem tarkvara" võiks öelda "meil on vaja head lahendust".

Azure docker ja eestikeelne kõnetuvastus

· 4 min lugemine
Infokiir OÜ

Eesti keele kõnetuvastus on üsna keeruline tarkvara. Isegi selle installeerimine enda arvutisse võib olla väljakutse. Mis siis rääkida veel selle kirjutamisest programmeerijana.

Veebibrauseris vastav tööriist on internetis saadaval siin: http://bark.phon.ioc.ee/webtrans/

Kui siiski soovime seda tarkvara ise jooksutada, siis üks lihtne võimalus on kasutada valmis docker konteinerit.

Juhendi leiame siit:

https://github.com/alumae/kaldi-offline-transcriber/tree/master/misc/docker

Kui teha selle juhendi järgi, siis suure tõenäosusega saame selle ka kohe tööle. Eelnevalt tuleb jälgida, et docker konteineri käsutuses oleks vähemalt 6GB RAM. Mul ebaõnnestus 4GB RAM-ga, kuid 6GB oli piisav, et üks näide tööle saada.

Kui me ei sooviks seda tarkvara hoida enda arvutis vaid hoopis Azure pilves, kuidas see siis tööle saada? Järgnevalt on dokumenteeritud väike juhend, kuidas mul see õnnestus kasutades PowerShell käsurida.

Kõigepealt tee resource group:

az group create --name tuvastusResourceGroup --location uksouth

vastus:

{
"id": "/subscriptions/55622624-1ccb-4e6c-97dc-51d463935a2e/resourceGroups/tuvastusResourceGroup",
"location": "uksouth",
"managedBy": null,
"name": "tuvastusResourceGroup",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}

Seejärel tee Container Registry:

az acr create --resource-group tuvastusResourceGroup --name tuvastusContainerRegistry --sku Basic

vastus:

{
"adminUserEnabled": false,
"creationDate": "2019-11-01T08:36:50.213637+00:00",
"id": "/subscriptions/55622624-1ccb-4e6c-97dc-51d463935a2e/resourceGroups/tuvastusResourceGroup/providers/Microsoft.ContainerRegistry/registries/tuvastusContainerRegistry",
"location": "uksouth",
"loginServer": "tuvastuscontainerregistry.azurecr.io",
"name": "tuvastusContainerRegistry",
"networkRuleSet": null,
"policies": {
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2019-11-01T08:36:52.156079+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"provisioningState": "Succeeded",
"resourceGroup": "tuvastusResourceGroup",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}

Logi sisse:

az acr login --name tuvastusContainerRegistry

Vastus:

Login Succeeded

Lubame admin kasutaja:

az acr update -n tuvastusContainerRegistry --admin-enabled true

vastus:

{
"adminUserEnabled": true,
"creationDate": "2019-11-01T08:36:50.213637+00:00",
"id": "/subscriptions/55622624-1ccb-4e6c-97dc-51d463935a2e/resourceGroups/tuvastusResourceGroup/providers/Microsoft.ContainerRegistry/registries/tuvastusContainerRegistry",
"location": "uksouth",
"loginServer": "tuvastuscontainerregistry.azurecr.io",
"name": "tuvastusContainerRegistry",
"networkRuleSet": null,
"policies": {
"quarantinePolicy": {
"status": "disabled"
},
"retentionPolicy": {
"days": 7,
"lastUpdatedTime": "2019-11-01T08:36:52.156079+00:00",
"status": "disabled"
},
"trustPolicy": {
"status": "disabled",
"type": "Notary"
}
},
"provisioningState": "Succeeded",
"resourceGroup": "tuvastusResourceGroup",
"sku": {
"name": "Basic",
"tier": "Basic"
},
"status": null,
"storageAccount": null,
"tags": {},
"type": "Microsoft.ContainerRegistry/registries"
}

Tekitatud kasutajanime ja parooli saab vaadata nii:

az acr credential show --name tuvastusContainerRegistry

Vastus:

{
"passwords": [
{
"name": "password",
"value": "********************************"
},
{
"name": "password2",
"value": "********************************"
}
],
"username": "tuvastusContainerRegistry"
}

Veendu, et käsurida lokaalses dockeris töötab. Näiteks:

docker exec 79bafd51385a1933d7ea584a07870a0bc8ab9c791ab24a938e17e3313ce750cb bash -c 'mkdir -p /opt/speechfiles/ ; cd /opt/speechfiles/ ; wget https://www.infokiir.ee/mp3test/proov.mp3 ; /opt/kaldi-offline-transcriber/speech2text.sh --trs /opt/speechfiles/proov.trs /opt/speechfiles/proov.mp3 ; cat /opt/speechfiles/proov.trs'

tag käsklusega märgistame konteineri:

docker tag alumae/kaldi-offline-transcriber-et tuvastuscontainerregistry.azurecr.io/kaldi-offline-transcriber-et:v1

Saadame selle azure pilve (see võtab üsnagi aega, sõltuvalt interneti kiirusest):

docker push tuvastuscontainerregistry.azurecr.io/kaldi-offline-transcriber-et:v1

Nüüd teen docker image vastava käsureaga:

az container create --restart-policy Never --registry-username tuvastusContainerRegistry --registry-password ******************************** --cpu 2 --memory 6 --resource-group tuvastusResourceGroup --name tuvastus6m --image tuvastuscontainerregistry.azurecr.io/kaldi-offline-transcriber-et:v1 --command-line "bash -c 'mkdir -p /opt/speechfiles/ ; cd /opt/speechfiles/ ; wget https://www.infokiir.ee/mp3test/proov.mp3 ; /opt/kaldi-offline-transcriber/speech2text.sh --trs /opt/speechfiles/proov.trs /opt/speechfiles/proov.mp3 ; cat /opt/speechfiles/proov.trs'"

Muide alla 6GB mälu ei tasu panna. Proovisin 4GB ja sellest jäi väheks.

Tulemust vaatan käsklusega:

az container logs --resource-group tuvastusResourceGroup --name tuvastus6m

See näeb välja umbes selline:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Trans SYSTEM "trans-14.dtd">
<Trans scribe="est-speech2txt" audio_filename="proov" version="1" version_date="191101">
<Speakers>
<Speaker id="spk1" name="K01" check="no" dialect="native" accent="" scope="local"/>
</Speakers>
<Episode>
<Section type="report" startTime="0.000" endTime="9.330">
<Turn speaker="spk1" startTime="0.690" endTime="9.150">
<Sync time="0.690"/>
Ma teen siis ise kõigepealt ühe väikse proovi. Vaatame, kas ta oskab helifaili teha tekstiks.
</Turn>
</Section>
<Section type="filler" startTime="9.330" endTime="10.320">
</Section>
</Episode>
</Trans>

Kui soovin uuesti käivitada kestuse mõõtmisega, siis kasutan käsklust:

Measure-Command { az container start --resource-group tuvastusResourceGroup --name tuvastus6m }

Tulemus:

Days : 0
Hours : 0
Minutes : 8
Seconds : 43
Milliseconds : 367
Ticks : 5233673801
TotalDays : 0,00605749282523148
TotalHours : 0,145379827805556
TotalMinutes : 8,72278966833333
TotalSeconds : 523,3673801
TotalMilliseconds : 523367,3801

See tarkvara jookseb üllatavalt kaua, samas tuvastuse kvaliteet on üllatavalt hea.

Enda otsingumootor ehk kuidas otsida infot staatiliselt veebisaidilt (Apache Solr ja Nutch)

· 6 min lugemine
Infokiir OÜ

Staatilisel veebisaidil on omad eelised: see on lihtsam, kiirem ja turvalisem kui dünaamiline sait. Nii nagu staatilist veebisaiti tehes, võib koostada ka dokumendikogu, kasutades markdown süntaksit.

Kuidas aga korraldada otsing, kui soovime dokumente hoida vaid sisevõrgus? Keegi ei keela enda otsingumootori püstipanekut. Toon siin lihtsa näite, kuidas seda teha Apache Solr ja Apache Nutch abil. Siintoodud juhend on Linux keskkonnas, kuid see töötab ka näiteks WSL keskkonnas.

Internetis on üsna hea lihtne juhend: https://factorpad.com/tech/solr/tutorial/solr-web-crawl.html. Ainuke häda on see, et veebisaidi sisu allalaadides -recursive võtmega kipub ilmuma veateade "[Fatal Error] :1:1: Content is not allowed in prolog." Selleks, et sellest üle saada, kasutame Apache Nutch-i.

Kuna lihtsasti mõistetavat ja töötavat õpetust oli raske leida, panen siis selle nüüd kirja.

tiit@tiit-Virtual-Machine:~$ cd
tiit@tiit-Virtual-Machine:~$ mkdir solr
tiit@tiit-Virtual-Machine:~$ cd solr
tiit@tiit-Virtual-Machine:~/solr$ wget http://www-us.apache.org/dist/lucene/solr/7.2.0/solr-7.2.0.tgz
tiit@tiit-Virtual-Machine:~/solr$ tar xf solr-7.2.0.tgz
tiit@tiit-Virtual-Machine:~/solr$ cd solr-7.2.0/
tiit@tiit-Virtual-Machine:~/solr/solr-7.2.0$ bin/solr start
tiit@tiit-Virtual-Machine:~/solr/solr-7.2.0$ bin/solr create_core -c infokiir
WARNING: Using _default configset. Data driven schema functionality is enabled by default, which is
NOT RECOMMENDED for production use.

To turn it off:
curl http://localhost:8983/solr/infokiir/config -d '{"set-user-property": {"update.autoCreateFields":"false"}}'

Created new core 'infokiir'
tiit@tiit-Virtual-Machine:~/solr/solr-7.2.0$

Veendume ka, et meil oleks java installeeritud:

tiit@tiit-Virtual-Machine:~/solr/solr-7.2.0$ java -version
openjdk version "1.8.0_151"
OpenJDK Runtime Environment (build 1.8.0_151-8u151-b12-0ubuntu0.16.04.2-b12)
OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)

Juhul, kui JAVA_HOME ei ole väärtustatud, siis teen seda käsklusega:

export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64

Edasi:

tiit@tiit-Virtual-Machine:~/solr/solr-7.2.0$ cd
tiit@tiit-Virtual-Machine:~$ mkdir nutch
tiit@tiit-Virtual-Machine:~$ cd nutch/
tiit@tiit-Virtual-Machine:~/nutch$ wget http://www-eu.apache.org/dist/nutch/1.14/apache-nutch-1.14-bin.tar.gz
--2018-01-08 14:04:20-- http://www-eu.apache.org/dist/nutch/1.14/apache-nutch-1.14-bin.tar.gz
Lahendan www-eu.apache.org (www-eu.apache.org)... 195.154.151.36, 2001:bc8:2142:300::
Loon ühendust serveriga www-eu.apache.org (www-eu.apache.org)|195.154.151.36|:80... ühendus loodud.
HTTP päring saadetud, ootan vastust... 200 OK
Pikkus: 249107211 (238M) [application/x-gzip]
Salvestan: `apache-nutch-1.14-bin.tar.gz'

apache-nutch-1.14-bin.tar.gz 100%[=============================================================================================>] 237,57M 5,30MB/s in 48s

2018-01-08 14:05:09 (4,93 MB/s) - `apache-nutch-1.14-bin.tar.gz' salvestatud [249107211/249107211]

tiit@tiit-Virtual-Machine:~/nutch$ tar xf apache-nutch-1.14-bin.tar.gz
tiit@tiit-Virtual-Machine:~/nutch$ cd apache-nutch-1.14/

Proovin, kas crawl käivitub:

tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$ bin/crawl
Usage: crawl [-i|--index] [-D "key=value"] [-w|--wait] [-s <Seed Dir>] <Crawl Dir> <Num Rounds>
-i|--index Indexes crawl results into a configured indexer
-D A Java property to pass to Nutch calls
-w|--wait NUMBER[SUFFIX] Time to wait before generating a new segment when no URLs
are scheduled for fetching. Suffix can be: s for second,
m for minute, h for hour and d for day. If no suffix is
specified second is used by default.
-s Seed Dir Path to seeds file(s)
Crawl Dir Directory where the crawl/link/segments dirs are saved
Num Rounds The number of rounds to run this crawl for
tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$

Edasi seadistame mõned parameetrid:

tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$ nano conf/nutch-site.xml

Kopeerin "configuration" tag-de vahele (sisu laenatud veebisaidilt http://opensourceconnections.com/blog/2014/05/24/crawling-with-nutch/):

<property>
<name>http.agent.name</name>
<value>MyBot</value>
<description>MUST NOT be empty. The advertised version will have Nutch appended.</description>
</property>
<property>
<name>http.robots.agents</name>
<value>MyBot,*</value>
<description>The agent strings we'll look for in robots.txt files,
comma-separated, in decreasing order of precedence. You should
put the value of http.agent.name as the first agent name, and keep the
default * at the end of the list. E.g.: BlurflDev,Blurfl,*. If you don't, your logfile will be full of warnings.
</description>
</property>
<property>
<name>fetcher.store.content</name>
<value>true</value>
<description>If true, fetcher will store content. Helpful on the getting-started stage, as you can recover failed steps, but may cause performance problems on larger crawls.</description>
</property>

<property>
<name>fetcher.max.crawl.delay</name>
<value>-1</value>
<description>
If the Crawl-Delay in robots.txt is set to greater than this value (in
seconds) then the fetcher will skip this page, generating an error report. If set to -1 the fetcher will never skip such pages and will wait the amount of time retrieved from robots.txt Crawl-Delay, however long that might be.
</description>
</property>

<!-- Applicable plugins-->
<property>
<name>plugin.includes</name>
<value>protocol-http|urlfilter-regex|parse-(html|tika|metatags)|index-(basic|anchor|metadata)|query-(basic|site|url)|response-(json|xml)|summary-basic|scoring-opic|indexer-solr|urlnormalizer-(pass|regex|basic)</value>
<description> At the very least, I needed to add the parse-html, urlfilter-regex, and the indexer-solr.
</description>
</property>
```![](2018-01-08-14-54-15.png)

```bash
tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$ nano urls/seed.text

Lisan siia rea:

http://www.infokiir.ee

Kommenteerin välja viimase rea ja lisan:

#+.
+^https?://([a-z0-9-]+\.)*www\.infokiir\.ee/

See on vajalik selleks, et me püsiks www.infokiir.ee veebisaidil ega hakkaks alla laadima väliseid viidatud veebisaite.

Veebisaidi sisu allalaadimine käib kahes etapis. Kõigepealt käivitan:

tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$ bin/crawl -s urls crawl/ 2

Seejärel:

tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$ bin/nutch solrindex http://localhost:8983/solr/infokiir crawl/crawldb/ crawl/segments/*
Segment dir is complete: crawl/segments/20180108144502.
Segment dir is complete: crawl/segments/20180108144521.
Indexer: starting at 2018-01-08 14:48:13
Indexer: deleting gone documents: false
Indexer: URL filtering: false
Indexer: URL normalizing: false
Active IndexWriters :
SOLRIndexWriter
solr.server.url : URL of the SOLR instance
solr.zookeeper.hosts : URL of the Zookeeper quorum
solr.commit.size : buffer size when sending to SOLR (default 1000)
solr.mapping.file : name of the mapping file for fields (default solrindex-mapping.xml)
solr.auth : use authentication (default false)
solr.auth.username : username for authentication
solr.auth.password : password for authentication


Indexing 6/6 documents
Deleting 0 documents
Indexer: number of documents indexed, deleted, or skipped:
Indexer: 6 indexed (add/update)
Indexer: finished at 2018-01-08 14:48:16, elapsed: 00:00:02
tiit@tiit-Virtual-Machine:~/nutch/apache-nutch-1.14$

Nüüd vaatan tulemust:

Otsing:

Linke:

https://et.wikipedia.org/wiki/Markdown

https://lucene.apache.org/solr/

http://nutch.apache.org/

https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux

https://factorpad.com/tech/solr/tutorial/solr-web-crawl.html

http://opensourceconnections.com/blog/2014/05/24/crawling-with-nutch/

https://lobster1234.github.io/2017/08/14/search-with-nutch-mongodb-solr/