Skip to Content

IT nieuczesane.
category

Category: DevOps/Scripting

skrypty, programy, command line i inne

wartościowy null – jak w Powershell sprawdzić limity skrzynek Exchange

Sprawa dość trywialna… przynajmniej tak by się można spodziewać. Limity wielkości skrzynek zapisane są w dwóch miejscach:

  • w parametrach samej skrzynki na Exchange – to dla tych, którzy będą mieli ‘use mailbox default’
  • w atrybutach w AD, które będą za chwilę opisane.

zacznę najpierw od szmacianego raportu SCCM:

nie wiem czy panowie z centrali sami przygotowywali ten raport czy to standardowy [domel, wiesz może?] ale jest to jeden z najbardziej oszukańczych raportów jaki widziałem:

  • dla osób z flagą ‘use default’ pokazuje wszędzie wartości null – jak by nikt nie miał skrzynki
  • dla osób, które mają zarówno ‘use default’ ale kiedykolwiek miały inne wartości, wartości te zachowane są w atrybutach AD [tyle, że nieużywane]. w zwiazq z tym SCCM pokazuje nieprawdziwe wartości, które są nieużywane.
  • jedyne co pokazuje dobrze to osoby, które mają coś ręcznie ustawione i jest to w użyciu.

masakra. trzeba było olać raport i zrobić to dobrze – czyli ręcznie. sprawa jest prosta. wykorzystywane są cztery atrybuty obiektu user [zapisuję małymi znakami, ponieważ przypominam, że PS wymaga używania w lowercase!]:

  • mdbusedefaults – czyli flaga ‘use defaults’. jeśli ustawiona jest na ‘true’ to reszta nie jest sprawdzana. po prostu dziedziczy parametry ustawione na storze [dla GT –> “na magazynie” (; ]
  • mdbstoragequota – wartość ‘issue warning’. quota
  • mdboverquotalimit – wartość ‘prohibit send’. softquota.
  • mdboverhardquotalimit – wartość ‘prohibit to send and receive’. hardquota.

image

so far, so good. problem zaczyna się kiedy próbuje się sprawdzić która skrzynka ma wartość domyślną, a która nie. powód – podstawowy dla PS czyli ‘co za cholerstwo zwraca ta funkcja?’. aby podjąć działanie zależnie od wartości mdbusedefaults trzeba sprawdzić czy ma wartość true czy false. a oto wyniki zabawy:

PS C:> $r.properties.mdbusedefaults
False
PS C:> if ($r.properties.mdbusedefaults -eq $false) {echo „aaaa”}
PS C:> if ($r.properties.mdbusedefaults -eq $true) {echo „aaaa”}
PS C:> if ($r.properties.mdbusedefaults -eq $null) {echo „aaaa”}
PS C:> if ($r.properties.mdbusedefaults) {echo „aaaa”}
aaaa
PS C:> if ($r.properties.mdbusedefaults -eq ‚False’) {echo „aaaa”}

co widać? w pierwszym zapytaniu dostajemy wartość false. kiedy jednak próbuje się tą wartość porównać z $false czy $true – żadna z powyższych. nie jest to również $null. w takim razie oczywistym wydaje się, że to musi być po prostu string. ale i to zawodzi.

pomimo usilnych prób nic z tego nie wyszło. poszedłem spać a na drugi dzień rozwiązanie jakoś tak samo przyszło:

PS C:> $r.properties.mdbusedefaults.gettype()

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     False    ResultPropertyValueCollection            System.Collections.ReadOnlyCollectionBase

skoro jest kolekcją to trzeba to zrobić tak:

PS C:> $r.properties.mdbusedefaults[0]
False
PS C:> if ($r.properties.mdbusedefaults[0] -eq $false) {echo „aaaa”}
aaaa

pytanie ‘czemu, u licha, to jest kolekcją??!!’ pozostawiam otwarte. dla mnie to idiotyzm ale może ktoś zna jakieś logiczne wyjaśnienie?

a na zakończenie cały skrypt:


eN.

grep/find w powershell

o ile jestem gorącym zwolennikiem PS, o tyle w tych, wydawałoby się, najprostszych operacjach jest masakrycznie upierdliwy i nieintuicyjny. przykładem może być właśnie funkcjonalność aka ‘grep’ tego, co jest wypluwane. w przypadku PS są [co najmniej] dwie możliwości:

  • podstawowa to commandlet Select-String. no i fajno – wbudowany, grepuje, można sobie np. w pliq poszukać jakiegoś ciągu znaków. ponieważ jest ‘wbudowany’ pozwala na łatwe oskryptowanie… ale pojawia sie pewien problem: wszystko co zwraca PS jest obiektem… a nie ciągiem znaków. wynika z tego tyle, że kiedy się coś skryptuje, rzadko kiedy da sie go realnie użyć – a to z tego powodu, że trzeba wszystkie interesujące nas atrybuty obiektów przeformatować na stringi i porównywać jeden po drugim – bo zwykły pipe po prostu wrzuca obiekt i tyle. mówiąc dosadnie: pupa.
  • pozostaje ‘stary, dobry’ findstr, który w każdym Windows jest [no ok, są tacy co wycinają pinga z systemu twierdząc, że nie potrzebny i zmniejsza footprint, więc są pewnie i tacy, co nie mają findstr (; ]. “przepajpowanie” [LOL q: jak to po polskiemu? “przekazanie danych na standardowe wyjście”…] wyników na findstr automatycznie przekonwertuje cały output na stringi [huehue… “całe informacje wyjściowe na wartość tekstową” – ja bym chyba nie zrozumiał po polsq o co cho] a więc zadziała ładnie i zawsze. problem? jest zewnętrznym programem, przez co ciężej potem coś takimi wynikami zrobić. jednak przy standardowym wykorzystaniu przy pracy z PS jako shellem – na pewno będzie działał zawsze i niezawodnie… w przeciwieństwie do Select-String.

eN.

powershell – wywołanie funkcji

piszę za karę – wczoraj rzucałem klątwy więc dziś na tablicę “zapamiętam jak się wywołuje funkcje w PS”… ograniczę się jednego razu.

trywialna funkcja:


spodziewałem się na ekranie “3” a tymczasem dostałem 1<CRLF>2. $a okazało się być zwracane jako obiekt jakiś dziwny… a to dla tego że funkcje wywołuje się:

fun 1 2

jakoś tak nieintuicyjnie. de facto jest to to samo co fun (2) (3) więc podając fun(1,2) jest to wywołanie z pierwszym parametrem “1,2” i drugim null.

i pomimo,że podobne funkcje widziałem na wielu stronach nie mogło to do mnie dotrzeć. to jak w tym doświadczeniu, w którym trzeba policzyć ile było podań piłki, ew. w historii o Inkach, którzy nie widzieli zbliżających się łodzi…

eN.

SCCM Raport Lista modeli komputerów

W SCCM 2007 R2 brakuje raportu który by wyświetlił listę komputerów z nazwą producenta, typem modelu komputera, numerem seryjnym i nazwą usera.

Poniżej raport który robi:

1) tworzymy nowy raport

2) jako Report SQL Statement wklejamy:

