Как асинхронно запускать процедуры в powershell
Перейти к содержимому

Как асинхронно запускать процедуры в powershell

  • автор:

Применение PowerShell для ИТ-безопасности. Часть V: оптимизация платформы безопасности с использованием скриптов

Несколько месяцев тому назад я приступил к решению одной задачи. Я решил доказать, что PowerShell может использоваться как инструмент контроля безопасности. Я закончил работу над своей публикацией, в которой описывается код PowerShell, позволяющий собирать события файловой системы, выполнять некоторые базовые функции анализа, а затем выводить результаты в графическом формате. Возможно, моя платформа безопасности с использованием скриптов (Security Scripting Platform; SSP) не является минимально жизнеспособным продуктом, но она, как мне кажется, полезна в качестве простого инструмента контроля для одиночного каталога файлов.

По завершении проекта я понимал, что определенный функционал можно усовершенствовать. Обработка событий выполнялась неэф-фективно. Передача информации между различными частями платформы SSP требовала оптимизации, а информация, отображаемая с помощью примитивного кода Out-GridView, была представлена в виде прославленной таблицы.

Новые и улучшенные возможности

Я решил повысить жизнеспособность платформы SSP. В первую очередь нужно было оптимизировать процедуру обработки событий. Изначально она была разработана таким образом, что обработчик в моем блоке скрипта Register-EngineEvent (см. информацию о блоках скриптов) извлекал сообщения о событиях файла и отправлял их во внутреннюю очередь, а затем — в основной фрагмент кода, ПО для классификации.

Подумав немного, я понял, что можно отправлять сообщения напрямую с помощью функции Register-EngineEvent -forward из блока скрипта обработки событий и просто удалить ненужный уровень этих жутких очередей.

Ниже представлена упрощенная и оптимизированная версия.

1. #Count events, detect bursts, forward to main interface 2. 3. $cur = Get-Date 4. $Global:Count=0 5. $Global:baseline = @ 6. $Global:cnts = @(0,0,0) 7. $Global:burst = $false 8. $Global:evarray = New-Object System.Collections.ArrayList 9. 10. $action = < 11. $Global:Count++ 12. $d=(Get-Date).DayofWeek 13. $i= [math]::floor((Get-Date).Hour/8) 14. 15. $Global:cnts[$i]++ 16. 17. 18. #event auditing! 19. 20. $rawtime = $EventArgs.NewEvent.TargetInstance.LastAccessed.Substring(8,6) 21. $filename = $EventArgs.NewEvent.TargetInstance.Name 22. $etime= [datetime]::ParseExact($rawtime,"HHmmss",$null) 23. 24. 25. $msg="$($etime)): Access of file $($filename)" 26. $msg|Out-File C:\Users\Administrator\Documents\events.log -Append 27. 28. New-Event -SourceIdentifier Delta -MessageData "Access" -EventArguments $filename #notify 29. 30. $Global:evarray.Add(@($filename,$etime)) 31. if(!$Global:burst) < 32. $Global:start=$etime 33. $Global:burst=$true 34. >35. else < 36. if($Global:start.AddMinutes(15) -gt $etime ) < 37. $Global:Count++ 38. #File behavior analytics 39. $sfactor=2*[math]::sqrt( $Global:baseline["$($d)"][$i]) 40. 41. if ($Global:Count -gt $Global:baseline["$($d)"][$i] + 2*$sfactor) < #at 95% level of poisson 42. 43. 44. "$($etime): Burst of $($Global:Count) accesses"| Out-File C:\Users\Administrator\Documents\events.log -Append 45. $Global:Count=0 46. $Global:burst =$false 47. New-Event -SourceIdentifier Delta -MessageData "Burst" -EventArguments $Global:evarray #notify on burst 48. 49. $Global:evarray= [System.Collections.ArrayList] @() 50. >51. > 52. else < $Global:burst =$false; $Global:Count=0; $Global:evarray= [System.Collections.ArrayList] @()>53. > 54. > 55. 56. Register-EngineEvent -SourceIdentifier Delta -Forward 57. Register-WmiEvent -Query "SELECT * FROM __InstanceModificationEvent WITHIN 5 WHERE TargetInstance ISA 'CIM_DataFile' and TargetInstance.Path = '\\Users\\Administrator\\' and targetInstance.Drive = 'C:' and (targetInstance.Extension = 'txt' or targetInstance.Extension = 'doc' or targetInstance.Extension = 'rtf') and targetInstance.LastAccessed > '$($cur)' " -sourceIdentifier "Accessor" -Action $action 58. Write-Host "starting engine . " 59. 60. while ($true)

