Skip Ribbon Commands
Skip to main content

Ondrej Sevecek's Blog

:

Engineering and troubleshooting by Directory Master!
Ondrej Sevecek's Blog > Posts > Jak si pomocí šetset PowerShellů zabetonovat a následně vyrestartovat počítač
září 26
Jak si pomocí šetset PowerShellů zabetonovat a následně vyrestartovat počítač

Dneska mi dorazil takovýhle zajímavý dotaz:

"Aplikacia pri urcitom evente zavola nespecifikovany PowerShell script ktory nasledne danu informaciu zapise do suboru (par bajtov) (resp. uvazuje sa aj o DB). A tu prichadza problem, je mozne taketo nieco paralene zavolat cca 500-600x za sekundu (tj. jeden script by musel zbehnut do cca 2ms?) Pocitame samozrejme s tym ze zapis do identickeho suboru je vyluceny takze v pripade takejto poziadavky prichadza do uvahy iba externa DB. Je to extremny pripad ktory v realnej situacii s velkou pravdepodobnostou nenastane – no poziadavka je otestovat to z ich aplikacie."

A protože mě to taky zajímalo, tak jsem si rovnou naprogramoval malinký skriptík, který zapisuje nějaká malinká data do souboru. Aby ten skriptík mohl běžet ve více instancích, musel jsem do něho přidat synchronizaci pomocí mutexu, což je mimochodem zajímavý příklad.

$mutex = New-Object System.Threading.Mutex($false, "someDataIntoFile")

[void] $mutex.WaitOne()

$logFile = "$env:Temp\someDataInfoFile.txt"
$logFileOriginalSize = (Get-Item $logFile -EA SilentlyContinue).Length

('{0}' -f (Get-Date)) | Out-File $logFile -Append
$logFileOriginalSize | Out-File $logFile -Append
$args[0] | Out-File $logFile -Append
'---------------' | Out-File $logFile -Append

[void] $mutex.ReleaseMutex()

Tenhle skript by měl být snad jasný. Na začátku si počkám, než dostanu mutex, abych mohl zapsat do souboru výhradně a tudíž konzistentně.

Skrip si uložte do nějakého PS1 souboru.

Jenže já tenhle skript potřebuju spustit současně 600x. Na to jsem si udělal malinký BAT soubor, který to prostě spustít tak rychle jak to jen jde právě šetset krát. Neříkám, že za sekundu, ale to není podstatné. Spustí to všechno co nejrychleji to jde. Rychleji to tedy nejde. Jestli to spouštění nebude trvat sekundu (to nebude :-)) tak aspoň víme, že to nejde.

Ale to neva. Necháme je spustit. Všechny poběží, počkají až se dostanou na řadu a zapíšou do souboru svoji vysněnou hodnotu. Zapisuji tam i čas, takže nakonec, až všech šet set PowerShelláčků skončí, tak v souboru bude vidět první a poslední datum zápisu a z toho půjde krásně zjistit, jak dlouho to trvalo.

BAT soubor následuje. Jediné co musíte, je umístit ho do stejného adresáře jako ten původní PS1 soubor a hlavně ho pojmenovat stejně, jako ten PS1 soubor.

FOR /L %%i IN (1,1,600) DO (START powershell -ExecutionPolicy Bypass -File %~d0%~p0%~n0.ps1 "Testovaci vstupni data")

A jak to všechno dopadlo na mém notebooku?

Akce se rozjela. A počítač vytuhnul. Chvilku byl vytuhnutý. A potom se restartoval :-)

Po novém startu jsem zkontroloval onen soubor. Během celé akce se podařilo zapisovat jen 1 minutu a 8 sekund. Potom to zřejmě vytuhlo. Během této doby dokončilo svoji práci cca 40 PowerShell procesů.

Takže to v provozu nezkoušejte :-)

Comments

Re: Jak si pomocí šetset PowerShellů zabetonovat a následně vyrestartovat počítač

