Trzeba było znaleźć wszystkich użytkowników, którzy nie logowali się od dłuższego czasu i przenieść ich do innego OU.
Problemy jakie się pojawiły to wartość atrybutu LastLogonTimeStamp, która jest specyficzna (liczba milisekund od epoki) i przenoszenie obiektów w AD. O ile pierwsze było proste do wygooglania o tyle z drugim strasznie ludzie kombinują, piszą miliony linii kodu i generalnie żadne z tych rozwiązań mi się nie podobało. Chwila samodzielnego kombinowania, trochę rzeźby i olśnienie w postaci, że PowerShell to przecież… shell :) i że działają w nim komendy commandlinowe takie jak np. dsmove :)

Poniżej skrypt, który znajduje wszystkich w danym OU , którzy nie logowali się od 14 miesięcy i przenosi ich od OU inactive. Minimalne wymagania: domena w trybie “Windows Server 2003”

# script finds all users in specified OU who haven’t logged for last n months # and moves theirs accounts to another OU # Author Kuba Siatkowski http://interkreacja.pl/
$howoldallowed = 14; #maximum time since last logon (months) $dom ="LDAP://OU=sourceou,DC=yourdomain,DC=com,DC=pl"; #search path $newparent ="OU=inactive,DC=yourdomain,DC=com,DC=pl"; #destination path for unused accounts #$Root = New-Object DirectoryServices.DirectoryEntry $strROOT $Root = New-Object DirectoryServices.DirectoryEntry $Dom $Searcher = New-Object DirectoryServices.DirectorySearcher $Searcher.SearchRoot = $root $searcher.Filter = (&(objectClass=User)(!(objectClass=Computer))); $users = $searcher.findAll(); $lastallowed = [DateTime]::Now.AddMonths($howoldallowed * (-1)); foreach ($user in $users) { if (!($user.Properties.lastlogontimestamp -eq $Null)){ $lastlogon = [DateTime]::FromFileTime([Int64]::Parse($user.Properties.lastlogontimestamp)); if (($lastlogon -lt $lastallowed)){ write-host $user.Properties.cn “; -NoNewLine; write-host $lastlogon ; -NoNewLine; write-host $user.Properties.distinguishedname; dsmove $de.distinguishedName -newparent $newparent } } else { write-host $user.Properties.cn never logged on; } }
-o((:: sprEad the l0ve ::))o-