SELECT
Distinct
SYS.Netbios_Name0,
SYS.User_Name0,
MOD.Manufacturer0,
MOD.Model0,
BIO.SerialNumber0
FROM v_R_System SYS
JOIN v_GS_COMPUTER_SYSTEM MOD on SYS.ResourceID = MOD.ResourceID
JOIN v_GS_PC_BIOS BIO on SYS.ResourceID = BIO.ResourceID
JOIN v_FullCollectionMembership FCM ON SYS.ResourceID = FCM.ResourceID
WHERE
FCM.CollectionID=@ID
ORDER BY SYS.Netbios_Name0

3) Tworzymy nowego Promta o nazwie ID, zaznaczamy Provide SQL Statement

4) Do Prompt SQL Statement wklejamy:

BEGIN
IF (@__filterwildcard = '')
SELECT DISTINCT CollectionID, Name FROM v_Collection ORDER BY Name
ELSE
SELECT DISTINCT CollectionID, Name FROM v_Collection
WHERE CollectionID like @__filterwildcard
ORDER BY Name
END

Proste i przydatne :-)

powershell – znaki diakrytyczne i import csv

dwie ciekawostki przy jednym prostym teście…

kiedy importuje się plik CSV z pojedynczym wierszem (oczywiście + nagłówek) atrybut ‘legth’ (count) zwraca null… przy każdej innej wielkości normalnie zwracana jest prawidłowa liczba. rzadko kiedy importuje się csv z jednym wierszem, ale przy testach nagle skrypt zaczął zwracać dziwne rzeczy…