Затем я взял основной фрагмент кода, где выполняется классификация файлов по наличию номеров социального страхования и прочих важных ключевых слов. При поступлении событий из обработчика запускается реклассификация файлов. Затем этот код периодически отображает некоторые результаты классификации.

В последней версии я удалил классификацию в «реальном времени» и сосредоточился на очистке кода PowerShell и улучшении графики — об этом речь пойдет ниже.

В первоначальной версии я выбрал неправильный путь и доверил модулю блокировки данных PowerShell синхронизацию доступа к данным от параллельных задач, которые я применял для выполнения рутинной работы. Последующее тестирование показало, что бесплатный модуль, который реализует командлет Lock-Object, не работает.

Даже начинающие системные программисты знают, что синхронизацию проще выполнять с помощью сообщений, а не низкоуровневых блокировок. Я изменил код, и теперь, как упоминалось выше, сообщения направляются из обработчика событий непосредственно в основной цикл обработки сообщений. Иными словами: мне удалось обеспечивать обработку асинхронных событий в синхронном режиме.

PowerShell и диаграммы .Net Framework

Самое заметное мое достижение за последний месяц — я разобрался, как встраивать диаграммы в стиле Майкрософт в PowerShell. Другими словами, гистограммами, линейными, точечными и иными диаграммами, доступными в Excel и Word, можно управлять на программном уровне в PowerShell. Я сравнительно недавно занимаюсь программированием в PowerShell, поэтому меня это сильно порадовало. Дополнительную информацию об элементах управления .Net Framework см. в этой публикации.

Это классно! Поначалу я даже подумал, что смогу также заменить запутанный код Out-GridView.
Но вскоре стало ясно, что проблема состоит в том, что помимо этого приходится иметь дело с элементами интерактивного программи-рования, связанными с формами Майкрософт. Я же просто хотел отображать свои диаграммы .Net и не писать код для низкоуровневых функций. Существует ли упрощенный способ решения этой задачи?

После активных размышлений я пришел к выводу, что простейшим способом в данной ситуации будет запуск каждой диаграммы в ее собственной функции runspace как отдельной задачи. (Примечание для фанатов: таким образом я избавился от необходимости создания функции обработки сообщений для всех диаграмм, так как каждая из них выполняется отдельно в виде модальных диалогов.)

В этом мне также помог бесплатный модуль PowerShell, который сворачивает запутанные элементы управления диаграмм .Net. Спасибо тебе, Мариус!

Ранее я уже настроил систему управления задачами, чтобы сканировать и классифицировать каждый контролируемый файл в каталоге. И теперь для запуска диаграмм мне нужно было просто обеспечить повторное использование этого кода управления задачами.

Я создал круговую диаграмму для представления относительной концентрации конфиденциальных данных, гистограмму для разбивки файлов по типу конфиденциальных данных. Но больше всего я горжусь классической ступенчатой диаграммой событий для условий всплеска доступа к файлам, что может быть признаком атаки.

Моя отличная информационная панель. Неплохо для PowerShell
с диаграммами .Net.

Если кому-то из вас интересен основной фрагмент кода, выполняющего всю работу в моей платформе SSP, то он приведен здесь ниже:

