Jak uruchamiać i odbierać zadania oraz zarządzać nimi w programie Windows PowerShell 2.0?
Skrypciarze odpowiadają na Wasze pytania
Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy. |
Jak uruchamiać i odbierać zadania oraz zarządzać nimi w programie Windows PowerShell 2.0?
Cześć, Skrypciarze! Zastanawiałem się nad napisaniem skryptu z użyciem klasy system.thread platformy .NET, umożliwiającego jednoczesne wykonywanie kilku czynności. Chcę przeprowadzić kwerendę usług domenowych usługi Active Directory, która będzie wymagać sporo czasu. Chciałbym, aby w czasie oczekiwania na zakończenie kwerendy skrypt wykonywał inne zadania. Stąd też pomysł użycia klasy system.thread. Jeśli zastosuję funkcję, kod będzie można bez większego trudu wykorzystać ponownie. Jak sądzicie? Czy to wykonalne? Czy zdarzyło się Wam kiedyś napisać taki skrypt?
-- FS
Cześć, FS! Czołem, tutaj skrypciarz Ed Wilson. Dziś rano popijam angielską czarną herbatę z laską cynamonu i słucham Marizy śpiewającej fado. W Charlotte jest chłodno i wilgotno, a kiedy zamknę oczy, nieomal czuję łagodną bryzę Morza Śródziemnego i czuję zapach ciastek pastel de nata. Kilka lat temu spędziłem miesiąc w Lizbonie, prowadząc warsztaty z programu Windows PowerShell. Wspominam ten czas znakomicie. Oto zdjęcie starej latarni, które zrobiłem jadąc nadmorską szosą z Luisem — moim przyjacielem i opiekunem w Portugalii.
W Lizbonie zresztą nauczyłem się dorzucać laskę cynamonu do herbaty. Portugalczycy rzecz jasna doprawiają w ten sposób kawę, ale odważyłem się kiedyś zrobić to z herbatą i wyszło znakomicie. Ciekawe, że w ciągu tygodnia kilkoro uczestników warsztatów przerzuciło się także na herbatę z laską cynamonu, stosując przejęty ode mnie trik, który ja wcześniej przejąłem od nich.
A przechodząc do Twojego pytania, FS: Nie zdarzyło mi się jeszcze napisać skryptu z użyciem klasy system.thread, ale zastanawiałem się nad tym. Nigdy się jednak do tego nie zabrałem, ponieważ w programie Windows PowerShell 2.0 wprowadzono pojęcie zadań. Przy użyciu zadania — czy to w konsoli programu Windows PowerShell, czy w skrypcie — można rozpocząć długotrwałą procedurę i natychmiast przejść do wykonywania innych działań.
Aby rozpocząć zadanie, należy najpierw włączyć usługi zdalne. Może to dziwne, ale program Windows PowerShell do uruchamiania zadań używa infrastruktury usług zdalnych. Aby włączyć usługi zdalne, należy użyć apletu polecenia Enable-PSRemoting. Należy pamiętać, że to polecenie należy uruchamiać z uprawnieniami administratora. Należy więc kliknąć prawym przyciskiem myszy ikonę programu Windows PowerShell i wybrać polecenie Uruchom jako administrator. Prawdopodobnie (zależy to od ustawień kontroli konta użytkownika) zostanie wyświetlony monit z pytaniem „Czy chcesz zezwolić następującemu programowi na wprowadzenie zmian na tym komputerze?”. Monit jest nieco mylący, ponieważ na razie nic jeszcze nie zrobiliśmy, więc program Windows PowerShell nie wprowadza żadnych zmian w systemie. Po uruchomieniu programu Windows PowerShell z uprawnieniami administratora należy użyć apletu polecenia Enable-PSRemoting do skonfigurowania programu Windows PowerShell w sposób umożliwiający korzystanie z usług zdalnych. Zostanie wyświetlony monit (chyba że zostanie użyty parametr –Force).
Uruchomienie apletu polecenia Enable-PSRemoting z parametrem –Force spowoduje, że program Windows PowerShell wyświetli takie dane wyjściowe, jak widać poniżej.
Po skonfigurowaniu usług zdalnych można rozpocząć nowe zadanie programu Windows PowerShell przy użyciu apletu polecenia Start-Job. Polecenie to jest uruchamiane jako zadanie umieszczane w bloku skryptu. Zadania otrzymują nazwy nadawane w sposób sekwencyjny: Job1, Job2 itd. Widać to poniżej:
PS C:\> Start-Job -ScriptBlock { get-process }
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Running True localhost get-process
PS C:\>
Zadania otrzymują identyfikatory, które także mają nazwy nadawane sekwencyjnie. Pierwsze zadanie utworzone w konsoli programu Windows PowerShell ma zawsze identyfikator 1. W celu uzyskania informacji o zadaniu można używać jego indentyfikatora lub nazwy. Widać to poniżej:
PS C:\> Get-Job -Name job1
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Completed True localhost get-process
PS C:\> Get-Job -Id 1
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Completed True localhost get-process
PS C:\>
Po ukończeniu zadania można je odebrać. Aplet polecenia Receive-Job zwraca takie same informacje, co w przypadku, gdy zadanie nie zostanie użyte. Poniżej widać dane wyjściowe zadania Job1 (w formie skróconej, aby zaoszczędzić miejsce):
PS C:\> Receive-Job -Name job1
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
62 9 1672 6032 80 0.00 1408 apdproxy
132 9 2316 5632 62 1364 atieclxx
122 7 1716 4232 32 948 atiesrxx
114 9 14664 15372 48 1492 audiodg
556 62 53928 5368 616 3.17 3408 CCC
58 8 2960 7068 70 0.19 928 conhost
32 5 1468 3468 52 0.00 5068 conhost
784 14 3284 5092 56 416 csrss
529 27 2928 17260 145 496 csrss
182 13 8184 11152 96 0.50 2956 DCPSysMgr
135 11 2880 7552 56 2056 DCPSysMgrSvc
... (dane wyjściowe w formie skróconej)
Po odebraniu zadania dane znikają — chyba że zapiszemy je w zmiennej. Ilustruje to kod widoczny poniżej:
PS C:\> Receive-Job -Name job1
PS C:\>
Nieco zamieszania może wprowadzić fakt, że zadanie ciągle istnieje, a aplet polecenia Get-Job nadal pobiera informacje o nim. Widać to poniżej:
PS C:\> Get-Job -Name job1
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Completed False localhost get-process
PS C:\>
Zalecałbym więc, aby po zakończeniu korzystania z obiektu job używać apletu polecenia Remove-Job do usunięcia pozostałości zakończonych zadań. Pozwoli to uniknąć zamieszania związanego z aktywnymi zadaniami, zakończonymi zadaniami i zadaniami oczekującymi na przetworzenie. Po usunięciu zadania próba pobrania informacji o nim przy użyciu apletu polecenia Get-Job zwraca błąd — zadanie już nie istnieje. Widać to poniżej:
PS C:\> Remove-Job -Name job1
PS C:\> Get-Job -Name job1
Get-Job : The command cannot find the job because the job1 name was not found. Verify the value of the Name parameter,
and then try the command again.
At line:1 char:8
+ Get-Job <<<< -Name job1
+ CategoryInfo : ObjectNotFound: (job1:String) [Get-Job], PSArgumentException
+ FullyQualifiedErrorId : JobWithSpecifiedNameNotFound,Microsoft.PowerShell.Commands.GetJobCommand
PS C:\>
Pracując z apletami poleceń związanymi z zadaniami, przeważnie nadaję zadaniom własne nazwy. Zadanie zwracające obiekty procesów przy użyciu apletu polecenia Get-Process może otrzymać np. nazwę getProc. Kontekstowe nadawanie nazw może być bardziej praktyczne od korzystania z takich nazw, jak Job1 czy Job2. Nie ma problemu, jeśli nazwy zadań są długie, ponieważ można ograniczyć potrzebę wpisywania, stosując symbole wieloznaczne. Odbierając zadanie należy pamiętać o przechowaniu zwróconych obiektów w zmiennej. Widać to poniżej:
PS C:\> Start-Job -Name getProc -ScriptBlock {get-process}
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
3 getProc Running True localhost get-process
PS C:\> Get-Job -Name get*
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
3 getProc Completed True localhost get-process
PS C:\> $procObj = Receive-Job -Name get*
PS C:\>
Mając zwrócony obiekt w zmiennej, można go używać z innymi apletami poleceń programu Windows PowerShell. Warto pamiętać, że obiekt jest rozszeregowany. Widać to poniżej — używam znaków gm jako aliasu apletu polecenia Get-Member:
PS C:\> $procObj | gm
TypeName: Deserialized.System.Diagnostics.Process
Oznacza to, że nie wszystkie elementy członkowskie obiektu System.Diagnostics.Process platformy .NET są dostępne. Metody dostępne normalnie widać poniżej (gps to alias apletu polecenia Get-Process, gm to alias apletu polecenia Get-Member, a znaki –m wystarczają, aby jednoznacznie wskazać parametr –membertype w wierszu konsoli programu Windows PowerShell):
PS C:\> gps | gm -m method
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
BeginErrorReadLine Method System.Void BeginErrorReadLine()
BeginOutputReadLine Method System.Void BeginOutputReadLine()
CancelErrorRead Method System.Void CancelErrorRead()
CancelOutputRead Method System.Void CancelOutputRead()
Close Method System.Void Close()
CloseMainWindow Method bool CloseMainWindow()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose Method System.Void Dispose()
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Kill Method System.Void Kill()
Refresh Method System.Void Refresh()
Start Method bool Start()
ToString Method string ToString()
WaitForExit Method bool WaitForExit(int milliseconds), System.Void WaitForExit()
WaitForInputIdle Method bool WaitForInputIdle(int milliseconds), bool WaitForInputIdle()
Poniżej widać metody obiektów rozszeregowanych; używam takiego samego polecenia, co poprzednio:
PS C:\> $procObj | gm -m method
TypeName: Deserialized.System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
ToString Method string ToString(), string ToString(string format, System.IFormatProvider formatProvider)
PS C:\>
Poniżej widać listę apletów polecenia, w których występuje fragment Job (tzn. powiązanych z zadaniami):
PS C:\> Get-Command -Noun job | select nameName----Get-JobReceive-JobRemove-JobStart-JobStop-JobWait-JobPS C:\>
PS C:\> Get-Command -Noun job | select name
Name
----
Get-Job
Receive-Job
Remove-Job
Start-Job
Stop-Job
Wait-Job
PS C:\>
Jak widać, omówiliśmy cztery spośród sześciu apletów poleceń. To już wszystkie podstawowe informacje o uruchamianiu i odbieraniu zadań oraz zarządzaniu nimi. Zapraszamy jutro na kolejny artykuł z serii poświęconej obsłudze zadań.
Jeśli chcecie szybciej dowiadywać się, jakim tematom poświęcone będą kolejne artykuły, śledźcie nas w serwisie Twitter lub Facebook. W razie jakichkolwiek pytań piszcie do nas na adres scripter@microsoft.com lub publikujcie na oficjalnym forum skrypciarzy. Do zobaczenia jutro.
Skrypciarze Ed Wilson i Craig Liebendorfer
Do początku strony |