Category: Początki
Scripting Games 2012–Odliczanie: 4…
| 2012-03-29 | Posted by Bartek Bielawski under Początki, Polskie blogi IT, pomoc, ScriptingGames, SG2012 |
|

4 dni… tylko tyle zostało do rozpoczęcia Scripting Games. Już za kilkadziesiąt godzin ludzie z całego świata zaczną próbować swoich sił w zadaniach, które dla nich przygotował Ed Wilson. Poshcode zacznie wypełniać się tegorocznymi skryptami. Dla mnie był to zawsze szczególnie pracowity czas, w tym roku pewnie będzie to praca jeszcze intensywniejsza: czytanie, testowanie, ocenianie, komentowanie cudzych skryptów, jak sądzę, jest bardziej zasobożernym procesem, niż ich pisanie. Liczę jednak, że satysfakcja będzie proporcjonalnie większa. Zanim to jednak nastąpi – czas na przedostatnią odsłonę tego cyklu, który z założenia ma Was zachęcić do udziału Scripting Games. Dziś:
4 miejsca, gdzie znajdziecie pomoc
Pewnie jak co roku – niektóre zadania będą trudniejsze, niektóre – łatwiejsze. Dwa lata temu wszyscy mogliśmy widzieć to, co napisali inni. Od zeszłego roku – takiej możliwości uczestnicy nie mają. Dlatego dziś opiszę gdzie szukać pomocy w sytuacji, gdy jakiś element zadania stanie nam niby ość w gardle. Naturalnie, nikt za nas nie napisze rozwiązania. Ale jeśli gdzieś “utkniemy” to z całą pewnością możemy liczyć na pomoc innych. A gdzie tej pomocy szukać…?
4… Hey! Scripting Guys! Blog
Ed wkłada wiele pracy nie tylko w przygotowanie zadań, ale również w przygotowanie uczestników. Na jego blogu jest dedykowany pod tegoroczne Scripting Games “Study Guide”. To nie tylko źródło wiedzy, to również swoista wskazówka: czego można się spodziewać w ramach poszczególnych konkurencji. Dla osób “zielonych” w temacie ciekawym źródłem wiedzy (w dodatku świetnie napisanym) będą artykuły z udziałem Scripting Wife. Ponieważ żona Eda nie jest “geekiem”, jej punkt widzenia może służyć tym, którzy w PowerShellu stawiają pierwsze kroki. Do tego dwie serie zarejestrowanych webcastów (w sumie 10 godzin pełnych informacji dotyczących PowerShella). Nie wspominając o setkach innych artykułów: każdy z nich może zawierać informacje pomocne przy rozwiązywaniu zadań. Pomijając same Scripting Games, to chyba jedno z lepszych źródeł wiedzy o PowerShellu dostępnych online (i naturalnie za darmo). Polecam!
3… IRC
Usługa zapomniana i porzucona przez wielu, obca i niezrozumiała dla pozostałych.
A jednak: na IRC istnieje miejsce, gdzie można spotkać miłośników PowerShella niemal codziennie, o dowolnej porze dnia i nocy. Ponieważ spotykają się tam ludzie z Europy, Ameryki, Australii, Azji, być może również Afryki (tu pewności nie mam) – można spodziewać się tam kogoś “aktywnego” o dowolnej porze dnia i nocy. Co jest dość istotne i pomocne: by tam się dostać nie trzeba instalować klienta irca: jeśli chcesz najpierw przekonać się, czy to w ogóle dla Ciebie możesz skorzystać z udostępnianej przez freenode wersji web – sam z niej korzystałem kilkakrotnie. Jestem tam częstym gościem, można tam też spotkać innych MVP, MCC lub po prostu entuzjastów PowerShella, którzy lubią rozmawiać o nim i dzielić się swoją wiedzą. Oczywiście, wiele tematów nie ma z nim nic wspólnego, w końcu to IRC…
Nikt nie moderuje rozmów by zagwarantować, że wszystkie będą on-topic. Temat Scripting Games często tam wypływa. Można też czasem uzyskać pomoc odnośnie miejsca, gdzie umieszczane są skrypty: Joel (Jaykul), autor i właściciel poshcode.org, jest tam bardzo częstym gościem. Czy może raczej gospodarzem. ![]()
2… Twitter
O wiele nowocześniejszy wynalazek do kontaktowania się z innymi ludźmi. Moim zdaniem – często zbyt ograniczony (lubię się rozpisać, więc 140 znaków w 9 przypadkach na 10 to dla mnie za mało). Plusem niewątpliwym jest fakt, że na Twitterze znajdziecie wielu ekspertów w zakresie PowerShella, którzy na IRCa nie zaglądają. Jeśli masz pytanie – wyślij je oznaczając tagiem #PowerShell – szansa, że uzyskasz odpowiedź jest bliska pewności. Scripting Games mają swój własny tag: #2012SG. To dwa sposoby, by uzyskać pomoc, gdy w czasie pisania skryptu napotkasz “ścianę”. Jeśli nie korzystałeś z Twittera to mogę śmiało zachęcić, wiele razy rozwiązywałem problemy/ szukałem tam rozwiązania. W zasadzie niezmiernie rzadko wysyłam informację o rzeczach nietechnicznych. Przyda się zarówno w trakcie Scripting Games, jak i po ich zakończeniu. ![]()
1… Google
Nie napiszę Bing, bo po prostu nie korzystam z niego.
Z Google korzystam bardzo często rozwiązując problemy jakie napotykam w pracy. W czasie ostatnich Scripting Games również korzystałem z niego wielokrotnie. Nie wszystko można znaleźć w Get-Help, bo nie wszystko w Scripting Games skupia się na PowerShellu – czasem musimy dowiedzieć się nowych rzeczy o samym systemie Windows, o Active Directory, o platformie .NET, by stworzyć skrypt spełniający kryteria zadania. Jedna rada: jeśli traficie na coś nieoczywistego przy pomocy google – dla dobra własnego i wszystkich ludzi, którzy w przyszłości korzystać będą z Waszego skryptu, umieśćcie w nim komentarz z linkiem do strony, która pomogła Wam znaleźć rozwiązanie. Po co powtarzać googlowanie w przyszłości?
Podsumowanie
Nasz cykl powoli dobiega końca. Ostatnia część będzie poświęcona kategoriom, mam nadzieję, że pomoże ona niezdecydowanym podjąć jedyną słuszną decyzję. ![]()
PowerShell–efektywnie(j), część 9
| 2012-03-17 | Posted by Bartek Bielawski under formatowanie, moduły, najlepsze praktyki, Początki, Polskie blogi IT |
|
Dziś wracamy do tematu modułów w PowerShellu. Uznałem, że jeśli teraz nie przysiądę i nie dokończę tego cyklu – to nie zrobię tego w najbliższej, dającej się przewidzieć przyszłości. Poprzednio opisałem podstawy tworzenia modułów, dziś – pora na manifest i pliki definiującej typy i format ich wyświetlania.
Manifest to prościutki skrypt PowerShella. W zasadzie zawiera on jedną tablicę skrótów z kluczami odpowiadającymi właściwościom/ ustawieniom modułu. Korzystamy przy tym z rozszerzenia .psd1, które wykorzystywane jest w zasadzie tylko w tym celu.
Nasz manifest
Manifest najprościej jest stworzyć przy pomocy polecenia New-ModuleManifest. Polecenie to spyta nas w zasadzie o wszystkie elementy, które do stworzenia manifestu są niezbędne. Większość kluczy ma dość jednoznaczne nazwy, zatrzymać się chciałbym w zasadzie przy dwóch: TypesToProcess i FormatsToProcess.
Oba klucze przyjmują tablicę stringów, w której zawrzeć możemy ścieżkę do wszystkich plików .ps1xml dotyczących naszego modułu. Pliki te służą definiowaniu dla istniejącego typu (czy to typu “prawdziwego”, czy też “wirtualnego”, stworzonego przez nas na potrzeby modułu) dodatkowych właściwości i metod (TypesToProcess) oraz sposobów wyświetlania (FormatsToProcess). Pliki .ps1xml to całkowicie odrębny temat, w dodatku dość obszerny. W wielkim skrócie można napisać, że są to pliki XML o zdefiniowanym schemacie, dzięki którym możemy “centralnie” przeprowadzać operacje podobne do tych, które wykonujemy przy pomocy poleceń takich jak Format-Table, czy Add-Member.
Manifest pozwoli nam powiązać te pliki z naszym modułem, dzięki czemu obiekty tworzone przy jego pomocy będą wyglądać tak, jak my sobie tego zażyczymy. By jednak obiekty przez nas generowane wyróżnić z tłumu innych, zwłaszcza jeśli nie chcemy dodawać “prawdziwego” typu poleceniem Add-Type, musimy skorzystać z jednej, dość prostej techniki, by nasze obiekty miały stosowną “metkę”.
Pseudo-typ i pliki PS1XML.
Skuteczne korzystanie z plików typów/ formatów wymaga od nas trzech rzeczy. Po pierwsze: funkcje tworzące nasz wymarzony obiekt muszą go odpowiednio “oznakować”:
function Get-Foo { param ( [Parameter(ValueFromPipeline = $true)] [string]$Bar ) process { $Out = New-Object PSObject -Property @{ One = 1 Two = $Bar } $Out.PSTypeNames.Insert(0, 'Typ.Wymarzony' ) $Out } }
Druga rzecz, to dodać ten wirtualny typ do naszych plików PS1XML w odpowiednim miejscu, zarówno w pliku opisującym formatki:
<Configuration>
<ViewDefinitions>
<View>
<Name>Wymarzony.FT</Name>
<ViewSelectedBy>
<TypeName>Typ.Wymarzony</TypeName>
</ViewSelectedBy>
… jak i pliku opisującym rozszerzenia naszego typu:
<?xml version="1.0" encoding="utf-8" ?>
<Types>
<Type>
<Name>Typ.Wymarzony</Name>
<Members>
Jak widać nie wymagało to wielkiej pracy, a efekt jest zwykle zadowalający. Zamiast dość losowego wyniku i obiektu bez żadnych “specjalnych” właściwości i metod możemy uzyskać zwierza, który wyświetlany będzie w sposób dla nas wygodny i będzie gotowy wykonać dla nas wybrane przez nas zadania:
To wszystko można oczywiście zrobić również bez modułu, ale moduł czyni te operacje o wiele prostszymi i daje nam (przy pomocy pliku manifestu) bardzo dokładną kontrolę.
$Env:PSModulePath czyli o instalacji modułu
Moduły można, jak widać na załączonym zrzucie ekranu, importować bez większego trudu z dowolnego miejsca na dysku. Istnieje jednak zmienna środowiskowa, która definiuje kilka folderów, z których import będzie o wiele prostszy. PSModulePath przypomina nieco zmienną PATH: ma identyczną składnię, lista folderów jest rozdzielona średnikami:
Poprawna struktura:
Ponieważ zdarzyć się może, że zrobimy literówkę w nazwie pliku lub folderu (a raczej ze względu na to, że sam kiedyś zmarnowałem sporo czasu próbując ustalić, czemu jeden z moich modułów nie działał poprawnie) stworzyłem wieki temu funkcję, która sprawdzi poprawność tych nazw i jeśli się na to zdecydujemy – błędy te naprawi. Na tym kończę serię dotyczącą efektywnego PowerShella. Troszkę się zeszło… ![]()
2012 Windows PowerShell Scripting Games
| 2012-02-19 | Posted by Bartek Bielawski under Początki, Polskie blogi IT, ScriptingGames, SG2012 |
|
Jeśli ktoś jeszcze o tym nie słyszał: już wkrótce rozpocznie się kolejna edycja Scripting Games. Kolejna okazja dla każdego miłośnika PowerShella (przyszłego, bądź obecnego) by zmierzyć się z zadaniami wymyślonymi przez “The Scripting Guy(s)!”, Eda Wilsona.
Tak jak w zeszłym roku: zadania podzielone będą na dwie kategorie. Kategoria dla początkujących ma być znów – faktycznie – dla początkujących (czytaj: zadania, z którymi przeciętny użytkownik PowerShella powinien sobie poradzić w jednej linii kodu). Kategoria dla zaawansowanych, moim skromnym zdaniem, nadaje się dla wszystkich, którzy już z PowerShellem jakiś czas pracują. Oczywiście, mogą się wtedy trafić konkurencje, w których nie uda się znaleźć rozwiązania – ale przynajmniej będzie satysfakcja, gdy jednak zadanie rozwiązać się uda.
Zadań w obu kategoriach będzie 10. Będą one ogłaszane każdego dnia roboczego przez dwa tygodnie. Na każde z zadań przeznaczony jest tydzień, więc okresy przeznaczone na wykonanie poszczególnych zadań nachodzą na siebie. Wszystkie skrypty należy umieszczać na specjalnie do tego celu przygotowanej stronie w ramach poshcode.org (prawdopodobny adres: 2012sg.poshcode.org). Skryptu raz umieszczonego nie da się modyfikować. Nie da się też wysłać kilku skryptów w ramach jednej kategorii. Dobrze jest więc kilka razy przetestować skrypt, zanim go umieścimy na stronie. Skrypty innych uczestników możemy zobaczyć dopiero wtedy, gdy skończy się okres przeznaczony na ich umieszczanie – nie można więc wrzucać cudzych skryptów jako własne.
Do udziału zachęcam wszystkich – trzeba naturalnie poświęcić nieco czasu, by “sklecić” skrypt, ale ryzykujecie w zasadzie niewiele:
- szarpanie ego, gdy ktoś zbeszta Was za użycie write-host, lub coś równie “niehigienicznego”
- czas, który moglibyście spędzić na czymś przyjemniejszym
- … więcej grzechów nie pamiętam
Co możecie zyskać?
- wiedzę
- kilka skryptów, które być może uda się (po drobnych modyfikacjach) użyć w pracy – i piszę to z autopsji
- wiedzę
- radość z konkurowania z innymi
- nagrody (zarówno za osiągnięcia, jak i losowe, za sam udział)
- wiedzę
- informację zwrotną o Waszych skryptach, zarówno od sędziów, jak i innych osób (komentarze będzie mógł do skryptów dodawać każdy)
Jak widać bilans zysków i strat wypada dość jednostronnie. ![]()
Osobiście nie mogę się doczekać początku Scripting Games (2-go kwietnia 2012). Tym razem “przeskoczyłem” na drugą stronę ogrodzenia i nie będę uczestniczył, tylko oceniał.
W zeszłym roku, gdy drepcząc nerwowo w miejscu oczekiwał na ostateczny wynik, spędziłem nieco czasu komentując skrypty napisane przez innych, dlatego też cieszę się na tę zamianę ról. Dodatkowo nie ryzykuję detronizacji.
Choć to akurat nie było aż tak istotne. Czas oddać wspólnocie to, z czego sam czerpałem garściami przez ostatnie dwa lata…
Na koniec kilka linków:
2012 Windows PowerShell Scripting Games: All Links on One Page – strona, która należy dodać do ulubionych i na której będzie można odnaleźć wszystko to, co istotne
Grab the 2012 Scripting Games Badge! – stąd możecie pobrać “Dr Scripto” i ozdobić nim (kwestia gustu…) swój blog, kierując ludzi do w/w strony. Jak widać ja już to zrobiłem.
2012 Scripting Games Study Guide: A Resource for Learning PowerShell – tu znajdziecie informacje o tym, jaką wiedzę dobrze jest przyswoić przed rozpoczęciem Scripting Games, by później “trzaskać” zadania bez większego wysiłku. Zwykle wymienione tam bloki tematyczne znajdują później swoje odzwierciedlenie w zlecanych zadaniach.
Jeśli macie jakieś dodatkowe pytania – chętnie odpowiem, lub przekażę pytanie organizatorowi konkursu. Od 2 kwietnia zaczynam wypatrywać Waszych skryptów. ![]()
PowerShell–efektywniej, część 6.
| 2011-11-06 | Posted by Bartek Bielawski under najlepsze praktyki, Początki, Polskie blogi IT, Skrypty, zaawansowane funkcje |
|
W poprzedniej części opisałem składnię, dzięki której funkcja zmienia się w funkcję zaawansowaną. Dziś skupię się na tym, co z tego wynika przy używaniu takiej funkcji.
Debug i Verbose
W wielu językach – zarówno programowania jak i skryptowych – pierwszą metodą sprawdzania co poszło nie tak jest wyświetlanie na ekran informacji, które mogą pomóc ustalić, gdzie popełniliśmy błąd. To generuje dwa problemy:
- nie usunięte komunikaty pojawiają się w najmniej odpowiednim momencie
- ponowne “włączenie” komunikatów po ich usunięciu jest niemożliwe
PowerShell ma bardzo przydatną właściwość: generuje nieco więcej strumieni niż domyślne wyjście standardowe i wyjście błędów: mamy dodatkowo ostrzeżenia, informacje rozszerzone (verbose) i komunikaty pomagające debugować (debug). Komunikaty verbose i debug można z powodzeniem pozostawić (jeśli są cenzuralne
) a w razie potrzeby – włączyć na żądanie. W funkcjach zwykłych wymagałoby to zmiany $DebugPreference i $VerbosePreference na poziomie sesji. Funkcje zaawansowane dają nam możliwość użycia po prostu jednego z parametrów: –Debug lub –Verbose. Dzięki temu automagicznie zmienia się wartość odpowiedniej zmiennej i wszystkie komunikaty pojawiają się w odpowiednich strumieniach. Dodajmy więc komunikaty dotyczące zawartości naszych parametrów:
Write-Verbose "Format: $Format" Write-Verbose "Liczba: $Liczba" Write-Verbose "Slowo: $Slowo" if ($Format) { Write-Debug "Wygląda na to, że używamy liczby." }
Begin, Process, End
Funkcja w PowerShellu może mieć trzy odseparowane części, co ułatwia zdecydowanie pracę w potokach i dzięki czemu każda funkcja może działać podobnie jak prawdziwy cmdlet (jeśli chodzi o funkcjonalność, nie o wydajność). Mamy więc:
- begin gdzie można zainicjować połączenia, zdefiniować funkcje pomocnicze, przetworzyć zmienne podawane “w linii”
- process stanowiący serce funkcji działającej w rurce: tu możemy sięgnąć do parametrów pobieranych z poprzedniej komendy i przekazać informację dalej
- end który sprząta na koniec: zabija połączenia, czyści pamięć ze zbędnych elementów
Jeśli zamierzamy korzystać tylko z parametrów podawanych w linii – nasza funkcja może mieć jedno, zbiorcze “ciało”. Jeśli jednak chcemy skorzystać z pipe’a – absolutnym minimum jest dodanie części process, pozostałe dwie pozostają wówczas opcjonalne. Begin ma sens wtedy, gdy potrzebujemy pewną operację przeprowadzić dokładnie raz na początku, a wykonywanie jej dla każdego elementu wpadającego w rurkę jest stratą czasu, czy wręcz może doprowadzić do nieoczekiwanych rezultatów. End działa podobnie – tylko operacja musi mieć miejsce dokładnie raz na końcu. Cała reszta – powinna trafić do bloku process. Zaawansowane funkcje tracą wiele jeśli pozbawimy ich tej troistości.
PSCmdlet
Zaawansowane funkcja ma jeszcze jedną wielką zaletę: w jej wnętrzu dostępna jest automatyczna zmienna ($PSCmdlet), która w zasadzie daje nam dostęp do tych samych metod i właściwości, jakie ma programista piszący cmdlet w C# lub VB.NET. Na blogu zespołu PowerShell jakiś czas temu opublikowana była prosta funkcja, która pozwala zajrzeć do wnętrza tej zmiennej, sprowadza się to właściwie do:
function Test-PSCmdlet { [CmdletBinding()] param() $p = $PSCmdlet function prompt { "Test-PSCmdlet> " } $host.EnterNestedPrompt() }
Dzięki temu możemy poeksperymentować ze zmienną $p (która jest kopią $PSCdmlet). W praktyce na ogół wykorzystuje się dwa jej elementy:
- właściwość ParameterSetName – pozwala ustalić, który zestaw parametrów jest wykorzystywany
- metody ShouldProcess i ShouldContinue – pozwalają zastosować parametry WhatIf oraz Confirm.
Ponieważ budowana przez nas zaawansowana funkcja wspiera ShouldProcess (a więc metody Shoud* będą w niej dostępne), oraz założyliśmy kilka różnych zestawów parametrów, więc wykorzystamy i jedno, i drugie:
process { if ($psCmdlet.ShouldProcess( "Cel: $Slowo $Liczba", "Operacja: Wyświetl" )) { switch ($psCmdlet.ParameterSetName) { Domyslny { "{0} to moje slowo" -f $Slowo } Liczby { "Moja liczba: {0:$Format}" -f $Liczba } } } }
Ponieważ część parametrów zamierzamy opcjonalnie pobierać z rurki – możemy do nich sięgać dopiero w bloku process. Jeśli mamy dwa zestawy parametrów na ogół wystarczy zwykły if – jeśli zestawów jest więcej, opcjonalnym rozwiązaniem może okazać się switch. Jak widać operacja przeprowadzana nie jest specjalnie niebezpieczna, ale czasem jednak funkcja napisana przez nas może nieść z sobą pewne ryzyko – warto wtedy wiedzieć jak zaimplementować parametry –WhatIf i –Confirm.
I tym optymistycznym akcentem kończę temat zaawansowanych funkcji. Jeszcze tylko nasza zaawansowana funkcja w pełnej krasie:
function Get-Foo { [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High', DefaultParameterSetName = 'Domyslny' )] param ( [Parameter( Mandatory = $true, HelpMessage = 'Pomocy!', ValueFromPipeline = $true, Position = 0, ParameterSetName = 'Liczby' )] [double]$Liczba, [Parameter( Mandatory = $true, HelpMessage = 'Pomocy!', ValueFromPipelineByPropertyName = $true, Position = 0, ParameterSetName = 'Domyslny' )] [ValidatePattern('^\w+$')] [string]$Slowo, [Parameter( Position = 1, ParameterSetName = 'Liczby', Mandatory = $true, HelpMessage = 'Pomozcie mi!' )] [ValidateSet('P4','N4','C4')] [string]$Format ) begin { Write-Verbose "Format: $Format" Write-Verbose "Liczba: $Liczba" Write-Verbose "Slowo: $Slowo" if ($Format) { Write-Debug "Wygląda na to, że używamy liczby." } } process { if ($psCmdlet.ShouldProcess( "Cel: $Slowo $Liczba", "Operacja: Wyświetl" )) { switch ($psCmdlet.ParameterSetName) { Domyslny { "{0} to moje slowo" -f $Slowo } Liczby { "Moja liczba: {0:$Format}" -f $Liczba } } } } }
Następną część zamierzam poświęcić kolejnej funkcjonalności, przydatnej zarówno w funkcjach (również zaawansowanych) jak i w skryptach: pomocy generowanej w oparciu o komentarze.
PowerShell – efektywnie(j), część 4.
| 2011-10-23 | Posted by Bartek Bielawski under najlepsze praktyki, Początki, Polskie blogi IT, Skrypty, zaawansowane funkcje |
|
Troszkę to trwało nim udało mi się przysiąść do tego artykułu. Przyczyna jest prozaiczna: temat jest dość obszerny i nie wiem jak go ugryźć. Pisanie skryptów w PowerShellu nie wymaga wielkiego wysiłku, ale jeśli chcemy by nasz skrypt był przydatny dla innych i dla nas za pół roku – trzeba się nieco przyłożyć w czasie jego tworzenia. Uznałem jednak, że rzecz sama się nie zrobi. W najgorszym wypadku po prostu rozpiszę się nieco bardziej niż zwykle (ha, ha, ha…
)
Od czego zacząć?
W zasadzie pierwsze pytanie jakie powinniśmy sobie zadać powinno brzmieć: czy chcemy napisać coś, co wykona serię operacji i da nam na koniec jakiś wynik (skrypt) czy bardziej interesuje nas biblioteka narzędzi (moduł). Dalej jest już prościej: dzielimy zadanie na proste czynności (funkcje), które następnie połączymy w całość. I o ile w przypadku modułów sprawa wydaje się “czysta” i dość naturalna, o tyle w wypadku skryptów musimy zwalczyć pokusę umieszczenia operacji w jednym, wielki worze.
Kod wielokrotnego użycia
Skrypty lubią rosnąć niby hydra: dodajemy do nich kolejne funkcjonalności, jednocześnie nie specjalnie dbając o to, by kod można było później wykorzystać. To moim zdaniem spory błąd: utrudnia ponowne wykorzystanie napisanego kodu w innym narzędziu, czyni narzędzie dość statycznym i dość silnie uwiązanym do wykorzystanej technologii. Może prosty przykład, by pokazać o co mi chodzi…
Naturalna kolej rzeczy: nasz skrypt może przyjąć jako parametr samą listę (przekazaną przez rurkę), OU w AD, plik txt/ csv z listą komputerów itd. Na wyjściu – podamy ścieżkę do pliku .csv w którym dane zostaną zapisane. To co się dzieje w środku zależy już od nas. Możemy więc albo zrobić to w formie funkcji, które następnie ustawimy w jednej “rurce” i uzyskamy pożądanych efekt. Albo wszystko zrobić za jednym zamachem, bez dziabania kodu na poszczególne fragmenty. Co tracimy?
- przejrzystość kodu (logika się “zlewa”)
- utrudnienia przy wymianie komponentu
- rozwiązując podobny problem musimy praktycznie kopiować cały skrypt, albo zacząć pisanie od początku
Problem, jaki może się pojawić, to konieczność zdefiniowania funkcji zanim ich użyjemy. Jak to w prosty sposób rozwiązać? Mój ulubiony trik to definiowanie na początku funkcji, która ma za zadanie tylko opisać zakładaną logikę – czy inaczej – szkic tego co chciałbym osiągnąć. Na ogół wygląda to tak:
#requires -version 2.0 <# Pomoc do skryptu #> function Invoke-Main { param ( $Parametr = $Script:Parametr, $DrugiParametr = $Script:DrugiParametr, $Path = $Script:Path ) Get-Foo -Parametr $Parametr | Test-Foo | ConvertTo-Bar -Drugi $DrugiParametr | Export-Csv -Path $Path } <# Tu definiujemy: * Get-Foo * Test-Foo * ConvertTo-Bar #> Invoke-Main
Jak widać – definicje funkcji następują przed jej wywołaniem (które ma miejsce na samym końcu skryptu) ale sposób ich wywołania znany jest od początku (zdefiniowany w pierwszej funkcji w skrypcie). Jeśli zechcę kiedyś zmienić finalny obiekt na ‘Boo’ zamiast funkcji ConvertTo-Bar zdefiniuję ConvertTo-Boo, zmienię nieco Invoke-Main i już – skrypt gotowy do użycia.
Funkcja w rurce – awansujemy.
Patrząc na składnię moich hipotetycznych funkcji od razu widać jedną rzecz: wszystkie “klocki” radzą sobie w rurce. To podstawa: pisząc funkcję niezdolną do pracy w środku pipe’a strzelamy sobie w stopę. By jednak współpraca przebiegała bezboleśnie – należy z całą pewnością przyzwyczaić się do pisania zaawansowanych funkcji. Wymagają one nieco dekoracji na wstępie, ale wartość dodaną trudno moim zdaniem przecenić. Druga rzecz, która być może w skryptach nie jest tak cenna, ale w modułach moim zdaniem absolutnie niezbędna: pomoc do funkcji. Wymaga to maciupeńkich nakładów pracy (odpowiednio skomponowany komentarz) a oszczędza konieczności czytania definicji funkcji za każdym razem. Myślę, że sam temat zaawansowanych funkcji jest zbyt obszerny, by go streścić tutaj, zostawię więc to na piątą część cyklu. Na rozbudzenie apetytu: malutka funkcja, która wykorzystuje część możliwości, które dają zaawansowane funkcje:
function Test-IsAlive { [CmdletBinding()] param ( [Parameter( ValueFromPipelineByPropertyName = $true, Mandatory = $true, HelpMessage = 'Nazwa komputera, ktory testujemy' )] [ValidatePattern('(?# Bez spacji w nazwach komputerow!)^\S+$')] [Alias('Name','CN','Nazwa')] [string]$ComputerName, [Parameter(ValueFromPipeline = $true)] [Alias('IO')] [PSObject]$InputObject ) process { Write-Verbose "Testuje komputer: $ComputerName" if (Test-Connection -ComputerName $ComputerName -Quiet -Count 1) { if (!$InputObject) { Write-Verbose 'Nic na wejsciu, tworzymy sami.' $InputObject = New-Object PSObject -Property @{ ComputerName = $ComputerName } } $InputObject | Add-Member NoteProperty IsAlive $true -PassThru } } }
Skutek? Mogę przez tą funkcję przepuścić dowolny obiekt, który posiada właściwość ComputerName, Name, Nazwa lub CN i jeśli właściwość ta nie zawiera spacji (ValidatePattern, z komentarzem, by nie straszyć ludzi niezrozumiałym regexpem) i da się ją “pingnąć” (preferowane więc będą obiekty pobrane z AD, lub innego zawierającego nazwę komputera) to na wyjściu dostanę ten sam obiekt “wzbogacony” o właściwość IsAlive. Jeśli spróbuję uruchomić funkcję bez parametru – poprosi mnie ona o wartość ComputerName. I rzecz nie bez znaczenia: dodanie wtrąceń typu Write-Verbose/ Debug działa bez potrzeby implementacji. [CmdletBinding()] daje mi te opcje za darmo. Mogę więc uruchomić funkcję z parametrem –Debug lub –Verbose i dowiedzieć się więcej o tym, co dzieje się w środku.
Wejście – wyjście.
Skrypty mają to do siebie, że czasem wolelibyśmy nie musieć pamiętać co do nich trzeba włożyć, oraz co byśmy chcieli z nich wyjąć. Z drugiej strony – czasem jednak chcemy mieć wpływ na to, co się stanie… PowerShell pozwala pogodzić te dwie sprzeczności. Rozwiązanie to wyciągnąć jak najwięcej elementów na zewnątrz skryptu (w postaci parametrów) i jednocześnie przypisać im wartość domyślną (by nie być zmuszonym podawać ich za każdym razem). Z wyjściem jest gorzej – optymalne rozwiązanie to parametr typu [switch], który na wyjściu da nam “żywe” obiekty. To co z nimi zrobimy dalej będzie zależeć już tylko od nas. I wilk syty, i owca cała.
PowerShell – efektywnie(j), część 2.
| 2011-10-04 | Posted by Bartek Bielawski under konsola, najlepsze praktyki, Początki, Polskie blogi IT |
|
W części pierwszej tego cyklu opisałem ogólnie to, jak moim zdaniem praca w PowerShellu różni się w zależności od naszej aktualnej aktywności. Skupiłem się na różnicach między trybem pracy interaktywnej i trybem tworzenia skryptów. Dziś, zgodnie z obietnicą, poznęcam się nieco nad pracą w konsoli.
Badacz
PowerShell daje nam możliwości, których próżno szukać w VBS. Trudno je też znaleźć w cmd, choć temu ostatniemu nieco bliżej do interaktywnej natury PowerShella. W VBS byliśmy skazani na pisanie od zera, sklejanie skryptów z klocków, żmudne testy bez prostej możliwości wglądu w działanie skryptu. PowerShell pozwala każdy obiekt zbadać, obejrzeć, obrócić, przeskanować, rozłożyć na czynniki pierwsze. Nie korzystając z tych możliwości ograniczamy sobie pole działania. Wielu rzeczy o PowerShellu dowiadywałem się po prostu klepiąc TABem na różnych obiektach. Get-Member też zwykle służy pomocą. To wszystko sprawia, że PowerShell jest wręcz stworzony do zgłębiania świata .NET. Swoją drogą to dumam, czy programistom zdarza się uruchamiać PowerShella tylko po to, by sobie szybciutko pogmerać w jakimś skompilowany kodzie…
Oprócz tego możemy pracując obserwować cały czas rezultaty i nasze zachowanie dostosowywać do wyników. Jeśli jakaś metoda wyrzuca błąd – możemy sprawdzić jej definicję, zmodyfikować, uruchomić ponownie… aż do skutku.
Z pewną taką nieśmiałością…
Pisałem już o tym chyba kiedyś, ale ta cecha PowerShella niezmiennie mnie zachwyca. Pięknie o tym mówi w czasie swoich prezentacji o PowerShellu Jeffrey Snover. Spróbuję przetłumaczyć
Odwieczny dylemat administratora:
Czy ta komenda jest poprawna? Czy jeśli ją wykonam, to stracę pracę? Czy przez moją pomyłkę Buffy i Puffy nie pójdą na studia? Może lepiej sprawdzą Co Jeśli…
-WhatIf i –Confirm – dwa parametry, które pewnie nie raz uratują adminowi jego cztery litery, lub przynajmniej pozwolą uniknąć 16-godzinnej dniówki. Korzystać z nich można, należy. Co więcej – korzystanie z –Confirm można w prosty (stosunkowo) sposób wymusić: wystarczy ustawić $ConfirmPreference na odpowiednio niską wartość. Domyślnie jest High (czyli tylko komendy z ConfirmImpact równym High będą wymuszać potwierdzenie). Ustawienie tego parametru na ‘Low’ może sprawić, że PowerShell będzie nas pytał o niemal wszystko.
WhatIf też można wymusić ($WhatIfPrerence = 1) ale to chyba już przesada… Zamiast coś robić, będziemy tylko dostawać informację co by było gdyby… Za to raczej nam nikt nie zapłaci.
A odwrócić to można tylko używając składni:
Komenda –WhatIf:$false
Niezbyt przyjazne, jeśli mam być szczery…
Klocki lego
Pisanie pełnej, “wypasionej” komendy od zera to troszkę jak malowanie obrazu bez szkiców… PowerShell to idealny szkicownik: możemy wykonać jakąś “rurkę”, sprawdzić czy rezultat nas zadowala, dodać kolejną komendę do potoku, sprawdzić. Zapisać w zmiennej, sprawdzić zawartość, przepuścić ją przez foreach ()… I tak, krok po kroku, dojść od koncepcji do pełnego rozwiązania. Czasem oczywiście nie jest to konieczne: łatwiej nam będzie zmodyfikować coś, co już kiedyś w pocie czoła stworzyliśmy. Ale na początku lepiej właśnie posłużyć się techniką “małych kroczków”. PowerShell, przez swoją interaktywność oraz fakt, że składnia w skrypcie niczym się nie różni od tej pisanej w konsoli, daje nam taką możliwość. Warto z niej skorzystać by nie napracować się nad jakimś skryptem tylko po to, by na koniec odkryć, że obiekt który zapowiadał się obiecująco kompletnie nie nadaje się do rozwiązania postawionego przed nami problemu. Budując rozwiązanie stopniowo unikniemy takich frustrujących i zniechęcających przygód.
Krótkie podsumowanie
Na dziś kończę. W następnej części skupię się na “trikach”, które często w konsoli wykorzystuję. Większość z nich opisałem w moim gościnnym artykule na blogu Hey, Scripting Guy! Część jednak dość lakonicznie, tu postaram się nieco bardziej rozpisać…
PowerShell – efektywnie(j), część 1.
| 2011-09-24 | Posted by Bartek Bielawski under najlepsze praktyki, Początki, Polskie blogi IT |
|
Wszystkie narzędzia używane przez człowieka mają swoje ograniczenia. Wkręt można wbić młotkiem, ale śrubokręt zwykle daje lepszy rezultat. Tak samo naturalnie jest z PowerShellem: można walić nim jak młotem, można subtelnie trafiać idealnie w problem. W tej serii postaram się opisać to, co moim zdaniem może pracę w PowerShellu usprawnić, uprościć i dostosować do poziomu, na którym obecnie pracujemy.
Wyróżniłbym dwa skrajne poziomy, wraz z pewnym obszarem pośrednim:
Innymi zasadami kierowałbym się w każdym z tych obszarów. Dlaczego? Bo życie należy sobie ułatwiać. Na początek postaram się w skrócie przedstawić różnice pomiędzy oboma trybami (tryb pośredni pozostawię sobie na deser) a następnie zagłębie się w to, co moim zdaniem może uczynić pracę na obu poziomach bardziej efektywną, czasem również efektówną.
Aliasy
Pracując interaktywnie korzystamy z aliasów: po to zostały stworzone. W skrypcie – każdy alias to potencjalne źródło problemów, błędów i dodatkowo – element pogarszający czytelność skryptu. Przykład z życia wzięty: doskonały moduł ShowUI w jednym z przykładowych skryptów korzysta z aliasu “ps”. Długo musiałem dochodzić do tego, czemu ten konkretny przykład u mnie nie działał. Przyczyna? Usuwam w profilu w/w alias, mam dysk PS:, do niego odpowiednią funkcję, która działa podobnie do a:, c:, d: – alias mi uniemożliwiał szybkie dopełnianie nazwy tabem, więc go usunąłem. Skrypt, mimo że napisany poprawnie, stracił swą funkcjonalność.
Pisałem o czytelności… Dla początkującego użytkownika PowerShella taki kod będzie mało czytelny…:
h|?{$_.Id-gt5}|%{ $_.CommandLine-replace'^.(\w+)','$1'}
Przykładów dowodzących zasadności używania aliasów w shellu jest pewnie jeszcze więcej. Wystarczy porównać:
# Z aliasami... ls -r -fo -ea 0 -fi *.ps1 # I bez.Get-ChildItem -Recurse -Force ` -ErrorAction SilentlyContinue -Filter *.ps1
Aliasy są też bardzo przydatne, jeśli używacie czasem narzędzi nie przesiadujących w Waszej ścieżce: można albo dodać kolejny folder do $env:PATH, albo stworzyć alias, który będzie uruchamiał potrzebne narzędzie.
Profile
Pracując interaktywnie bez profilu tracimy czas – wiele funkcji i narzędzi definiujemy za każdym razem, zamiast zapisać je raz i później po prostu używać. Profil może za nas załadować wtyczki i moduły, może dodać wykorzystywane przez nas często zmienne, stworzyć dyski – możliwości jest bardzo wiele.
Skrypty dla odmiany powinny być kompletnie niezależne od profilu. Skrypt, jeśli jest napisany z głową, powinien sprawdzić czy wszystkie niezbędne do jego działania elementy są już w środowisku. Do testów najlepiej użyć możliwości, jakie daje powershell.exe – ma on parametr –noprofile, który świetnie nadaje się do uruchamiania “środowiska testowego” dla skryptów.
Host i UAC
Pracując interaktywnie korzystajmy raczej z hosta, który daje nam największy komfort. Dobrze poświęcić nieco czasu, “sprawdzić” dostępne opcje – w tym również opcje komercyjne (na ogół dostępne są wersje trial). Nie ma rozwiązania idealnego dla wszystkich, dlatego najlepiej “posmakować” dostępnych opcji i wybrać taką, w której będziemy się czuć najlepiej. Dodatkowo warto rozważyć ustawienie wybranego hosta tak, by uruchamiał się z “odpowiednimi” uprawnieniami. Osobiście uważam UAC za świetny wynalazek, nawet na serwerach go nie wyłączam. Ale póki PowerShell nie ma możliwości w prosty sposób “przeskoczyć” na wyższy poziom w trakcie pracy – wolę go od razu na tym wyższym poziomie uruchamiać.
Skrypty dla odmiany powinny “umieć się zachować”. Naturalnie, są takie, których użycie w innym hoście niż ten, w którym go tworzono, po prostu nie ma sensu. Ale jeśli skrypt nie jest z hostem bezpośrednio “powiązany” – dajmy użytkownikowi wybór. To oznacza, że powinniśmy przetestować nasz skrypt w kilku hostach, absolutne moim zdaniem minimum to PowerShell.exe i PowerShell ISE. Jeśli zaś chodzi o UAC – skrypt powinien wiedzieć, co będzie mu potrzebne. Powinien uprawnienia sprawdzić. I jeśli mu czegoś brakuje – uprzedzić użytkownika zanim spróbuje coś zmodyfikować.
Formalizm
Pracując interaktywnie tworzymy czasem krótkie funkcje, bloki skryptu, tymczasowe narzędzia. Ponieważ stworzyliśmy je przed chwilką – nie ma sensu ich dokumentować. Get-Help raczej na nich nie użyjemy. Nie ma też raczej powodu nadmiernie rozbudowywać blok przyjmujący parametry – wszelkie walidacje nie mają większego sensu, wiemy jak wygląda nasza funkcja, więc znamy jej ograniczenia, wiemy z jakimi założeniami została stworzona.
Skrypt dla odmiany powinien być dobrze udokumentowany. Korzystajmy z tego wszystkiego, co daje nam środowisko: pomoc w komentarzach, walidacja parametrów, zmienne z usztywnionymi typami, informacje typu warning, debug, verbose – to wszystko ułatwi nam modyfikowanie skryptu w przyszłości i używanie go bez konieczności otwierania go w edytorze za każdym razem. Koszt takiej operacji w wypadku skryptów używanych od czasu do czasu szybko się zwróci. A ewentualna rozbudowa o dodatkowe funkcje nie przyprawi nas o ból głowy.
Co dalej?
Ten wpis zaczyna pewien cykl. Dalej zagłębię się nieco bardziej w obu skrajnościach, na koniec zaś postaram się napisać, jak w prosty sposób można “przeskoczyć” z poziomu interaktywnego do skryptowego. Druga część będzie w całości poświęcona pracy interaktywnej w PowerShellu.