Comments (6)

  1. Odpowiedz

    Hmmm … znaczy można … tyle że Oldcmp (http://www.joeware.net/freetools/tools/oldcmp/) z przełącznikiem -user -move -newparent i -llts robi to samo … i pisac nie trzeba.

    2 … ten filtr to taki troche dziwny :) nie latwiej bylo:

    “(&(objectClass=User)(objectCategory=Person))“

    Pomijając że filtr dziwny to składa się z dwóch zapytań po nieindeksowanym atrybucie (objectClass) więc wydajność średnia.

    A jak już powershell to bym sprawdził czy w cmdletach Quest tego się nie da łatwo opędzić, a co do już tylko tego skryptu to ta konwersja czasu trochę przekombinowana – prościej będzie tak:
    [System.DateTime]::FromFileTime($user.Properties.lastlogontimestamp)

    To samo a jednak inaczej … ale do tego zadania i tak bym wybrał oldcmp.

    To pisałem ja … Jarząbek

  2. Grzesiek

    Odpowiedz

    Witam,

    nie znam sie na Powershell ale interesuje mnie zagadnienie
    „jak sprawdzic prawdziwy ostatni czas logowania uzytkownika”
    Odwolam ise ty do tego artykulu http://www.logicunion.pl/artykuly/lastLogon.html
    Windows Server 2003 oferuje nam LastLoginTime oraz LastLogonTimeStamp
    jedno z nich replikowane jest jak mi ise wydaje co 2 tygodnie.
    Jednake sprawdzenie ostatniej daty logowania nie jest takie proste. Zrobilem maly tes i czesto dostawalem rozne czasy logowania dla tego samego uzytkownika.
    Ponizej przyklady czasu logowan dla jednego uzytkownika w zaleznosci od serweru i zmiennej ktora wykozystujemy
    server1 Last logon time: 17/04/2008 14:32:24
    server1 Last logontimeStamp: 09/03/2009 19:54:27
    server2 Last logon time: 17/04/2008 14:32:24
    server2 Last logontimeStamp: 09/03/2009 19:54:27
    server3 Last logon time: 13/03/2009 15:08:51
    server3 Last logontimeStamp: 09/03/2009 19:52:46
    server4 Last logon time: 13/03/2009 15:08:51
    server4 Last logontimeStamp: 09/03/2009 19:52:46
    server5 Last logon time: 13/03/2009 15:08:51
    server5 Last logontimeStamp: 09/03/2009 19:52:46
    server6 Last logon time: 23/02/2008 12:57:07
    server6 Last logontimeStamp: 09/03/2009 19:52:36
    server7 Last logon time: 24/02/2009 10:17:58
    server7 Last logontimeStamp: 09/03/2009 19:56:41
    server8 Last logon time: 24/02/2009 10:17:58
    server8 Last logontimeStamp: 09/03/2009 19:56:41
    server9 Last logon time: 24/02/2009 10:17:58
    server10 Last logontimeStamp: 09/03/2009 19:56:41
    server10 Last logon time: 24/02/2009 10:17:58
    server11 Last logontimeStamp: 09/03/2009 19:56:41
    server11 Last logon time: 24/02/2009 10:17:58
    server12 Last logontimeStamp: 09/03/2009 19:56:41
    server12 Last logon time: 13/03/2009 15:51:43
    server13 Last logontimeStamp: 09/03/2009 19:52:41
    server13 Last logon time: 03/10/2008 14:27:58

    To tylko czesc serwerow…
    jak widac roznice sa spore w zaleznosci jakiej metody uzyjemy.
    Jesli uzyjemy prostej metody pobrania LastLogonTimeStamp to w zaleznosci z ktorym serwerem sie polaczymy dostaniemy jakas wartosc…
    Rozwiazanie ktore ja zastosowalem to bylo odpytanie kazdego serwera z osobna o obie zmienne i wybranie najswiezszej daty.
    calosc zrobilem w VBS. Niestety zabiera to strasznie duzo czasu.
    U mnie jest okolo 2500 uzytkownikow i okolo 30 serwerow na calym swiecie wiec boje sie nawet uruchamiac ten scrypt.
    W powyzszym przypadku timeStamp jest calkiem OK ale zdazylo mi sie ze na niektorych serwerach niestety nie bylo zadnej daty logowania.
    Co w wypadku jesli akurat polaczymy sie z takim serwerem? dostaniemy ze uzytkownik sie nie logowal i go przeniesiemy…

    POzdrawiam i mam nadzieje ze w miare jasno napisalem

  3. kfaz

    Odpowiedz

    @Tomek
    1) rzeczywiście filtr jest trochę przekombinowany, zdecydowanie można zadawać ładniej zapytania do LDAP
    2) konwersja. To pisałem w Powershell 1 i wydaje mi się, że to co napisałeś działa dopiero od wersji 2 ale mogę się mylić
    3) a czemu własne a nie gotowe? Po prostu nie znałem narzędzia polecanego przez Ciebie, poza tym jeszcze parę innych rzeczy z kontami robię przy okazji :)

  4. kfaz

    Odpowiedz

    @Grzesiek
    Rzeczywiście nie doczytałem o tym, że ten atrybut jest replikowany (a w zasadzie nadpisywany) raz na 14 (-5) dni :-/

    Działa to tak:
    -jeśli: aktualnaData – msDS-LogonTimeSyncInterval > lastLogonTimeStamp to lastLogonTimeStamp = aktualna data

    Tutaj mamy dokładność 14 dni, czyli wiemy czy ktoś się logował w przeciągu ostatnich 14 dni czy nie. Jako, że skrypt liczy czas w miesiącach to nie ma opcji żeby przenieść konto komuś kto jest aktywny.

    Jeśli chcemy znać dokładną datę logowania to lepszą opcją wydaje się sprawdzenie na wszystkich kontrolerach domeny atrybutu lastlogon, wybranie najnowszego i uznawanie tego za wyznacznik w skryptach. Wadą takiego rozwiązania jest liczba zapytań i czas jaki to zajmie.

    Dla dociekliwych więcej o atrybucie i tym jak jest wyliczany jest tutaj http://technet.microsoft.com/en-us/library/cc772829.aspx

    —-
    Ten komenatrz był edytowany bo za pierwszym razem zrobiłem błąd w opisie.

  5. Odpowiedz

    @kfaz: pamietam, ze robilem taki 'systemik’ na pejocie ktory zapisuje logowanie do bazy sql. przez radmina mozna bylo sprawdzic dokaldnie logowanie i na ktorym kompie jest teraz user – czy to jeszcze dziala? ktos to moze poprawial?

  6. Odpowiedz

    Ciągle działa i jako, że to skompilowany VBS to dopóki działa to nie ruszamy :-)
    Jednak skrypt jako, że działa na stacjach nie zapisuje np. logowania do poczty.

Skomentuj kfaz Anuluj pisanie odpowiedzi

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload CAPTCHA.