1. $scan = < #file content scanner 2. $name=$args[0] 3. function scan < 4. Param ( 5. [parameter(position=1)] 6. [string] $Name 7. ) 8. $classify =@-[0-9]-[0-9]' > 9. 10. $data = Get-Content $Name 11. 12. $cnts= @() 13. 14. if($data.Length -eq 0) < return $cnts>15. 16. foreach ($key in $classify.Keys) < 17. 18. $m=$classify[$key].matches($data) 19. 20. if($m.Count -gt 0) < 21. $cnts+= @($key,$m.Count) 22. >23. > 24. $cnts 25. > 26. scan $name 27. > 28. 29. 30. 31. 32. #launch a .net chart 33. function nchart ($r, $d, $t,$g,$a) < 34. 35. $task= < 36. Param($d,$t,$g,$a) 37. 38. Import-Module C:\Users\Administrator\Documents\charts.psm1 39. $chart = New-Chart -Dataset $d -Title $t -Type $g -Axis $a 40. Show-Chart $chart 41. 42. >43. $Task = [powershell]::Create().AddScript($task).AddArgument($d).AddArgument($t).AddArgument($g).AddArgument($a) 44. $Task.RunspacePool = $r 45. $Task.BeginInvoke() 46. 47. > 48. 49. Register-EngineEvent -SourceIdentifier Delta -Action < 50. 51. if($event.MessageData -eq "Burst") < #just look at bursts 52. New-Event -SourceIdentifier File -MessageData $event.MessageData -EventArguments $event.SourceArgs 53. >54. 55. 56. Remove-Event -SourceIdentifier Delta 57. > 58. 59. 60. 61. 62. $list=Get-WmiObject -Query "SELECT * From CIM_DataFile where Path = '\\Users\\Administrator\\' and Drive = 'C:' and (Extension = 'txt' or Extension = 'doc' or Extension = 'rtf')" 63. 64. 65. #long list --let's multithread 66. 67. #runspace 68. $RunspacePool = [RunspaceFactory]::CreateRunspacePool(1,5) 69. $RunspacePool.Open() 70. $Tasks = @() 71. 72. 73. 74. 75. foreach ($item in $list) < 76. 77. $Task = [powershell]::Create().AddScript($scan).AddArgument($item.Name) 78. $Task.RunspacePool = $RunspacePool 79. 80. $status= $Task.BeginInvoke() 81. $Tasks += @($status,$Task,$item.Name) 82. >83. 84. 85. 86. 87. #wait 88. while ($Tasks.isCompleted -contains $false) < 89. 90. >91. 92. 93. #Analytics, count number of sensitive content for each file 94. $obj = @<> 95. $tdcnt=0 96. $sfcnt=0 97. $nfcnt=0 98. 99. 100. for ($i=0; $i -lt $Tasks.Count; $i=$i+3) < 101. $match=$Tasks[$i+1].EndInvoke($Tasks[$i]) 102. 103. if ($match.Count -gt 0) < 104. $s = ([string]$Tasks[$i+2]).LastIndexOf("\")+1 105. 106. $obj.Add($Tasks[$i+2].Substring($s),$match) 107. for( $j=0; $j -lt $match.Count; $j=$j+2) < 108. switch -wildcard ($match[$j]) < 109. 'Top*' < $tdcnt+= 1 >110. 111. 'Sens*' < $sfcnt+= 1>112. 113. 'Numb*' < $nfcnt+=1>114. 115. > 116. 117. > 118. > 119. $Tasks[$i+1].Dispose() 120. 121. > 122. 123. 124. #Display Initial Dashboard 125. #Pie chart of sensitive files based on total counts of senstive dat 126. $piedata= @<> 127. foreach ( $key in $obj.Keys) < 128. $senscnt =0 129. for($k=1; $k -lt $obj[$key].Count;$k=$k+2) < 130. $senscnt+= $obj[$key][$k] 131. 132. >133. $piedata.Add($key, $senscnt) 134. 135. > 136. 137. 138. nchart $RunspacePool $piedata "Files with Sensitive Content" "Pie" $false 139. 140. #Bar Chart of Total Files, Sensitive vs Total 141. $bardata = @ 142. $bardata.Add("Files w. Top Secret",$tdcnt) 143. $bardata.Add("Files w. Sensitive", $sfcnt) 144. $bardata.Add("Files w. SS Numbers",$nfcnt) 145. 146. 147. nchart $RunspacePool $bardata "Sensitive Files" "Bar" $false 148. 149. 150. #run event handler as a seperate job 151. Start-Job -Name EventHandler -ScriptBlock() 152. 153. 154. while ($true) < #main message handling loop 155. 156. [System.Management.Automation.PSEventArgs] $args = Wait-Event -SourceIdentifier File # wait on event 157. Remove-Event -SourceIdentifier File 158. #Write-Host $args.SourceArgs 159. if ($args.MessageData -eq "Burst") < 160. #Display Bursty event 161. $dt=$args.SourceArgs 162. #time in seconds 163. [datetime]$sevent =$dt[0][1] 164. 165. $xyarray = [ordered]@<>166. $xyarray.Add(0,1) 167. for($j=1;$j -lt $dt.Count;$j=$j+1) < 168. [timespan]$diff = $dt[$j][1] - $sevent 169. $xyarray.Add($diff.Seconds,$j+1) 170. >171. nchart $RunspacePool $xyarray "Burst Event" "StepLine" $true 172. > 173. 174. 175. >#while 176. 177. Write-Host "Done!"