jako boční efekt, jak se dívám, se mi taky zvětšil stárnkovací soubor 2 GB :-)
ondass on 26.9.2013 11:31

:)

To znie dobre. Takto sme sa zabali v cmd.exe cez "%0|%0" a v linuxe cez ":(){ :|:& };:"

Robili sme to hlavne v skole ked sa nam nechcelo makat a tak sme dali server do mrtva :)
Ondrej Zilinec on 26.9.2013 14:12

powershell

problem neni v PowerShell scriptu, ale v tom mnozstvi spustenych powershell.exe. Pustil jsem jen cmd> FOR /L %%i IN (1,1,600) DO (START powershell.exe) a po chvilce PC zatuhlo a nereagovalo a vzpamatovalo se az po >5min, kdy na mne vyskakaly chyby

---------------------------
powershell.exe - System Error
---------------------------
A new guard page for the stack cannot be created.

---------------------------
powershell.exe - Application Error
---------------------------
The application was unable to start correctly (0xc000012d). Click OK to close the application.


a v tom CMD, kde jsem to pustil bylo

C:\Users\user>(START powershell )
Cannot find function ext-ms-win-cmd-util-l1-1-0.dll:ShellExecuteWorker.
Insufficient system resources exist to complete the requested service.
The system cannot execute the specified program.

C:\Users\user>The system cannot write to the specified device.
START powershell )
The system cannot execute the specified program.


v TASKLIST to psalo powershell asi 300x a kdyz uz to reagovalo, tak to zralo 2.5 GB RAM, CPU asi 5%, HDD 100%
VasekB on 26.9.2013 20:07

Re: Jak si pomocí šetset PowerShellů zabetonovat a následně vyrestartovat počítač

jj, plně souhlasím. ani já bych nevinil sám PowerShell. Prostě jde o přetížení prostředků. A ano, zobrazilo se mi taky několik oken ohledně neschopnosti už další procesy spouštět.

Šlo mi prostě o to, vyzkoušet, co to snese. A jestli je rozmuný nápad spouštět tolik PowerShell.exe v rychlém sledu.

Co bych ale nečekal je restart mého počítače. To si snad NT jádro (blahé paměti) nemůže dovolit? Chápal bych, že se to celé zabetonuje, ale že to po několika minutách všechno v klidu skončí, nebo prostě nenaskočí a případně vytimeoutuje.
ondass on 26.9.2013 20:31

Nema to byt jinank?

Nechci teď narychlo polemizovat - četl jsem to jen jednou z rychlíku, ale takto se podle mě nejedná o pravé simultánní spuštění tak, aby to musel synchronizovat mutex. Možná mám mezery ve znalostech, ale START spustí příkaz v samostatným vlákně(tedy bude běžet 600 potomků od procesu CMD). O sdílení přístupu k souboru by se měl tedy starat OS, nikoli script "zevnitř". Aby to dělalo to co chcete, tak by se podle mě měl ten fork udělat 600x uvnitř scriptu. Potom se musíte starat o synchronizaci programově zevnitř scriptu.
A spadlo to podle mě proto, že PS je swiňa moloch a tím 600x START-em si musel 600x alokovat prostředí, zdroje a tak.
Ale jak říkám, možná se hluboce pletu.
RaT on 1.10.2013 13:41

Aha

Aha, no tak jsem dočetl i diskusi :o)
RaT on 1.10.2013 13:46

Add Comment

Title


Pole Title nemusíte vyplňovat, doplní se to samo na stejnou hodnotu jako je nadpis článku.

Author *


Pole Author nesmí být stejné jako pole Title! Mám to tu jako ochranu proti spamu. Roboti to nevyplní dobře :-)

Body *


Type number two as digit *


Semhle vyplňte číslici dvě. Předchozí antispemové pole nefunguje úplně dokonale, zdá se, že jsou i spamery, které pochopily, že je občas potřeba vyplnit autora :-)

Email


Emailová adresa, pokud na ni chcete ode mě dostat odpověď. Nikdo jiný než já vaši emailovou adresu neuvidí.

Attachments