Управління процесами, послугами та серверами автоматизації за допомогою PowerShell – це фундаментальна здатність для будь-якого фахівця в сфері ІТ та кібербезпеки. PowerShell, розроблений Microsoft, є потужним інструментом для скриптингу та автоматизації, що дозволяє контролювати та управляти процесами та послугами на комп’ютерах та серверах. У цій статті ми розглядаємо, як використовувати PowerShell для моніторингу, запуску, зупинки та налаштування процесів та послуг, а також для управління серверами і їх конфігурацією. Ви навчитеся застосовувати різноманітні команди та скрипти для ефективного управління ІТ-інфраструктурою.
Ця стаття також надасть вам інформацію про створення скриптів для автоматизованого управління задачами, як-от регулярне оновлення серверів, моніторинг стану системи та виправлення помилок. В інтернеті існує величезна кількість корисних сервісів, з якими можна працювати, отримуючи доступ до їх ресурсів по протоколу NTTR. Веб-розробники постійно працюють із цими запитами HTTR для доступу до зовнішніх функцій API або для тестування власних додатків. Традиційно це робиться за допомогою спеціальних додатків (наприклад, Postman), консольних утиліт, таких як cURL і wget, а також NTTR-клієнтів, інтегрованих в середовища розробки. PowerShell пропонує два стандартних командлети для доступу до веб-ресурсів по протоколу NTTR: Invoke-WebRequest і Invoke-RestMethod.
Ви можете використовувати командлет Invoke-WebRequest, щоб відправити запит на веб-сервер і отримати від нього відповідь.
Командлет Invoke-WebRequest добре підходить для парсингу Tayuke: цей командлет може зберігати сторінки на локальний диск, цим він схожий на консольну утиліту wget і навіть має такий псевдонім:
PS C:\Script> Get-Alias wget CommandType Name Alias wget -> Invoke-WebRequest
Використовуйте цей командлет для переходу на просту сторінку, наприклад Приклад домену (https://example.com/index.html) (див. Малюнок 1). 14.1
За замовчуванням Invoke-WebRequest виконує HTTP-запит з методом GET до ресурсу на веб-сервері, з адресою ресурсу, вказаною як значення параметра -Uri. В результаті повертається об’єкт типу Htm1WebResponseObject, в якому зберігається інформація про відповідь сервера:
PS C:\Script> $web = Invoke-WebRequest -Uri https://exanple.com/index.ht3nl PS C:\Script> $web | Get-Member TypeName: Microsoft.PowerShell.Commands.HtmlWebResponseObject PS C:\Script> $web StatusCode : 200 StatusDescription : OK Content : <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8” /> <meta http-equiv="Content-type" content="text/html; char set=utf-8” /> <meta name="viewport" conten... RawContent : HTTP/1.1 200 OK Age: 497890 Vary: Accept-Encoding X-Cache: HIT Forms Content-Length: 1256 Cache-Control: max-age=604800 Content-Type: text/html; charset=UTF-8 Date: Mon, 12 Jul 2021 16:05:14 GMT Exp... : {} Headers : {[Age, 497890], [Vary, Accept-Encoding], [X-Cache, HIT], [Content-Length, 1256]... } Images InputFields Links : {} : {} : {@{innerHTML=More information...; innerText=More information ...; outerHTML=<A href="https://www.iana.org/domains/example ">More information...</A>; outerText=More information...; tagName=A; href=https://www.iana.org/domains/example}} ParsedHtml RawContentLength : mshtml.HTMLDocumentClass : 1256
У полі statuscode міститься код відповіді від сервера (200 для нашого прикладу), у полі statusDescription — текстовий опис відповіді (ОК).
Вміст відповіді від сервера зберігається як рядок у полі content. В нашому у випадку тут буде записаний HTML-код:
PS C:\Script> $web.Content <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name-'viewport” content="width=device-width, initial-scale=l" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; } div { width: 600px; margin: 5em auto; padding: 2em; background-color: #fdfdff; border-radius: 0.5em; box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02); } a:link, a:visited { color: #38488f; text-decoration: none; @media (max-width: 700рх) { div { margin: 0 auto; width: auto; } } </style> </head> <body> <div> <hl>Example Domain</hl> <p>This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.</p> <p><a href=”https://www.iana.org/domains/example">More information...</a></p> </div> </body> </html>
У полі Rawcontent записується повна відповідь від сервера з НТТР-заголовками на початку:
PS C:\Script> $web.RawContent НТТР/1.1 200 OK Age: 497890 Vary: Accept-Encoding X-Cache: HIT Content-Length: 1256 Cache-Control: max-age=604800 Content-Type: text/html; charset=UTF-8 Date: Mon, 12 Jul 2021 16:05:14 GMT Expires: Mon, 19 Jul 2021 16:05:14 GMT ETag: "3147526947+ident" Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT Server: ECS (dcb/7F83) <!doctype html> <html> <head> <title>Example Domain</title>
Також заголовки відповіді виділяються окремо та зберігаються у вигляді хеш-таблиці у якості headers:
PS C:\Script> $web.headers Key Value Age 497890 Vary Accept-Encoding X-Cache HIT Content-Length 1256 Cache-Control max-, Content-Type Date Expires ETag Last-Modified Server max-age=604800 text/html; charset=UTF-8 Mon, 12 Jul 2021 16:05:14 GMT Mon, 19 Jul 2021 16:05:14 GMT "3147526947+ident" Thu, 17 Oct 2019 07:18:26 GMT ECS (dcb/7F83)
Щоб зберегти відповідь від сервера у вигляді локального файлу, потрібно при викликі Invoke-WebRequest ВИКОРИСТОВУВАТИ КЛЮЧ -OutFile і вказати шлях до потрібного файлу.
PS C:\Script> Invoke-WebRequest -Uri https://exanple.com/index.html -OutFile page.html
Перевіримо вміст файлу page.html і переконаємося, що в ньому записано HTML розмітку збереженої сторінки:
PS C:\Script> type .\page.html <!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content=”text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=l" /> <style type="text/css"> body { background-color: #f0f0f2; margin: 0; padding: 0; font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; div { width: 600px; margin: 5em auto; padding: 2em; background-color: ttfdfdff; border-radius: 0.5em; box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02); a:link, a:visited { color: #38488f; text-decoration: none; } @media (max-width: 700px) { div { margin: 0 auto; width: auto; } } </style> </head> <body> <div> <hl>Example Domain</hl> <p>This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.</p> <p><a href="https://www.iana.оrg/domains/example”>More information... </ax/p> </div> </body> </html>
Подібним чином можна зберігати не лише HTML-файли, а й ресурси інших типів (текстові, графічні чи мультимедійні файли тощо), до яких можна звернутись на сайт.
У властивостях Forms (форми), Images (зображення), InputFields (ПОЛЯ ВВЕДЕННЯ) І Links (посилання) об’єкта HtmiwebResponseObject зберігаються масиви об’єктів, які описують відповідні елементи HTML-розмітки, отриманої від сервера. Обробляючи ці колекції, можна отримати інформацію про елементи, що цікавлять нас, на завантаженій сторінці.
Виділимо на цій сторінці усі посилання на сайт habr.com. Для цього потрібно відфільтрувати масив $web. Links, залишивши в ньому об’єкти, які мають значення властивості href відповідає масці *habr.com*:
PS C:\Script> $habr_links = $web.Links | Where-Object href -like '*habr.com*'
В $habr_iinks містить два об’єкти PSCustomObject, що містять різні HTML-атрибути для посилань:
PS C:\Script> $habr_links.count 2 PS C:\Script> $habr_links | Get-Member
Наприклад, виведемо значе:
PS C:\Script> $habr_links | ForEach-Object {$_.href + " - " + $_.innerText } https://habr.com/ru/company/ruvds/blog/487876/ - Что такое Windows PowerShell и с чем его едят? / Хабр https://habr.com/ru/company/ruvds/blog/487876/ - habr.com >ru/company/ruvds/blog/487876/
У властивості ParsedHtml об’єкта HtmlWebResponseObject міститься об’єкт типу mshtmi.HTMLDocumentciass, який надає доступ до DOM-дерева завантаженої HTML сторінки.
PS С:\Users\andrv> $html = $web. ParsedHtml PS C:\Users\andrv> Get-Member -Inputobject $html TypeName: mshtmi.HTMLDocumentciass
Командлет Invoke-WebRequest дозволяє не тільки виконувати GET-запити, але й викликати інші методи, визначені у протоколі HTTP (delete, head, merge, patch, post, put, trace). І тому потрібний метод вказується як значення параметра -Method. Розглянемо приклад виконання запиту з HTTP-методом post, який часто використовується для передачі даних із веб-форм або завантаження файлів на сервер. Звертатись ми будемо до ресурсу http://httpbin.org/post, в результаті сервер має повідомити нам про отримані дані. Передаватимемо два параметри з іменами name і lastName, які помістимо у хэш-таблицу $params:
PS С:\Users\andrv> $params = @{name='Andrey'; lastName='Popov'}
Виконаємо Invoke-WebRequest з методом post, помістивши параметри, що передаються у тіло запиту (параметр -Body):
PS С:\Users\andrv> Invoke-WebRequest -Uri http://httpbin.org/post -Method POST -Body $params StatusCode StatusDescription Content : 200 : OK : { "args": {}, "data": "", "files": {}, "form": { "lastName": "Popov", "name": "Andrey" }, "headers": { "Content-Length": "26", "Content-Type": "application/x-www-form.. RawContent : HTTP/1.1 200 OK Connection: keep-alive Access-Control-Allow-Origin: ★ Access-Control-Allow-Credentials: true Content-Length: 503 Content-Type: application/json Date: Fri, 16 Jul 2021 03:03:13 GM... Forms Headers : {} : {[Connection, keep-alive], [Access-Control-Al low-Origin, *], [Access-Control-Allow-Credent ials, true], [Content-Length, 503]...} Images InputFields Links ParsedHtml RawContentLength : {} : {} : {} : mshtml.HTMLDocumentClass : 503
Параметри командлет invoke-webRequest, що надсилаються на сервер, автоматично призводить до формату application/x-www-form-urlencoded, який використовується при передачі даних з веб-форм. Відповідь у полі content говорить про те, що сервер прийняв наші параметри і визначив, що вони були відправлені з форми. Іноді потрібно передавати на сервер дані у форматі JSON, а не в application/x-www-form-urlencoded. У цьому випадку потрібно вказати параметр -contentType зі значенням application/json. Наприклад:
PS С:\Users\andrv> $json_params = "{ 'nameAndrey', ' lastNamePopov' }" PS C:\Users\andrv> Invoke-WebRequest -Uri http://httpbin.org/post -ContentType "application/json" -Method POST -Body $json_params StatusCode : 200 StatusDescription : OK Content : { "args": {}, "data": "{ ’name':'Andrey’, 'lastNamePopov ’ Г, "files": {}, "form": {}, "headers": { "Content-Length": "39", "Content-Type": "application/json", "Host": "... RawContent : HTTP/1.1 200 OK Connection: keep-alive Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Content-Length: 475 Content-Type: application/json Date: Fri, 16 Jul 2021 03:43:04 GM... Forms Headers : {} : {[Connection, keep-alive], [Access-Control-Allo w-Origin, *], [Access-Control-Allow-Credentials , true], [Content-Length, 475]...} Images InputFields Links ParsedHtml RawContentLength : И : {} : (} : mshtml.HTMLDocumentClass : 475
Як бачимо, при такому способі відправки запиту серверний скрипт, що обробляє звернення до ресурсу http://httpbin.org/post, витягнув отримані дані і при формуванні свого JSON-відповіді помістив їх у поле data, а не в полі form. Командлет Invoke-RestMethod якщо ми звертаємося до веб-сервісу, який підтримує REST API, то відповідь сервера швидше за все міститиме структуровані дані у форматі JSON або XML. Так, у попередньому прикладі за допомогою командлета Invoke-WebRequest посилали POST-запит на ресурс http://httpbin.org/post і отримували у відповідь JSON рядок:
post -Method POST -Body @ {name=' Andrey ’ ; lastName= ’ Popov' } PS C:\Users\andrv> $web.Content { "args”: {}, ’’data”: "files": {}, "form": { "lastName": "Popov", "name": "Andrey" }, "headers": { "Content-Length": "26", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "Mozilla/5.0 (Windows NT; Windows NT 10.0; ru-RU) WindowsPowerShell/5.1.19041.1023", "X-Amzn-Trace-Id": "Root=l-60f2a42c-18f152db3b76b5d66dl73e31" }, "json": null, "origin": "85.95.179.209", "url": "http://httpbin.org/post"
Щоб працювати з полями відповіді, ми повинні перетворити JSON на об’єкт PowerShell за допомогою командлета convertFrom-Json (ми розглядали подібні перетворення у розділі 12):
PS С:\Users\andrv> $response = $web.Content | ConvertFrom-Json PS C:\Users\andrv> $response args : data : files : form : @{lastName=Popov;name=Andrey} headers : @{Content-Tength=26; Content-Type=application/x-www-form-urlencoded; Host-httpbin.org; User-Agent=Mozilla/5.0 (Windows NT; Windows NT 10.0; ru-RU) Windows PowerShell/5.1.19041.1023; X-Amzn-Trace-Id=Root=l-60f2a42c-18f152db3b76b5d66dl73e31} j son : origin : 85.95.179.209 url : http://httpbin.org/post PS C:\Users\andrv> $response.form.name Andrey
У подібних випадках, коли від сервера ми отримуємо структуровані дані, зручніше користуватися командлетом invoke-RestMethod, який діє аналогічно Invoke-WebRequest і має такі ж параметри, але при цьому автоматично перетворює відповідь від сервера в об’єкт PowerShell. Виконаємо наш запит за допомогою invoke-RestMethod, зберігши результат у змінній $result:
PS С:\Users\andrv> $result = Invoke-RestMethod -Uri http://httpbin.org/ post -Method POST -Body @ (name='Andrey' ; lastName=' Popov'}
Проверим тип и содержимое переменной $ result:
PS С:\Users\andrv> Get-Member -Inputobject $result TypeName: System.Management.Automation.PSCustomObject uri NoteProperty string url=http://httpbin.org/post PS C:\Users\andrv> $result Name MemberType Definition Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() args NoteProperty System.Management.Automation.PSCusto data NoteProperty string data= files NoteProperty System.Management.Automation.PSCusto form NoteProperty System.Management.Automation.PSCusto headers NoteProperty System.Management.Automation.PSCusto j son NoteProperty object json=null origin NoteProperty string origin=85.95.179.209 args : data : files : form : @(lastName=Popov;name=Andrey} headers : @{Content-Length=26; Content-Type=application/x-www-form-urlencoded; Host=httpbin.org; User-Agent=Mozilla/5.0 (Windows NT; Windows NT 10.0; ru-RU) Windows PowerShell/5.1.19041.1023; X-Amzn-Trace-Id=Root=l-60f2a897-6354ce272644b6d412560a9b} j son : origin : 85.95.179.209 uri : http://httpbin.org/post
Як бачимо, замість рядка у форматі JSON ми отримуємо PowerShell-об’єкт типу System.Management.Automation. PSCustomObject І можемо відразу звертатися До потрібних
властивостям:
PS С:\Users\andrv> $result.form.lastName Popov
Отже, для виконання HTTP-запитів до веб-ресурсів, що повертають HTML-сторінки, зручніше використовувати командлет Invoke-webRequest, а для роботи із зовнішніми REST API, що повертають структуровані дані, краще підійде командлет Invoke-RestMethod.
Для звернення до веб-ресурсів за протоколом HTTP у PowerShell є два стандартні командлети: Invoke-webRequest та Invoke-RestMethod.
Ці командлети діють аналогічно один одному, за винятком того, що Invoke-RestMethod автоматично перетворює відповідь від сервера на об’єкт PowerShell.