第2部 ターミナルとシェル
第6章 PowerShell徹底入門
Windows管理の主戦場で最も頼れる相棒が PowerShell です。前章までの bash が「文字列を流す」のに対し、PowerShell は「オブジェクト(構造化されたデータ)を流す」——この一点を腹に落とせば、Windows運用は驚くほど楽になります。この章では、その考え方と土台となるコマンドレットを、実際に打てる形でじっくり身につけます。
🎯 この章で学ぶこと
- PowerShell とは何か。cmd.exe との違い、5.1 と 7 の違い
- PowerShell 最大の特徴「オブジェクトを流すパイプライン」の考え方
- コマンドレットの「動詞-名詞」命名規則と、コマンドの探し方・ヘルプの引き方
- よく使うコマンドレットと、bash コマンド(第5章)との対応
Where-Object/Sort-Objectなどでデータを加工する方法- 実行ポリシーの意味と、安全にスクリプトを扱う心構え
6.1 PowerShell とは — Windows 標準の「管理シェル」
第4章で「シェルとは、人間の指示を受け取ってOSに伝える通訳」だと学びました。Windows にも昔から cmd.exe(コマンドプロンプト)というシェルがありますが、これは MS-DOS 時代の名残で、できることが限られています。そこで Microsoft が「サーバーや大量のPCを本気で管理するための現代的なシェル」として設計したのが PowerShell です。今日の Windows 管理では、こちらが事実上の標準です。
まずは起動してみましょう。スタートメニューで「PowerShell」と入力すれば見つかります。起動すると次のようなプロンプトが表示されます。
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
PS C:\Users\yuuki>
先頭の PS が「これは PowerShell ですよ」という目印、その後ろが現在いるフォルダ(カレントディレクトリ)です。本書ではプロンプトを短く PS C:\> と表記します。> の右側があなたの入力欄です。
cmd.exe とどこが違うのか
見た目は似た「黒い画面」ですが、中身は別物です。最大の違いは次項で扱う「流れるものがオブジェクトか文字列か」ですが、まず全体像を対比しておきましょう。
| cmd.exe(コマンドプロンプト) | PowerShell | |
|---|---|---|
| 登場時期 | MS-DOS 由来の古い設計 | 現代的な管理用に設計 |
| パイプで流れるもの | 文字列(テキスト) | オブジェクト(構造化データ) |
| コマンドの命名 | バラバラ(dir, copy, tasklist) | 統一(動詞-名詞) |
| できること | ファイル操作など基本的な範囲 | OS・サービス・レジストリ・Active Directory・クラウドまで |
| 拡張性 | 低い | .NET を土台に非常に高い |
PowerShell は dir や cd といった昔ながらのコマンド名も「別名(エイリアス)」として受け付けます。ですから dir と打てば一覧が出ますし、bash に慣れた人が ls と打っても動きます。裏では PowerShell 本来のコマンドレット(Get-ChildItem)が呼ばれています。これは移行をなめらかにするための親切設計です(6.5 で詳しく)。
Windows PowerShell 5.1 と PowerShell 7 の違い
実務でよく混乱するのが「2種類ある」という点です。整理しておきましょう。
| Windows PowerShell 5.1 | PowerShell 7(以降) | |
|---|---|---|
| 通称 | 「Windows PowerShell」 | 「PowerShell」「PowerShell Core」 |
| 土台 | .NET Framework(Windows専用) | .NET(クロスプラットフォーム) |
| 動く環境 | Windows のみ | Windows / Linux / macOS |
| Windows への同梱 | 標準で入っている | 別途インストールが必要 |
| 実行ファイル名 | powershell.exe | pwsh.exe |
| 今後 | メンテナンスのみ(新機能なし) | こちらが主流。積極開発中 |
自分がどちらを使っているかは、$PSVersionTable という変数を見れば分かります。$ で始まるのは変数の目印です(第7章で詳しく扱います)。
PS C:\> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.19041.4291
PSEdition Desktop
BuildVersion 10.0.19041.4291
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
PSVersion が 5.1... なので、これは「Windows PowerShell 5.1」です。PowerShell 7 で同じことをすると、PSEdition が Core、PSVersion が 7.x と表示されます。
結論はどちらでも構いません。基本のコマンドレットと考え方はほぼ共通だからです。手元の Windows にすぐある 5.1 で学び始め、慣れたら 7 を追加インストールする——これが無理のない進め方です。本書のコマンドは、特記なき限りどちらでも動きます。
6.2 最大の特徴 — 「オブジェクトを流すパイプライン」
ここが PowerShell を理解する最大の山であり、最大のごほうびです。第5章で bash のパイプ(|)は「前のコマンドの出力(文字列)を次のコマンドに渡す」仕組みだと学びました。PowerShell のパイプも記号は同じ | ですが、流れるものが文字列ではなく「オブジェクト」です。これが世界を変えます。
bash のやり方 — 文字列を切り刻む
たとえば「実行中のプロセスから、名前が chrome のものだけ取り出したい」とします。Linux/macOS(第5章)では、コマンドの出力はただの文字の並びなので、grep で文字列検索し、awk で列を数えて切り出す、といった作業になります。
# Linux/macOS (bash) の場合 — 文字列を検索して列番号で切り出す
$ ps aux | grep chrome | awk '{print $2, $11}'
1234 /opt/google/chrome/chrome
5678 /opt/google/chrome/chrome
この方法の弱点は、「列が何番目か」を人間が数えなければならず、出力の並びが少しでも変わると壊れることです。CPU使用率で並べ替えたければ、また別の列を数え直す必要があります。
PowerShell のやり方 — 名前でプロパティを扱う
PowerShell では Get-Process が返すのは文字列ではなく、1プロセス=1個の「プロセスオブジェクト」です。各オブジェクトは Name(名前)、Id(プロセスID)、CPU(CPU時間)、WS(メモリ使用量)といった名前つきの引き出し(プロパティ)を持っています。だから列番号を数える必要はなく、$_.Name のように名前で中身を取り出せます。
PS C:\> Get-Process | Where-Object { $_.Name -eq "chrome" }
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
412 52 210344 245678 92.34 1234 1 chrome
388 48 198210 231002 74.11 5678 1 chrome
$_ は「いま流れてきている1個のオブジェクト」を指す特別な書き方です(「アンダースコア変数」と読みます)。$_.Name は「そのオブジェクトの Name プロパティ」。-eq は「等しい」という比較演算子です(第7章で一覧にします)。つまり Where-Object { $_.Name -eq "chrome" } は「流れてくるプロセスのうち、Name が chrome のものだけ通す」という意味になります。
すばらしいのはここからです。「CPU使用時間の多い順に並べて、上位5件だけ」も、列を数え直すことなくプロパティ名を指定するだけで書けます。
PS C:\> Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
412 52 210344 245678 92.34 1234 1 chrome
388 48 198210 231002 74.11 5678 1 chrome
255 33 98120 115400 41.08 2468 1 Teams
198 15 45320 82340 22.55 1122 1 explorer
140 12 30210 51230 12.90 3344 1 Code
これが「オブジェクトを流す」ことの威力です。データが構造を保ったまま次のコマンドに渡るので、後段は「CPU という名前の引き出しで並べ替えて」と意味で指示できるのです。表示の見た目に依存しません。
画面に表を表示している時点でも、PowerShell の内部ではオブジェクトが流れています。最後に画面へ出すときだけ、PowerShell が自動で「見やすい表」に整形してくれているのです。つまり「表はゴールではなく、途中は常にオブジェクト」——この感覚が PowerShell 上達の鍵です。オブジェクトの中身を調べる方法は 6.7 で扱います。
| bash(第5章) | PowerShell | |
|---|---|---|
| パイプで流れるもの | 文字列(テキストの行) | オブジェクト(名前つきデータ) |
| 値の取り出し方 | 列番号を数える(awk '{print $2}') | プロパティ名で指定($_.Id) |
| 絞り込み | grep で文字列一致 | Where-Object で条件式 |
| 並べ替え | sort(文字列として) | Sort-Object(型を理解して数値順など) |
| 壊れやすさ | 出力の見た目が変わると壊れる | 見た目に依存せず頑丈 |
6.3 コマンドレットの命名規則 — 「動詞-名詞」
PowerShell のコマンドは コマンドレット(cmdlet) と呼ばれ、すべて 動詞-名詞(Verb-Noun)という統一形式で名づけられています。Get-Process なら「Get(取得する)+ Process(プロセス)」で「プロセスを取得する」。Stop-Service なら「Stop(止める)+ Service(サービス)」で「サービスを止める」。名前を見ればほぼ意味が分かる——これは cmd.exe のバラバラな名前(dir, copy, tasklist)に対する大きな進歩です。
| 動詞 | 意味 | 例 |
|---|---|---|
Get- | 取得する・見る | Get-Process, Get-Service, Get-Content |
Set- | 設定する・変更する | Set-Location, Set-Content |
New- | 新しく作る | New-Item, New-LocalUser |
Remove- | 削除する | Remove-Item, Remove-Service |
Start- | 開始する | Start-Service, Start-Process |
Stop- | 停止する | Stop-Service, Stop-Process |
Add- | 追加する | Add-Content |
Test- | 調べる・検査する | Test-Path, Test-Connection |
PowerShell が「正式に認めている動詞」の一覧は Get-Verb で確認できます。自分でコマンドを作るとき(第7章)も、この動詞に沿うのが作法です。
PS C:\> Get-Verb | Select-Object -First 8
Verb Group
---- -----
Add Common
Clear Common
Close Common
Copy Common
Enter Common
Exit Common
Find Common
Get Common
迷ったら名詞は単数形です。「プロセス一覧」を取りたくても Get-Processes ではなく Get-Process。「1つ取得する」という命名でも、実際には複数のオブジェクトがまとめて返ってきます。この一貫性のおかげで、知らないコマンドでも名前が推測しやすくなっています。
6.4 コマンドの探し方とヘルプの引き方
コマンドレットは数千個あります。すべて覚える必要はありません。大事なのは「探し方」と「ヘルプの読み方」を知っていることです。3つの道具を押さえましょう。
Get-Command — コマンドを探す
Get-Command(コマンドを取得する)は、名前の一部からコマンドレットを検索します。ワイルドカード *(任意の文字)が使えます。「サービス関連のコマンドを知りたい」なら次のようにします。
PS C:\> Get-Command *service*
CommandType Name Version Source
----------- ---- ------- ------
Cmdlet Get-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet New-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Restart-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Resume-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Set-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Start-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Stop-Service 3.1.0.0 Microsoft.PowerShell.Management
Cmdlet Suspend-Service 3.1.0.0 Microsoft.PowerShell.Management
「サービスに対してできること」がずらりと並びました。動詞-名詞の命名のおかげで、名詞(service)で検索するだけで「取得・作成・開始・停止・再起動…」が一望できるのです。
Get-Help — 使い方を読む
Get-Help は、そのコマンドレットの説明・パラメータ・使用例を表示します。実務でいちばん役立つのは -Examples(使用例)オプションです。
PS C:\> Get-Help Get-Process -Examples
NAME
Get-Process
SYNOPSIS
指定されたプロセスを取得します。
-------------------------- 例 1 --------------------------
PS C:\> Get-Process
実行中のすべてのプロセスを取得します。
-------------------------- 例 2 --------------------------
PS C:\> Get-Process -Name explorer
名前が explorer のプロセスを取得します。
-------------------------- 例 3 --------------------------
PS C:\> Get-Process | Where-Object { $_.WS -gt 100MB }
メモリを 100MB より多く使っているプロセスを取得します。
まず -Examples で「叩けば動く例」を見て、まねる。これが最速の学び方です。全文をじっくり読むなら Get-Help Get-Process -Full、ブラウザで公式ドキュメントを開くなら Get-Help Get-Process -Online です。
ヘルプの本文は初期状態では入っておらず、「ヘルプが見つかりません」と出ることがあります。管理者権限の PowerShell で一度 Update-Help を実行すると、最新のヘルプがダウンロードされ、以降 -Examples などが読めるようになります。うまく取得できないコマンドがあってもエラーは無視して構いません。
3つの道具の使い分け
| やりたいこと | コマンド |
|---|---|
| コマンドの名前を探す | Get-Command *キーワード* |
| 使い方・使用例を読む | Get-Help コマンド名 -Examples |
| そのオブジェクトが持つ中身を調べる | コマンド | Get-Member(6.7) |
この3つが揃えば、初めて見るコマンドでも自力で使いこなせます。「暗記」ではなく「調べ方」で戦うのが PowerShell の作法です。
6.5 よく使うコマンドレット — bash との対応つき
日々の管理で頻出のコマンドレットを、Linux/macOS の bash コマンド(第5章)と対応させながら見ていきます。前述のとおり、右の bash 名や cmd 名の多くは PowerShell でもエイリアス(別名)として使えます。
| コマンドレット | 意味 | bash / cmd での相当 | 使えるエイリアス |
|---|---|---|---|
Get-ChildItem | フォルダの中身を一覧 | ls / dir | ls, dir, gci |
Set-Location | カレントフォルダを移動 | cd | cd, sl |
Get-Location | 今いる場所を表示 | pwd | pwd, gl |
Get-Content | ファイルの中身を表示 | cat / type | cat, type, gc |
Copy-Item | ファイル・フォルダをコピー | cp / copy | cp, copy, cpi |
Move-Item | 移動・名前変更 | mv / move | mv, move, mi |
Remove-Item | 削除 | rm / del | rm, del, ri |
New-Item | ファイル・フォルダを新規作成 | touch / mkdir | ni, mkdir |
Get-Process | 実行中のプロセス一覧 | ps / tasklist | ps, gps |
Get-Service | サービスの状態一覧 | (相当なし) | gsv |
Select-String | ファイル内を文字列検索 | grep / findstr | sls |
ファイルとフォルダの操作
Get-ChildItem でフォルダの中身を一覧します。ls や dir と打っても同じです(裏で Get-ChildItem が動く)。
PS C:\> Set-Location C:\Logs
PS C:\Logs> Get-ChildItem
Directory: C:\Logs
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2026/07/01 9:12 20480 app-20260701.log
-a--- 2026/07/02 9:08 18944 app-20260702.log
-a--- 2026/07/03 9:15 21150 app-20260703.log
d---- 2026/06/30 18:00 archive
左端の Mode にある d はフォルダ(directory)、a はファイル(archive属性)を表します。ここでも一覧の各行は文字列ではなく「ファイルオブジェクト」で、LastWriteTime(更新日時)や Length(サイズ)を名前で扱えます。第7章の自動化では、この LastWriteTime を使って「古いログだけ選ぶ」処理を書きます。
# ファイルの中身を表示(cat / type と同じ)
PS C:\Logs> Get-Content .\app-20260703.log
2026-07-03 09:15:01 INFO service started
2026-07-03 09:15:04 WARN disk usage 82%
2026-07-03 09:16:22 ERROR failed to connect database
# 新しいフォルダを作る
PS C:\Logs> New-Item -ItemType Directory -Name "2026-07"
# ファイルをコピーする
PS C:\Logs> Copy-Item .\app-20260703.log -Destination .\2026-07\
Remove-Item(rm / del)で消したファイルは、原則ごみ箱を経由せず即座に消えます。特に -Recurse(フォルダごと中身も全部)は強力です。削除系のコマンドは、実行前に -WhatIf(実際には消さず「何が消えるか」だけ表示)で確認する習慣をつけてください。-WhatIf は第7章で詳しく扱う、身を守る最重要オプションです。
プロセスとサービス
Windows 管理の中心が「プロセス(実行中のプログラム)」と「サービス(裏で動き続ける常駐プログラム)」の操作です。Get-Service はサービスの状態を一覧します。
PS C:\> Get-Service | Select-Object -First 5
Status Name DisplayName
------ ---- -----------
Running BITS Background Intelligent Transfer Ser...
Stopped Bonjour Service Bonjour サービス
Running Dhcp DHCP Client
Running Dnscache DNS Client
Running Spooler Print Spooler
Status が Running なら稼働中、Stopped なら停止中です。特定のサービスだけ見るには -Name を指定します。次は印刷を司る Spooler を止めて、また起動する例です(操作には管理者権限が必要です)。
PS C:\> Get-Service -Name Spooler
Status Name DisplayName
------ ---- -----------
Running Spooler Print Spooler
PS C:\> Stop-Service -Name Spooler
PS C:\> Start-Service -Name Spooler
PS C:\> Restart-Service -Name Spooler
「印刷ができない」というよくある問い合わせは、この Restart-Service Spooler 一発で解決することがしばしばあります。第7章では「停止していたら自動で起動する」自動化に発展させます。
6.6 パイプラインでデータを加工する
6.2 で味見した「オブジェクトのパイプライン」を、ここで道具立てとして整理します。よく使う「加工コマンドレット」は次の5つです。これらは組み合わせて使います。
| コマンドレット | 役割 | bash の相当 |
|---|---|---|
Where-Object | 条件に合うものだけ絞り込む | grep |
Sort-Object | 指定プロパティで並べ替える | sort |
Select-Object | 必要なプロパティ・件数だけ選ぶ | cut / head |
Measure-Object | 件数・合計・平均などを集計する | wc |
Format-Table | 表示を表に整形する | (表示専用) |
Where-Object — 絞り込みと $_
Where-Object は、{ } の中の条件が真になるオブジェクトだけを通します。条件の中では、いま流れてきている1個を $_ で参照します。「メモリ(WS)を 200MB より多く使っているプロセス」を選んでみましょう。-gt は「より大きい(greater than)」です(記号 > は使わないことに注意。> はリダイレクトの意味になってしまうためです)。
PS C:\> Get-Process | Where-Object { $_.WS -gt 200MB }
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
412 52 210344 245678 92.34 1234 1 chrome
388 48 198210 231002 74.11 5678 1 chrome
200MB のように、PowerShell は KB / MB / GB といった単位をそのまま書けます(200MB は自動的に 209715200 バイトに解釈されます)。これも「数値をきちんと数値として扱う」オブジェクト指向の恩恵です。
多くの言語では「より大きい」を > と書きますが、シェルの世界では > は昔から「出力をファイルに書き出す(リダイレクト)」記号として予約されています(第5章)。そこで PowerShell は比較演算子を -gt(greater than)、-lt(less than)、-eq(equal)のようにハイフン+英字で表します。記号の取り合いを避けた、理にかなった設計です。演算子の一覧は第7章にまとめます。
Sort-Object と Select-Object — 並べ替えて選ぶ
絞り込んだものを並べ替え、必要な分だけ取り出します。-Descending は降順(大きい順)、-First 3 は先頭3件です。さらに Select-Object は「表示するプロパティ」も選べます。
PS C:\> Get-Process | Sort-Object CPU -Descending |
>> Select-Object -First 3 Name, Id, CPU
Name Id CPU
---- -- ---
chrome 1234 92.34
chrome 5678 74.11
Teams 2468 41.08
コマンドが長いときは、パイプ | の直後で改行できます。すると PowerShell は「まだ続きがある」と判断し、行頭に >> という継続プロンプトを出して次の入力を待ちます(この >> はあなたが打つ文字ではなく、PowerShell が表示する目印です)。Select-Object Name, Id, CPU のように書くと、その3つのプロパティだけが表になります。
Measure-Object — 集計する
件数や合計、平均を出すのが Measure-Object です。「今いくつプロセスが動いているか」を数えてみます。
PS C:\> Get-Process | Measure-Object
Count : 187
Average :
Sum :
Maximum :
Minimum :
Property :
Count が 187、つまり 187 個のプロセスが動いています。特定プロパティの合計や平均も出せます。次は「全プロセスのメモリ(WS)使用量の合計と平均」です。
PS C:\> Get-Process | Measure-Object WS -Sum -Average
Count : 187
Average : 38251632.4
Sum : 7153055260
Maximum :
Minimum :
Property : WS
合計約 7.1GB のメモリを、平均 1プロセスあたり約 36MB 使っている、と読めます。grep | wc -l で行数を数えていた bash と違い、「数値の合計・平均」まで一撃で出せるのがオブジェクトの強みです。
6.7 オブジェクトの中身を調べる — Get-Member
「このコマンドの結果は、どんなプロパティを持っているのか?」——これが分かれば、Where-Object や Select-Object で何を指定できるかが分かります。それを教えてくれるのが Get-Member(エイリアス gm)です。パイプでオブジェクトを渡すと、そのオブジェクトの「プロパティ(データ)」と「メソッド(操作)」を一覧してくれます。
PS C:\> Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Kill Method void Kill()
Start Method bool Start()
WaitForExit Method bool WaitForExit()
CPU Property System.Double CPU {get;}
Id Property int Id {get;}
Name Property string Name {get;}
StartTime Property System.DateTime StartTime {get;}
WorkingSet Property long WorkingSet {get;}
...
先頭の TypeName が「これは System.Diagnostics.Process 型のオブジェクトだ」と示しています。以下、MemberType が Property の行が「名前で取り出せるデータ」、Method の行が「そのオブジェクトにできる操作」です。たとえば Kill() メソッドがあると分かれば、プロセスを終了させられることが分かります。
プロパティ名が分かったら、Select-Object -Property で見たい列だけを表にできます。既定の表には出ない StartTime(起動時刻)も、名前を指定すれば取り出せます。
PS C:\> Get-Process chrome |
>> Select-Object -Property Name, Id, StartTime, WorkingSet
Name Id StartTime WorkingSet
---- -- --------- ----------
chrome 1234 2026/07/08 8:41:20 251574784
chrome 5678 2026/07/08 8:41:23 236548096
新しいコマンドレットに出会ったら、まず コマンド | Get-Member で「どんなプロパティがあるか」を覗くのが定石です。プロパティ名さえ分かれば、絞り込み(Where-Object)も並べ替え(Sort-Object)も選択(Select-Object)も自在に書けます。6.4 の Get-Command・Get-Help と合わせて、この3点セットが PowerShell 探索の基本装備です。
6.8 実行ポリシー — なぜスクリプトは既定でブロックされるのか
ここまでは1行ずつコマンドを打ってきました。次章では、複数のコマンドをまとめたスクリプトファイル(.ps1)を作ります。ところが、PowerShell を入れたばかりの Windows で .\script.ps1 を実行しようとすると、次のように拒否されることがあります。
PS C:\> .\backup.ps1
.\backup.ps1 : このシステムではスクリプトの実行が無効になっているため、
ファイル C:\backup.ps1 を読み込めません。
発生場所 行:1 文字:1
+ .\backup.ps1
+ ~~~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: ...
+ FullyQualifiedErrorId : UnauthorizedAccess
これは故障ではなく、安全のためにわざとブロックしているのです。この設定を実行ポリシー(Execution Policy)と呼びます。もしスクリプトが無制限に実行できると、メールに添付された悪意ある .ps1 をうっかりダブルクリックしただけで攻撃コードが走ってしまいます。それを防ぐ最初の関門が実行ポリシーです。
現在の設定は Get-ExecutionPolicy で確認できます。
PS C:\> Get-ExecutionPolicy
Restricted
Restricted(制限あり)は「スクリプトは一切実行しない」という最も厳しい状態です。主なポリシーを整理します。
| ポリシー | 意味 |
|---|---|
Restricted | スクリプトを一切実行しない(既定・最も安全) |
RemoteSigned | 自分で書いたローカルのスクリプトは実行可。ネットから来たものは署名が必要 |
AllSigned | すべてのスクリプトに信頼された署名を要求(厳格) |
Unrestricted | ほぼ何でも実行(非推奨) |
現場でよく使われる落としどころが RemoteSigned です。「自分で作ったスクリプトは動かせるが、インターネットからダウンロードした素性の知れないスクリプトは署名がなければブロックする」という、実用性と安全性のバランスが取れた設定です。変更には管理者権限の PowerShell が必要です。
PS C:\> Set-ExecutionPolicy RemoteSigned
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。
実行ポリシーを変更すると、セキュリティ上のリスクにさらされる可能性があります。
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [?] ヘルプ: Y
影響範囲を現在のユーザーだけに限定したい場合は -Scope CurrentUser を付けます。Set-ExecutionPolicy -Scope CurrentUser RemoteSigned なら、管理者権限がなくても自分の環境だけ変更できます。
ネット上の手順に「エラーが出たら Set-ExecutionPolicy Unrestricted や Bypass にすればOK」と書かれていることがありますが、これは全スクリプトを無条件に許可する状態で、マルウェアの実行を許す穴になり得ます。原則は RemoteSigned まで。実行ポリシーは「万能の鍵」ではなく「うっかり実行を防ぐ関門」であり、これ自体はセキュリティ機能の一部にすぎない点も覚えておきましょう。
PowerShell は Windows を隅々まで操れる強力なシェルです。強力さは、悪用されれば脅威にもなります。実際、攻撃では正規ツールである PowerShell が悪用されることも珍しくありません。だからこそ運用者は次の3点を習慣にしてください。(1) 実行ポリシーは RemoteSigned を基本とし、安易に Unrestricted へ下げない。(2) ネットで拾ったスクリプトを中身を読まずに実行しない——特に Invoke-Expression(iex)で「ダウンロードして即実行」する一行コマンドは、攻撃の常套手段でもあります。必ず一度ファイルに落とし、目を通してから動かす。(3) 管理者権限は必要なときだけ。サービスの停止やシステム設定の変更には管理者権限が要りますが、常時「管理者として実行」で作業すると、ミスや悪意あるスクリプトの被害が一気に広がります。普段は一般権限で作業し、必要な操作のときだけ昇格する——これは第3章で学んだ「最小権限の原則」そのものです。仕組み(なぜブロックするのか)を理解して運用することが、いちばんの防御になります。
まとめ
- PowerShell は Windows 標準の現代的な管理シェル。cmd.exe より圧倒的に多くのことができる
- Windows PowerShell 5.1(Windows専用・同梱)と PowerShell 7(クロスプラットフォーム・要インストール)がある。基本は共通
- 最大の特徴はオブジェクトを流すパイプライン。bash が文字列を切り刻むのに対し、PowerShell はプロパティ名でデータを扱える
- コマンドは
動詞-名詞で統一。Get-Commandで探し、Get-Help -Examplesで使い方、Get-Memberで中身を調べる Where-Object(絞り込み)・Sort-Object(並べ替え)・Select-Object(選択)・Measure-Object(集計)が加工の基本。比較は-gt-lt-eq- 実行ポリシーは安全のための関門。基本は
RemoteSigned。管理者権限とネット由来スクリプトの扱いに注意
練習問題
「実行中のプロセスを CPU 使用時間の多い順に並べ、上位5件だけを、プロセス名・ID・CPU の3項目で表示したい」。この処理を1行の PowerShell で書いてください。使うコマンドレットは Get-Process・Sort-Object・Select-Object です。
解答を見る
PS C:\> Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name, Id, CPU
Get-Process でプロセスオブジェクトを取得し、パイプで Sort-Object CPU -Descending に渡して CPU の多い順(降順)に並べ、さらに Select-Object -First 5 で先頭5件を取り、Name, Id, CPU でその3プロパティだけを表示しています。列番号を数える必要がなく、プロパティ名を指定するだけで済む点が、文字列を扱う bash との決定的な違いです。
Linux に慣れた同僚が、Windows の PowerShell で ls、cd Logs、cat app.log、pwd と打っています。それぞれ「本来の PowerShell コマンドレット(動詞-名詞)」では何にあたるか答えてください。また、なぜ bash 風の名前でも動くのかを一言で説明してください。
解答を見る
| 打った文字 | 本来のコマンドレット |
|---|---|
ls | Get-ChildItem |
cd Logs | Set-Location Logs |
cat app.log | Get-Content app.log |
pwd | Get-Location |
動く理由は、PowerShell がこれらの名前を「エイリアス(別名)」として本来のコマンドレットに割り当てているからです。移行をなめらかにする親切設計で、どんなエイリアスがあるかは Get-Alias で確認できます。
あるスクリプト .\report.ps1 を実行しようとしたら「このシステムではスクリプトの実行が無効になっている」と拒否されました。(1) この制限の名前は何か。(2) 現在の設定を確認するコマンドは何か。(3) 「自分で書いたスクリプトは動かせるが、ネットから来たものは署名を要求する」という実用的な設定にするには、どのポリシーに変更すればよいか答えてください。
解答を見る
(1) 実行ポリシー(Execution Policy)です。悪意あるスクリプトのうっかり実行を防ぐための関門です。
(2) Get-ExecutionPolicy で確認します。初期状態では Restricted(実行を一切許可しない)と表示されるはずです。
(3) Set-ExecutionPolicy RemoteSigned です(変更には管理者権限、またはユーザー限定なら -Scope CurrentUser を付けます)。Unrestricted や Bypass は全スクリプトを無条件に許可してしまうため、安易に選ばないのが鉄則です。