Извлеченные уроки

Конечно, в рамках любой задачи главным является не сама цель, а процесс поиска решения. Согласны? В данном случае я узнал главную для себя вещь — PowerShell можно использовать для контроля безопасности. Для одиночного каталога, в небольшой системе. Причем только в случае эпизодического использования.

Я планирую внести определенные улучшения в реализацию, которую я только что представил (добавить графику в режиме реального времени), однако я вовсе не ожидаю, что мое финальное программное обеспече-ние станет чем-то большим, чем просто модельным проектом.

Контроль событий файлов, анализ и графическое отображение информации для всей системы — это крайне сложная задача для одного человека. В принципе, мое решение можно перекодировать, используя C++, но в рамках приложения по-прежнему придется решать проблему задержек и отклонений при обработке низкоуровневых событий. Чтобы сделать это правильно, необходимо иметь некие механизмы глубоко в самой ОС (для начала), а затем выполнять гораздо более серьезный анализ событий файлов, чем тот, что выполняется моим примитивным кодом. Это далеко не просто!

Обычно я заканчиваю подобные публикации категории «сделай сам» словами «вы знаете, о чем речь». Не буду вас разочаровывать.

Вы знаете, о чем речь. Наше собственное решение корпоративного класса является настоящейплатформой безопасности данных (Data Security Platform; DSP), так как оно выполняет функции классификации, анализа, обнаружения угроз и многое другое на уровне целых ИТ-систем.

Не отступайте, пробуйте свои варианты. Может быть, даже на основе этого проекта. Разбирайтесь с реальными возможностями платформы DSP, изучайте ее слабые и сильные стороны.

Есть вопросы? Не стесняйтесь и задавайте их нам!

  • powershell
  • varonis
  • информационная безопасность
  • хранение данных

Асинхронное выполнение хранимых процедур в MS SQL Server средствами Access 2003

Если у Вас встала задача асинхронно выполнять хранимые процедуры в Microsoft SQL Server, при этом эти процедуры будут запускаться из клиента Access 2003, то данный материал будет Вам полезен, так как в нем я покажу на примере как можно решить данную задачу средствами VBA Access.

Асинхронное выполнение хранимых процедур в MS SQL Server

Для начала давайте разберемся, что мы понимаем под «асинхронное выполнение хранимых процедур». Это то, когда мы запускаем на выполнение хранимую процедуру и, не дожидаясь окончания ее работы, запускаем другую процедуру или вовсе продолжаем работать в клиенте.

Нам это может потребоваться, например, в случаях, когда у нас несколько баз данных и нам одновременно на всех БД нужно из клиента запустить некие процедуры (для чего это может потребоваться неважно). Или, например, процедура очень долго выполняется, а нам необходимо работать в программе дальше.

Итак, а сейчас давайте разберемся, какие средства при этом мы будем использовать. В качестве SQL сервера для примера у меня будет выступать SQL Server 2012, в качестве клиента ADP проект Access 2003. В качестве инструментов реализации асинхронного выполнения процедур я буду использовать объект ADODB.Command, который позволяет это делать, при этом мы можем сделать так, чтобы клиент оповестил нас об окончание работы хранимых процедур.

Исходные данные

Допустим, у нас есть база данных Test, а в ней есть хранимые процедуры SP_Test_1 и SP_Test_2.

USE [Test] GO CREATE PROCEDURE dbo.SP_Test_1(@TestParam AS INT) AS BEGIN /* SQL инструкция Вашей хранимой процедуры Я в качестве примера просто приостанавливаю выполнение процедуры на 5 секунд */ WAITFOR DELAY '00:00:05'; SELECT @TestParam END GO CREATE PROCEDURE dbo.SP_Test_2(@TestParam AS INT) AS BEGIN /* SQL инструкция Вашей хранимой процедуры Я в качестве примера просто приостанавливаю выполнение процедуры на 5 секунд */ WAITFOR DELAY '00:00:05'; SELECT @TestParam END

Заметка! Для комплексного изучения языка T-SQL рекомендую посмотреть мои видеокурсы по T-SQL, в которых используется последовательная методика обучения и рассматриваются все конструкции языка SQL и T-SQL.

Adp проект настроен на работу с базой данных.

Задача. Нам необходимо запустить эти процедуры в асинхронном режиме, чтобы вторая, независимо от того завершила ли выполнение первая процедура, начала свою работу.

Асинхронный запуск хранимых процедур из Access 2003

Как я уже сказал данный способ, подразумевает использование объекта ADODB.Command. Для решения задачи на форму добавим кнопку с названием TestExec, а в обработчик события «Нажатие кнопки» вставляем следующий код (он прокомментирован).

Private Sub TestExec_Click() On Error GoTo Err1 'Переменные Dim SQLCmd1 As ADODB.Command, SQLCmd2 As ADODB.Command Dim TestRS1 As Recordset, TestRS2 As Recordset Dim StartTime As Date, TimeALL As String Dim TmpTimeHour As String, TmpTimeMinute As String, TmpTimeSecond As String 'Создание объектов Set SQLCmd1 = New ADODB.Command Set SQLCmd2 = New ADODB.Command 'Настройки объекта SQLCmd1 With SQLCmd1 .CommandTimeout = 0 .ActiveConnection = CurrentProject.Connection 'Текущее соединение .CommandType = adCmdStoredProc 'Будем выполнять хранимую процедуру .CommandText = "dbo.SP_Test_1" 'Имя хранимой процедуры 'Параметр хранимой процедуры .Parameters.Append .CreateParameter("@TestParam", adBigInt, adParamInput, , 1) End With 'Настройки объекта SQLCmd2 With SQLCmd2 .CommandTimeout = 0 .ActiveConnection = CurrentProject.Connection .CommandType = adCmdStoredProc .CommandText = "dbo.SP_Test_2" .Parameters.Append .CreateParameter("@TestParam", adBigInt, adParamInput, , 2) End With 'Запоминаем время старта 'Просто для того чтобы знать сколько выполнялись наши процедуры StartTime = Now TmpTimeHour = Hour(StartTime) TmpTimeMinute = Minute(StartTime) TmpTimeSecond = Second(StartTime) 'Запускаем процедуры в асинхронном режиме Set TestRS1 = SQLCmd1.Execute(, , adAsyncExecute) 'Set TestRS1 = SQLCmd1.Execute 'Запуск в обычном режиме Set TestRS2 = SQLCmd2.Execute(, , adAsyncExecute) 'Ждем пока процедуры выполнятся Do Until TestRS1.State <> 4 And TestRS2.State <> 4 DoEvents Loop 'Узнаем продолжительность выполнения процедур 'И выводим время в формате "00:00:00" 'Часы If Hour(Now - StartTime) < 10 Then TmpTimeHour = "0" & Hour(Now - StartTime) Else TmpTimeHour = Hour(Now - StartTime) End If 'Минуты If Minute(Now - StartTime) < 10 Then TmpTimeMinute = "0" & Minute(Now - StartTime) Else TmpTimeMinute = Minute(Now - StartTime) End If 'Секунды If Second(Now - StartTime) < 10 Then TmpTimeSecond = "0" & Second(Now - StartTime) Else TmpTimeSecond = Second(Now - StartTime) End If 'Формируем время TimeALL = TmpTimeHour & ":" & TmpTimeMinute & ":" & TmpTimeSecond MsgBox "Операция выполнена за " & TimeALL, vbInformation, "Сообщение" 'Очищаем Recordset Set TestRS1 = Nothing Set TestRS2 = Nothing Ex1: Exit Sub Err1: MsgBox Err.Description End Sub

Сохраняем и нажимаем на кнопку, т.е. проверяем работу.

Скриншот 1

Видим, что процедуры выполнились одновременно, асинхронный режим работает.

На этом у меня все, пока!

1000++ способ запуска команд на удаленном компьютере

В наше время даже для собак придумали удаленное управление.

Возвращаясь к циклу «Конспект Админа», мне хотелось бы рассказать о вариантах запуска исполняемых программ на удаленных компьютерах. Эта статья будет интересна тем, у кого еще нет систем централизованного управления, но уже есть понимание утомительности ручного обхода рабочих станций и серверов. Либо тем, кому решения «под ключ» не интересны ввиду неспортивности.

В качестве того, зачем нужен такой запуск программ, можно привести недавнюю истерию с Петей\Не-Петей, когда все бросились проверять\отключать SMBv1 и загружать обновления. Да и провести инвентаризацию или установить срочный патч таким методом тоже можно.

Когда-то давно я устроился работать в организацию в период эпидемии Kido\Conficker. Наиболее простым способом выяснить, все ли хорошо в ИС компании, была славная утилита от Касперского под названием Kido Killer, которая проверяла наличие вируса и устраняла его. Запускать программу на доброй сотне машин руками было невесело, поэтому пришлось знакомиться с автоматизацией.

Если в операционных системах *nix для удаленного запуска, как правило, используется SSH, то у Windows способов запуска программ и скриптов воистину как песка в пустыне. Я разберу основные варианты, как общеизвестные, так и экзотические. Таких очевидных вещей как telnet-сервер касаться не буду, тем более Microsoft уже убрала его из современных ОС.

Способы старые, временем проверенные

Psexec

Пожалуй, это первое, что приходит на ум, когда идет речь об удаленном запуске программ. Утилита от Марка Руссиновича используется еще со времен Windows NT и до сих пор применяется. Помимо основной функции, можно использовать ее и как Runas, и для запуска программ в пользовательской сессии терминального сервера. Psexec также позволяет задавать ядра процессора, на которых будет запускаться программа, и ее приоритет в системе.

В качестве примера посмотрим, установлено ли обновление, закрывающее нашумевшую уязвимость SMB на списке компьютеров:

psexec @computers.txt /u USER /p PASS cmd.exe /v /c ""systeminfo | find "KB4012212" || echo !computername! >> \\server\share\log.txt"""

В файле computers.txt находится список компьютеров. Для запуска по всему домену можно использовать \\*. В файле \\server\share\log.txt будут появляться имена рабочих станций или серверов без обновления. Если в домене существуют компьютеры с *nix на борту или нет доступа к административному сетевому ресурсу Admin$ ― команда на этой машине не выполнится, но обработка продолжится. Чтобы скрипт не зависал при каждой попытке подключения, можно задать тайм-аут с помощью ключа -n.

Если компьютер выключен ― мы об этом не узнаем. Поэтому лучше предварительно проверять доступность машин или собирать в файле информацию об успешном или неудачном выполнении.

К минусам Psexec можно отнести то, что она из-за своего удобства и популярности часто используется вирусописателями. Поэтому антивирусные системы могут обнаруживать утилиту как опасность вида remote admin.

По умолчанию процесс на удаленной машине выполняется от имени пользователя, запустившего Psexec. При необходимости логин и пароль можно задать явно или же использовать аккаунт SYSTEM.

WMIC

Для управления системами Windows с помощью разных графических утилит часто используется WMI (Windows Management Instrumentation) ― реализация объектно-ориентированного стандарта управления WBEM. В качестве утилиты с графическим интерфейсом для работы с WMI можно использовать wbemtest.exe.

Для работы с WMI из консоли создана wmic.exe. Например, для проверки установленных обновлений вместо жутковатой конструкции из предыдущего примера можно использовать простую команду:

wmic /node:"servername" qfe get hotfixid | find "KB4012212"

Использовать список компьютеров также можно командой /node:"@computers.txt".

Еще при помощи WMI можно запускать программы – синтаксис предельно прост:

wmic /node:"servername" process call create "cmd /c somecommands"

К сожалению, в отличие от Psexec, получить вывод в консоли не получится ― придется выводить результаты команды в файл.

По умолчанию процесс на удаленной машине выполняется от имени пользователя, запустившего wmic. При необходимости логин и пароль можно задать явно.

Групповые политики и скрипты

Если предыдущие варианты не требовали доменной среды, то в этом случае потребуется домен. Поддерживаются скрипты при входе и выходе пользователя из системы, а также при ее включении и выключении. Поскольку каждый администратор Windows сталкивался с ними, я не буду подробно расписывать как ими пользоваться ― лишь напомню, где их искать.

Скрипты, выполняющиеся при старте и завершении системы.

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

Скрипты, настраиваемые в пользовательском разделе, выполняются от имени пользователя, а в разделе компьютера ― под аккаунтом SYSTEM.

Назначенные задания

Довольно интересный способ, заслуживающий право на жизнь. Назначенные задания можно создавать из командной строки при помощи утилиты schtasks.exe, выполнять их, затем удалять. Подробнее с синтаксисом можно ознакомиться в документации, я же разберу пример использования назначенных заданий в доменной среде. Предположим, нам нужно выполнить команду как можно быстрее вне зависимости от того, выключен компьютер или нет. Для этого используются так называемые предпочтения групповых политик (Group Policy Preference).

Искать установку назначенных заданий следует в конфигурации компьютера или пользователя ― «Настройка ― Параметры панели управления ― Назначенные задания».

Создание нового назначенного задания.

Для выполнения команды или скрипта ASAP понадобится создать «Немедленную задачу (Windows 7 и выше)». Если вдруг в инфраструктуре остались машины под управлением Windows XP, то подойдет «Очередное задание (Windows XP)».

Стоит сделать несколько политик с соответствующими WMI-фильтрами или создать два разных назначенных задания в одной политике с нацеливанием ― например, при помощи того же WMI-фильтра. Это поможет избежать конфликтов в разнородной среде со старыми и новыми Windows.

Пример WMI-фильтра для применения политики только на компьютерах с Windows XP:

SELECT * FROM Win32_OperatingSystem WHERE Version LIKE "5.1%" AND ProductType = "1"

В остальном процедура создания назначенного задания тривиальна. Единственное, не забывайте отметить пункт «Применить один раз и не применять повторно», если задача не требует повторного запуска.

Запускаем немедленную задачу только один раз.

При использовании таких назначенных заданий программа запустится, как только компьютер получит обновление групповой политики. Это удобно: не нужно проверять доступность компьютеров в случае Psexec и wmic и заставлять пользователей перезагружать машины, как в случае скриптов групповых политик. При необходимости можно скопировать файл скрипта локально в разделе «Настройка ― Конфигурация Windows ― Файлы».

Назначенные задания позволяют явно задать имя пользователя для запуска программы, в том числе и для SYSTEM.

Через реестр

Модификация реестра на пользовательских машинах ― странный вариант, лишь на случай крайней необходимости. Можно использовать ветки Run или RunOnce. Подробнее о них ― в документации. Сама модификация реестра может проводиться через групповые политики или из командной строки ― например, такой командой:

reg add \\COMPUTER\HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce /v script /t Reg_SZ /d "script.cmd"

В зависимости от ветки реестра, процесс будет выполняться или под пользователем, выполнившим вход в систему, или под аккаунтом SYSTEM.

Есть и другие способы, такие как правка ярлыков в папке «Автозагрузка» или добавление в ярлык к популярной программе && script.cmd, но эти методы уже из серии «можно, но не нужно».

Теперь перейдем к новым инструментам.

Способы новые или куда же без PowerShell

PowerShell, оправдывая свое название, может подключаться к удаленным компьютерам при помощи WMI, RPC и WS-Management (WSMan). Использование последнего метода требует предварительной настройки.

Командлеты, не требующие предварительной настройки, как правило, имеют параметр ComputerName, но не имеют параметра Session. Посмотреть список таких командлетов можно командой:

Get-Command | where

Для настройки WSMan в общем случае достаточно выполнить команду Enable-PSRemoting-Force. Она запустит службу удаленного управления WinRM и пропишет исключения в фаерволе ― в принципе, это можно сделать для всего домена при помощи групповых политик. Подробнее настройка описана в документации.

После того как все компьютеры будут готовы принимать запросы, мы сможем подключаться при помощи соответствующих командлетов PowerShell. Для проверки возможности подключения используется командлет Test-WSMan.

Проверка возможности подключения.

Для того чтобы выполнить определенную команду или скрипт, используется командлет Invoke-Command со следующим синтаксисом:

Invoke-Command -ComputerName COMPUTER -ScriptBlock < COMMAND >-credential USERNAME

Где COMPUTER ― имя компьютера, COMMAND ―– имя команды, а USERNAME ― имя пользователя, если оно нужно.

Смотрим содержимое диска С удаленного компьютера.

Если же нам нужно получить полноценную консоль ― не автоматизации ради, а ради управления конкретным компьютером, ― то можно использовать командлет Enter-PSSession.

Работаем в консоли удаленного компьютера.

Напомню, что с помощью JEA можно ограничить доступные подобной сессии командлеты или дать доступ нужным без прав администратора.

Конечно, кроме встроенных средств и небольших утилит, существует множество программ для управления структурой. Помимо взрослых решений, для управления конфигурациями вроде Chef, Ansible и MS SCCM можно использовать и средства мониторинга вроде Zabbix, и даже консоль управления антивирусом Касперского.

В период гетерогенных структур хорошо бы иметь возможность унифицированного управления Windows и Linux. Это можно сделать и с помощью PowerShell, что само по себе достойно отдельной статьи ― стоит такую сделать или уже лишнее?

Кстати, поделитесь вашими способами скрытого и не очень запуска программ на удаленных компьютерах. Ну, за исключением эксплойтов.

Как асинхронно запускать процедуры в powershell

You are using an outdated browser. Please upgrade your browser to improve your experience.

expand-card-line
calendar-line -->

Можно запустить рабочий процесс, чтобы создать действие для командлета PowerShell и заданного набора параметров. Это действие позволяет использовать функцию PowerShell в vRealize Orchestrator . При необходимости можно создать образец рабочего процесса, который выполняет созданное действие.

Можно использовать большой набор типов данных для модуля сценария PowerShell . Доступные типы данных включают примитивные типы, такие как Integer , Boolean , Char , любые типы, доступные в сборке .NET, или пользовательские типы. При создании действий на основе определений командлета PowerShell входные и выходные параметры командлета представляются типами, которые поддерживает платформа vRealize Orchestrator . Подключаемый модуль PowerShell определяет сопоставления типа. Как правило, типы примитивов сопоставляются с соответствующими типами vRealize Orchestrator , а сложные типы представляются объектом PowerShellRemotePSObject .

Необходимые условия

  • Убедитесь, что вы вошли в клиент vRealize Orchestrator как администратор.
  • Проверьте подключение к узлу PowerShell из представления Иерархия .

Процедура

  1. В vRealize Orchestrator Client выберите Библиотека > Рабочие процессы и введите теги powershell и generate в поле поиска рабочего процесса.
  2. Выберите рабочий процесс Создание действия для командлета PowerShell и щелкните Запустить .
  3. На вкладке Командлет выберите командлет PowerShell , который нужно запустить при использовании создаваемого действия.
  4. Выберите набор параметров для командлета.

Значения определения набора параметров отображаются в текстовом поле Определение набора параметров

Примечание: Нельзя изменить значения определения набора параметров путем изменения строки в текстовом поле Определение набора параметров . Можно проверить наличие в строках информации о параметрах, которые содержатся в наборе параметров.

Примечание: Имя созданного рабочего процесса состоит из предварительно определенной строки «Выполнить командлет» и имени созданного действия.

Дальнейшие действия

Можно интегрировать созданное действие в настраиваемые рабочие процессы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *