Приветствую Вас ГостьЧетверг, 21.11.2024, 16:56

В помощь админу


Каталог статей

Главная » Статьи » Windows » Скрипты

Скрипт автоматически выкидывающий пользователей из терминальной сессии.

Так как пользователи по большей степени не хотят вникать во все компьютерные тонкости, то нам, админам, приходится постоянно бороться не только с серверами, но и с обычными юзерами! К чему это я? Да всё очень просто - имеется у нас в одном филиале терминальный сервер 1C, но так как денег было мало выделено, то удалось в сервак поставить всего 16 гектар оперативки. Но сам терминальный сервак сделал я виртуальным, в итоге я выделил ему всего 10 гектар оперативы, 2 на виртуальный контроллер контроллер домена, 2 под FreeBSD для бэкапов, остальное отдал под платформу VMWare ESXI 5.1. Я начал потихоньку переносить пользователей в домен, а их контроллер перенёс в отдельный сайт. После успешного переноса всех пользователей на новый терминальный сервер выяснилось, что не хватает памяти в серваке.
После проведённого анализа выяснилось, что всю память съедает SQL, на котором крутится 1С. Было решено провести ряд мер по изменению ситуации:

  1. Удалось приобрести простенький NAS от D-Link. Туда я перенёс бэкапы и соответственно избавился от FreeBS. Терминальному серверу выделил ещё 2 гектара оперативы.
  2. Удалось приобрести ещё 4 планки памяти по 2 гектара. Заменил в серваке 4 планки с 1 на 2 гектара. В итоге прирост ещё в 4 гектара.
  3. Был написан скрипт, который автоматически выбрасывает пользователей из терминальной сессии, что приводит к выгрузке из памяти профиля пользователя со всеми службами и процессами пользователя, что существенно повлияло на работоспособность сервера.

Сам скрипт написал на VBS, на серваке создал задание, которое запускает скрипт каждый час. При написании скрипта были поставлены следующие задачи:

  1. Не трогать сессии админов!
  2. Тех пользователей, что просто нажали на крестик (т.е. неправильно закрыли сессию) выкидываем сразу.
  3. Остальных пользователей выкидываем при простое большем чем в 9 часов (почему выбрано именно так, а не всех поголовно в определённое время? филиал работает круглосуточно!).
  4. Не забываем про отчётность! админ должен знать что и когда происходило!

Сам скрипт RDP_Reset.vbs:

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Скрипт следит за терминальными пользователями и выкидывает их сессии по условиям: '
'    1.По какой-либо причине не произошёл выход из сессии                           '
'    2.Пользователь не закрывает сессию более 8 часов! Просто какой-то кашмар -     '
'      пора домой, а они кричат: "Хлебом не корми - работу давай!"                  '
'               Скрипт написал Анчуров Олег Владимирович в 2013 году.               '
'                     Скрипт взят с сайта: http://ithelp.moy.su                     '
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

On Error Resume Next
Dim WshShell, WshShell2
Dim objScriptExec, objScriptExec2
Set WshShell = CreateObject("Wscript.Shell")
Set WshShell2 = CreateObject("Wscript.Shell")
Set objScriptExec = WshShell.Exec("qUser.exe")
Dim User, Rdp, Id, Status, OffLine, TDate, TTime
Dim Line, Line2
Dim a, c, t, p, i, Reset
Dim Msg, k

Msg = "ПРОТОКОЛ РАБОТЫ СКРИПТА, АВТОМАТИЧЕСКИ ВЫКИДЫВАЮЩЕГО ПОЛЬЗОВАТЕЛЕЙ ИЗ ТЕРМИНАЛЬНЫХ СЕССИЙ НА ТЕРМИНАЛЬНОМ СЕРВАКЕ:" + chr(13) + chr(10) + chr(13) + chr(10)
k = 0