plik, o którym mowa, zawierał znaki diakrytyczne – tego właśnie dotyczyły testy: funkcji sczytującej csv i konwertującej wartości na ograniczony alfabet. tutaj wyszła kolejna ciekawostka – z jakiegoś powodu większość znaków nie była konwertowana. powodem okazał się sposób zapisu pliq – PS czyta pliki zapisane w UTF-16 lub UTF-8. jeśli csv jest w ANSI to PS dostaje ‘sieczkę’ i nie za bardzo rozpoznaje w nim znaki alfabetu (; zabawne, bo get-content radzi sobie z tym znakomicie. najprostszy sposób konwersji wygląda zatem: get-content .myfile.csv>>myfile2.csv bo zapis jest standardowo w unicodzie.

eN.

funkcje w powershell

funkcje w powershell to bardzo dziwny i nieintuicyjny wynalazek. należy więc intuicję zmienić, a to oznacza – zrozumieć jak ten diabeł działa. pełny art w wer. angielskiej polecam przeczytać, ponieważ to w pełni wyjaśnia problem. ja przedstawię go po swojemu – czyli w skrócie i na przykładach q:

weźmy prostą funkcję testową:

znając trochę języki programowania można się spodziewać, że na ekranie pojawi się:

będę liczył

coś!!!aaaa

tymczasem realny output będzie zaskaqjący:

cośbęde liczył!!!aaaa

o co cho? cała funkcja konwertowana jest w locie na obiekt. wszystko, co ‘wychodzi’ z funkcji traktowane jest jako atrybut obiektu. w związq z tym:

  • return nie jest potrzebny – kończy wykonanie funkcji, ale zwykły output wystarczy
  • każdy output jest jednym z atrybutów obiektu zwracanego przez funkcję

przy tej samej funkcji można zrobić inne doświadczenie:

które pokaże, że zwracana jest dwuelementowa tablica zawierająca “będę liczył” oraz “!!!aaaa”.

funkcja w najprostszej postaci może wyglądać zatem tak:

jeśli zatem w funkcji wykorzystywana jest jakaś funkcja zwracająca cokolwiek na ekran, niezbędne jest dodanie “|out-null” żeby nie otrzymać tego jako atrybut w zwracanym obiekcie.

eN.

gdzie jest moja przestrzeń?

ciekawostka przyrodnicza: na serwerze kończy się miejsce na dysq. sprawdzam wielkość dysq – 33GB, sprawdzam zajętość katalogów przy pomocy explorera – wychodzi koło 16GB. ilość wolnego miejsca na dysq – bliska 0. o co c’mon?

jeszcze ciekawiej: dokładnie taka sama sytuacja jest na drugim dysq w tym serwerze. wychodzi na to, że zniknęło ok 4o%-5o% wszystkich dysqw – nie wiadomo gdzie i jak.

w pierwszej kolejności zadzwoniłem i zamówiłem nowe dyski do serwera. w między czasie trzeba sprawdzić o-co-cho.

dochodzenie

zacząłem od dość brzydkiej operacji – nadawania uprawnień do ‘zakazanych’ katalogów – system volume information, recycle bin i wszelkie inne systemówki, do których nie ma uprawnień a więc na pewno zostały wkalqlowane w sumaryczną wielkość. wszystkie miały pomijalną wielkość. to, czego się przy okazji dowiedziałem to to, że system sobie potem ładnie te katalogi ‘reperuje’ przywracając im po jakimś czasie [restart?] uprawnienia. ufff… przynajmniej sie nie rozjechał (;

kolejny strzał – shadow copy lub restore points. w w2k8 (R2) nie ma dostępnej opcji/zakładki Restore Points. próbowałem na siłę sprawdzić korzystając z rozwiązania z http://www.win2008workstation.com/forum/viewtopic.php?p=4301#p4301. zakładka pojawia się co prawda – ale wywala się z błędem. niemniej można to sprawdzić nieco bardziej ‘legalnie’:

ponieważ restore point jest ‘migawką’ shadow copy – powinien być zapis o niej w systemie. w związku z tym powinno dać się to sprawdzić przy pomocy vssadmin

PS C:> vssadmin.exe list shadows
vssadmin 1.1 – Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.

No items found that satisfy the query.

pupa. nie muszę w związq z tym dodawać, że sama funkcjonalność previous versions jest wyłączona. zaczynam zabawę z alternatywnym badaniem wielkości katalogów – czyli powershell. znalazłem fajny art krok-po-kroq wyjaśniający jak do tego podjeść. nie jest miłe i tak proste, jak bym się tego spodziewał – ale działa (: no i kilka fajnych tipsów PS przyda się na przyszłość:

"{0:N2}" -f ((Get-ChildItem ‚.program files (x86)’ -recurse | Measure-Object -Property length -sum).sum / 1GB ) +" GB"

nie bez powodu pokazuję od razu ten katalog – ponieważ to właśnie on okazał się być złodziejem przestrzeni. jeszcze troszkę bardziej rozbudowana składnia do reqrencyjnego odpytania i jest winny!

PS C:Program Files (x86)> get-childitem | %{"$_ size: "+ "{0:N2}" -f ((Get-ChildItem $_ -recurse | Measure-Object -Property length -sum).sum / 1GB )+" GB"}
[…]
Microsoft Configuration Manager size: 18,32 GB
[…]

explorer pokazuje dla tego katalogu znaczną różnicę w wielkości: 0B (słownie – zero bajtów). na drugim dysq sprawca jest ten sam – repozytorium SCCM i katalog SMSPKG.

dyski właśnie przyszły – a więc czas na kolejne hardtesty – jak przerzucić cały system na nowe dyski. spróbuję windows backup…

**UPDATED**

pozostaje pytanie – czemu explorer nie pokazuje wielkości niektórych katalogów. i tutaj odpowiedzią jest moja najulubieńsza, taka jej mać, funkcja – UAC. ma to związek ze starszym wpisem. ktoś mógłby stwierdzić, że to nie wina UAC tylko explorera – którego nie da się [normalnie] odpalić z tokenem administratora. powershell potrafił zliczyć wielkości, ponieważ był właśnie z nim uruchomiony. prawie na pewno – gdybym zamiast explodera używał jakiegoś menadżera plików firmy trzeciej – również zliczyłby katalogi prawidło. imho jednak takie rzeczy stanowią integralną część systemu i powinny być przemyślane w całości – jako spójna platforma. no nic – po prostu dodaję nową zasadę: “nie używaj explorera na serwerze z UAC”.

druga kwestia – jeszcze do zbadania – to z jakiej racji SCCM tak pożarł miejsce.

eN.

znaleźć obiekt po mailu

kilqkrotnie miałem problem – przychodzi ktoś i żąda żeby zrobić coś z kontem, którego email to …. chodzi o to, że czasem był to email, czasem alias – generalnie nie ma standardowego searcha, który potrafi to zrobić. otóż i skrypcik:

pozostaje jeszcze jeden problem… foldery publiczne, które też mogą mieć email…

eN.

Backup ISA TMG

ISA i TMG to takie fajne serwerki, które łatwiej jest postawić od początku niż przywrócić z kopii zapasowej. A jeszcze prościej zrobić jeden obraz z systemu, a następnie odtworzyć z obrazu, i wgrać najnowszy konfig. Ale jak więc zabezpieczać konfig ISA/TMG? Dość prosto i szybko można to zrobić skryptem, pamiętając o kilku rzeczach:

  • Backup konfiguracji powinien być trzymany na oddzielnym serwerze, najlepiej backupowanym przez coś innego
  • Pojedyńcza kopa zapasowa ma 7-8 MB, co przy kopii codziennej daje 3G na rok, a tygodniowej 420MB
  • Folder docelowy dobrze jest skompresować, wybierając odpowiednią flagę NTFS-ową na folderze, wtedy ilość miejsca z 7MB spada do 2.5MB, przy czym kolejne backupy będą zabierały jeszcze mniej
  • Jeśli certyfikaty będą eksportowane, to znajdą się również w konfiguracji TMG
  • Przy tmg, routing jest trzymany w konfiguracji TMG, więc przed importowaniem trzeba go wyrzucić z pliku netsh

A poniżej skrypt:

‚bAckupisa/tmgtofile
Const destination = „C:bck”
Const passwd = „12345678”

Const fpcExportImportPasswords = &H00000001
Const fpcExportImportUserPermissions =&H00000002
Const fpcExportImportServerSpecific= &H00000004
Const fpcExportImportEnterpriseSpecific = &H00000008
      fpcOptionalData = fpcExportImportPasswords Or _
      fpcExportImportUserPermissions Or _
      fpcExportImportServerSpecific Or _
      fpcExportImportEnterpriseSpecific
date = replace(Date,„/”,„_”)
Set root = CreateObject(„FPC.Root”)
Set firewall = root.GetContainingArray
firewall.ExportToFile destination & date & „_ISA_CONFIG.XML”_
                     ,fpcOptionalData,passwd

Set wshShell = WScript.CreateObject(„WScript.shell”)
wshshell.run „cmd/c „” netsh int ip dump > ” & _
              destination & date & „ip.nsh”””
wshshell.run „cmd/c „” netsh int ip show dns > ” & _
             destination & date & „dns.txt”””

pedanteria niepożądana

prosty search po obiektach w AD, które mają włączoną flagę niewygasania hasła:

i okazuje się, ze na ekranie pustka… wyświetlają się tylko pola ‘sn’. WTF?

problemem jest pedanteria i używanie małych/wielkich znaków – okazuje się, że PS przyjmuje wyłącznie małe literki:

echo "[$($i.samaccountname)] , $($i.displayname) , $($i.sn), $($i.distinguishedname)"

pffff…

eN.