Do Until objScriptExec.StdOut.AtEndOfStream
    Line = objScriptExec.StdOut.ReadLine
    Line2 = ""
    'Производим перекодировку текста из Dos в ANSI:
    For i = 1 to Len(Line)
        a = Asc(Mid(Line,i,1))
        If a < 128 then Line2 = Line2 + chr(a)
        If a > 127 and a < 176 then Line2 = Line2 + chr(a + 64)
        If a > 175 and a < 224 then Line2 = Line2 + chr(a)
        If a > 223 and a < 240 then Line2 = Line2 + chr(a + 16)
        If a = 240 then Line2 = Line2 + chr(168)
        If a = 241 then Line2 = Line2 + chr(184)
        If a > 241 then Line2 = Line2 + chr(a)
    Next
    Line = Line2
   
    'Разщипляем строку на составляющие
    User = LCase(Trim(Mid(Line, 2, 22)))
    Rdp = LCase(Trim(Mid(Line, 24, 16)))
    Id = LCase(Trim(Mid(Line, 40, 6)))
    Status = LCase(Trim(Mid(Line, 47, 8)))  'Если нужно, то раскоментировать!
    OffLine = LCase(Trim(Mid(Line, 55, 12)))
    TDate = LCase(Trim(Mid(Line, 67, 11)))  'Если нужно, то раскоментировать!
    TTime = LCase(Trim(Mid(Line, 78, 6)))   'Если нужно, то раскоментировать!

    'Первая строка нас не интересует!
    'Переменная Rdp может принимать следующие значения:
    'rdp-tcp#xxx   - стандартный клиент RDP
    'console       - консоль, например из DameWare
    'пустая строка - пользователь отключился некорректно
    If Rdp <> "сеанс" Then
        a = 0
        a = a + InStr(User,"admin1") 'Эту учётку трогать низя!
        a = a + InStr(User,"admin2") 'Эту учётку трогать низя!
        a = a + InStr(User,"admin3") 'Эту учётку трогать низя!
        a = a + InStr(User,"admin4") 'Эту учётку трогать низя!
        'Остальные учётки проверяем дальше...
        If a = 0 then
            c = 0
            t = 0
            p = 0
            If OffLine = "отсутствует" then c = c + 1 'Если была закрыта сессия просто крестиком или по какой-либо причине не произошёл выход из системы, то сразу необходимо выкинуть пользователя из сессии!
            p = InStr(OffLine,":")
            If p > 0 then
                t = CDbl(Left(OffLine,p - 1))
                If t > 8 then c = c + 1 'Если пользователь не выключает комп на ночь и его сессия простаивает больше 8 часов, то тоже выкидываем из сессии!
            End If
            If c > 0 then
                Reset = "logoff " & Id 'Команду LogOff можно заменить на Reset Session. Кому что больше подходит.
                Set objScriptExec2 = WshShell2.Exec(Reset)
                Msg = Msg + "Отключен пользователь: " + User + chr(13) + chr(10)
                Msg = Msg + "Значения параметров команды QUser для данного пользователя: " + chr(13) + chr(10)
                Msg = Msg + "     Пользователь: " + User + chr(13) + chr(10)
                Msg = Msg + "    Сеанс:        " + Rdp + chr(13) + chr(10)
                Msg = Msg + "    ID:           " + Id + chr(13) + chr(10)
                Msg = Msg + "    Статус:       " + Status + chr(13) + chr(10)
                Msg = Msg + "    Бездействие:  " + Offline + chr(13) + chr(10)
                Msg = Msg + "    Время входа:  " + TDate + "/" + TTime + chr(13) + chr(10) + chr(13) + chr(10)
                k = k + 1
                WScript.Sleep 3000 'Это время (в млсек) ждёт скрипт, пока будет исполнена команда Logoff. если паузы не делать, то будет отключен только первый пользователь, а остальных проигнорирует!
            End If
        End If
    End If
Loop
Set objScriptExec = Nothing
Set WshShell = Nothing

If k > 0 then
    Dim objEmail
    MSG = MSG + "Всего отключено контактов: " + CStr(k) + chr(13) + chr(10) + chr(13) + chr(10)
    MSG = MSG + "Время/дата отработки скрипта: " + CStr(Time) + "/" + CStr(Date) + chr(13) + chr(10)
    'WScript.Echo(MSG)
   
    Const EmailFrom = "bot@firma.ru"         ' от кого будет отправляться e-mail
    Const EmailPassword = "SuperPassword"       ' пароль от e-mail
    Const strSmtpServer = "smtp.firma.ru" ' smtp сервер
    Const EmailTo = "admin@firma.ru"    ' Кому будет отправляться e-mail
    Set objEmail = CreateObject("CDO.Message")
   
    objEmail.From = EmailFrom
    objEmail.To = EmailTo
    objEmail.Subject = "Отчёт по работе скрипта RDP_Reset" 'Тема письма
    objEmail.Textbody = MSG
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusername") = EmailFrom
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendpassword") = EmailPassword
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSmtpServer
    objEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
    objEmail.Configuration.Fields.Update
    objEmail.Send
    Set objEmail = Nothing
End If

 

Админ должен больше отдыхать! Удачи!

Категория: Скрипты | Добавил: isz (21.09.2013)
Просмотров: 9041 | Комментарии: 2 | Теги: пользователь, Скрипт, терминальная сессия, vbscript, терминальный сервер, терминал, vbs | Рейтинг: 5.0/1
Всего комментариев: 2
2 isz  
0
Появилась хорошая новость - наконец-то мне удалось адаптировать данный скрипт под 2012 терминальный сервак!
Смотрим что в итоге получилось здесь.

1 isz  
0
Внимание, есть интересная заметка. Данный скрипт идеально работает под Windows Server 2003 и идеально перехватывает оба события (простой по времени и некорректное завершение сессии), но есть большое но! На 2012 сервере данный скрипт работает только по одному событию - простой по времени. Связано это с отличием результата отработки команды quser в разных версиях ОС. На 2008 платформе не удалось проверить пока. Если кто это уже сделал, просьба отпишитесь в коментах.
Просьба не судить строго. Для меня это тоже печальная новость, но пока я не нашёл способа решения данной проблемы в виду отсутствия времени.
Если у кого есть мысли, которые помогут мне ускорить адаптацию скрипта, то пишем сюда в коменты. Заранее спасибо...

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Категории раздела
Active Directory [12]
DHCP [1]
Windows [13]
Wins [1]
Групповая политика [3]
Программы [2]
Резервное копирование [6]
Сеть [5]
Скрипты [31]
Терминальный сервер [7]
Почта [7]
Реестр [2]
Реестр Windows
Командная строка [7]
CMD: Командная строка Windows
Поиск
Форма входа
Наш опрос
Оцените мой сайт
Всего ответов: 149
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика