PowerShellスクリプトでタスクを自動化する方法を学びましたね。素晴らしいです!しかし、今ではスクリプトとモジュールが乱雑になり、手動のスクリプト実行、スケジュールされたタスクなどが混在しています。この混沌を整理し、PowerShellの自動化オーケストレーションエンジンであるPSakeを導入する時が来ました。
PSakeはPowerShellモジュールとして書かれたオーケストレーションエンジンであり、スクリプトの順序を整理し、実行条件を完全に制御することができます。PSakeはビルド自動化ツールであり、主な使用ケースはビルドスクリプトです(通常はビルドサーバーでリリース自動化シナリオで実行されます)。しかし、日常のスクリプトシナリオでは一般的に見過ごされています。それを変えましょう。
このチュートリアルでは、PSakeの動作と、今日実践できる素晴らしい例を学んでいきます!
前提条件
この記事は、一緒に進めることを想定したチュートリアルです。正確に進めるためには、次のものを用意してください:
- Windows PowerShell 3+。チュートリアルではWindows PowerShell v5.1を使用します。
- GithubからのPSakeのzipファイル。このチュートリアルではv4.9.0を使用します。
PSakeモジュールのセットアップ
GithubからダウンロードしたPSakeプロジェクトをローカルマシンに持っていると仮定して、まずいくつかの手順を実行する必要があります。
- GithubからダウンロードしたPSakeのzipファイルを展開してください。
- srcフォルダーを展開されたZIPファイルの内容の中にある
$env:PSModulePath
の下のパスに移動し、PowerShellが新しいモジュールを認識するようにします。srcフォルダーの名前をPSakeに変更してください。- 次に、
Get-Module PSake -ListAvailable
を実行して表示されるか確認してください。エラーが表示されない場合、準備ができています。
関連記事: PowerShellモジュールの理解と構築
基本的なPowerShell PSakeスクリプトの作成
PSakeを理解するために、何かを構築する必要があります。PSakeが何ができるかを確認するために、単純なPSakeスクリプトを作成しましょう。
- 名前がpsakefile.ps1のスクリプトを作成し、単一のタスクを追加してください。タスクは、少なくとも名前とアクションブロックを持つ必要があります。名前psakefile.ps1は必須ではありませんが、エンジンによって期待されるデフォルトの名前です。
A PSake task in its basic form is very similar to a PowerShell function:
a container for one or more commands that, when performed together, achieve a certain goal. These commands go into a script block that is passed to theAction
parameter. A task has many advantages over a function. You will learn about these advantages as you read along.
以下は、比較的シンプルなタスクを持つpsakefile.ps1の例です。
2. PSakeファイルを作成したので、PowerShellコンソールから Invoke-PSake
コマンドを使用して呼び出し、タスク名をTaskList
パラメーターの値として渡すことができます。
Invoke-PSake
はPSakeの実行エンジンです。このコマンドはpsakefile.ps1で定義されたタスクをトリガーします。タスク名またはコンマ区切りのタスクのリストをTaskList
パラメータに渡します。複数のタスクを実行する場合、TaskList
に渡した順序で各タスクが実行されます。
以下はHelloWorldタスクをトリガーする方法です:
psakefile.ps1という名前のファイルを保持し、コンソールをそのフォルダに設定している限り、
BuildFile
パラメータとその値を省略することができます。
Invoke-PSake
を実行すると、PSakeの出力がコンソールに表示されます。psakefile.ps1のタスクを実行すると、以下のような出力が表示されます。

出力は以下のコンポーネントで構成されています:
- PSakeのバージョンの詳細。
- 各ビルドタスクの名前(PSakeではすべてのタスクをbuild タスクと見なします)。例:シアンでHelloWorldを実行します。
- タスクが生成した出力。例:黄色でHello Worldを表示します。
- 成功/失敗のメッセージ。例:緑でpsake succeeded…を表示します。
- 各タスクの所要時間とスクリプト全体の合計所要時間を含む時間の要約(Build Time Report)。
PSakeを使用してSQLをインストールする
前のセクションでは、ダミーのPSakeスクリプトを呼び出すだけでした。この知識を基に、SQLをインストールするPSakeスクリプトを作成してください!
この例では、次のようなPSakeスクリプトを作成します。
- マシン上の空きディスク容量を検証します。
- ローカルリポジトリからSQL ZIPファイルをダウンロードします。
- ZIPファイルを展開します。
- CドライブまたはDドライブ(どちらか存在する方)でインストールを実行します。
次に、この仕事にPSakeをどのように活用できるかを見てみましょう。
ビルディングブロックの設計
PSakeは、タスクの組み立てに関するものです。各タスクには一意の名前が必要であり、理想的にはPowerShell関数のような単一のアトミック操作を実行するべきです。このコンセプトを使用して、以下のステップを各タスクのために記述できます。
- ValidateDiskSpace
- DownloadSql
- ExtractSql
- InstallSqlDriveC
- InstallSqlDriveD
この段階では、実際に何かを行うためのコードを構築しているわけではありません。タスクの骨組みを作成し、PSakeファイルを作成しているだけです。後でタスクに追加するために、以下のタスク内のWrite-Host
の参照に気付くでしょう。
各タスクには常に
Description
パラメータを使用する必要があります。Description
パラメータは、タスクの実行時およびコードのレビュー時に各タスクについての詳細情報を提供します。
タスクの実行順序の定義
タスクのセットを含むPSakeファイルができました。この段階では、すべてのタスクを一度に実行するか、Invoke-PSake
コマンドで一部のタスクのみを実行することができます。
あなたは、Invoke-PSake
とTaskList
パラメーターを使用して、いくつかのタスク(またはすべてのタスク)を呼び出すことができます。前の簡単な例と同様に、タスクの名前を項目として定義した配列を作成します。
Invoke-PSake
は、配列で定義された順序で各タスクを実行します。
上記のコードを実行すると、次のような結果が得られるはずです。

PreConditionの追加
特定の条件が満たされた場合にのみ、特定のアクションを実行する必要があるかもしれません。このチュートリアルの例であるSQLインストールスクリプトでは、たとえば、インストーラを格納するボリュームが利用可能かどうかをテストしてから、インストーラを起動するタスクを実行する必要があるかもしれません。
PreCondition
パラメーターを使用して、タスクが実行されるかどうかを決定する、真または偽の値を返すコードを実行できます。
以下の例では、$installSqlOn_C_Drive
と$installSqlOn_D_Drive
変数に注意してください。 Invoke-PSake
がこのスクリプトを呼び出すとき、これらの変数はCボリュームまたはDボリュームが存在するかどうかに応じて真または偽の値を含みます。
各task
行では、各タスクにPreCondition
スクリプトブロックパラメーターがあり、これらの変数の値が含まれています。実行時には、これらの変数に応じてInstallSqlDriveC
またはInstallSqlDriveD
タスクが実行されます。
タスクパラメーター
Action
およびDescription
に加えて、タスクは以下のパラメータをサポートしています:
PreCondition
– ブール値を返すスクリプトブロック。Falseの場合、特定のタスクはスキップされます(使用例は上記に示されています)。PostCondition
– バリデーションステップ。ブール値を返すスクリプトブロックです。Falseはバリデーションが失敗し、スクリプト全体が停止することを意味します。PreAction
– タスクの実行前に実行されるスクリプトブロックです。PostAction
– タスクが成功した直後に実行されるスクリプトブロックです。ContinueOnError
– スイッチパラメータ。使用すると、タスクの実行中に発生する可能性のあるエラーがスクリプト全体の停止を引き起こさないようになります。Depends
– 実行される前に現在のタスクの実行が必要なタスクの名前(またはタスク名のリスト)です。PSakeはこの情報を使用して、タスクの依存関係を正しい順序で実行します。たとえば、タスクAがタスクBに依存している場合、PSakeエンジンはAの前にBを実行します。
最初は依存性のメカニズムは良いアイデアのように思えます。タスクを論理的な順序で設定するのに役立ちます。ただし、
Depends
パラメータを使用すると、異なるタスクが結び付けられ、後で独立してテストするのが難しくなります。ただし、ユーザーはタスクの実行順序を明示的に設定し、PSakeファイルを呼び出す際にこの順序を渡すことができるため、Depends
パラメータの使用は完全に回避できます。
次に、これらのタスクパラメータの使用例を見てみましょう。
PreActionとPostConditionの追加
上記の例のInstallSqlDriveDタスクを出発点として、インストールに追加の要求があるかもしれません。
たとえば、インストールの開始時と終了時の時間を記録する必要があるかもしれません。これらの時間をSqlSetupStartDateとSqlSetupEndDateという環境変数に記録する必要があります。さらに、インストールが完了した後に、D:\TempSqlFilesフォルダが存在しないことを確認する必要があります。
幸いなことに、PSakeのタスクパラメータPreAction
、PostAction
およびPostCondition
(それぞれ)は、まさにこれらの新しい要件を満たします。以下に、それがどのように行われるかの例を示します:
PesterテストでPSakeスクリプトを実行する
PowerShellスクリプトを呼び出す場所なら、PSakeファイルを呼び出すこともできます。Pesterでインフラストラクチャテストを構築している場合、テスト内でPSakeを呼び出すことができます。
関連記事:PowerShellのためのPesterテストの作成
たとえば、DownloadSql
タスクを実行した後にフォルダにSQLセットアップZIPファイルが存在することを確認するPesterテストがあるかもしれません。その場合、簡単なPesterテストを作成し、テスト内でDownloadSql
タスクを呼び出し、実行後すぐにZIPファイルが存在するかどうかを確認します。
タスクへのパラメータの渡し方
PSakeを使用し始めると、いくつかのタスクにパラメータを渡すことができるようになるかもしれません。通常、PowerShellの関数やスクリプトでは、関数/スクリプトに対してさまざまな名前付きパラメータを渡しますが、PSakeは異なります。
PSakeファイルにパラメータを渡すためには、各タスク内で使用できるキー/値のペアを定義するProperties
ブロックを使用します。
PSakeファイルの先頭に
Properties
ブロックを定義することを忘れないでください。すべてのPSake操作は上から下に読み込まれます。
たとえば、PSakeファイルの各タスクに動的なSqlYear
およびSqlVersion
変数を渡すには、以下のように定義します。
そして、Invoke-PSake
を使用してPSakeファイルを呼び出すと、以下の出力が表示されます。$SqlYear
と$SqlVersion
変数がProperties
ブロックで定義された値で展開されていることに注意してください。
Properties
パラメータの使用
タスクにパラメータを従来のパラメータ経由で渡したい場合、PSakeを使用すると便利です。先に示した例のように、psakefile.ps1の先頭には引き続きPropertiesブロックを保持する必要がありますが、PSakeを使用すると値を上書きすることができます。
それを行うには、キー/値のペアごとにハッシュテーブルを定義します。次に、ハッシュテーブルをProperties
パラメータに渡します。PSakeエンジンは、psakefile.ps1スクリプト内のProperties
ブロックで指定された値よりも、渡されたハッシュテーブル内の値を使用します。
Properties
ブロックとProperties
パラメータの構文の違いに注意してください。Properties
ブロックでは、各行が変数であり、したがってドル記号で始まります。一方、Properties
パラメータはハッシュテーブルであり、各アイテムがキーであり、先頭に$が付いていません。もう一つの違いは、ハッシュテーブルの前に@文字が付いていることです。
以下に、Properties
パラメータを使用する例を示します。
PSakeタスクのモジュール化: タスクをファイルとして扱う
PSakeファイルは、特に大規模な自動化タスクを組織化する必要がある場合、爆発的に成長する可能性があります。それらのタスクを管理できるようにするために、モジュール化やタスクの分割に焦点を当てるべきです。
関連記事: 地獄からのPowerShellスクリプトのリファクタリングの生き残り方
このチュートリアルの例では、以下の5つのタスクを使用しました:
- ValidateDiskSpace
- DownloadSql
- ExtractSql
- InstallSqlDriveC
- InstallSqlDriveD
それぞれのタスクは、単一のpssakefile.ps1スクリプトの内部で定義されています。もし時間の経過とともにさらに多くのタスクを追加することが予想される場合は、それらのタスクを個別のファイルに分割し、各タスクをValidateDiskSpace.ps1、DownloadSql.ps1、InstallSqlDriveD.ps1、InstallSqlDriveD.ps1などのようなファイルに配置するべきです。
例えば、InstallSqlDriveD.ps1には次のコードのみが含まれます:
タスクが移動されたら、Include
関数を使用してファイルをpsakefile.ps1にインポートします。これが完了すると、psakefile.ps1の内容は次のコードに簡略化されます:
Invoke-PSake
がpsakefile.ps1スクリプトをトリガーする際、Invoke-PSake
は、タスクがpsakeファイル内にあるのか、Include
メソッドによってインポートされたのかを知らないし気にしません。
次のステップ
PSakeは、ソフトウェアビルド、CI/CD、パッケージの展開、インストーラーの作成など、多くの目的に使用できる強力なスクリプトオーケストレータです。唯一の制限はあなたの想像力です。PSakeを使って大規模なスクリプトを構築することに慣れることで、タスク(コードのビルディングブロック)について考えるようになります。タスクのコンセプトはPowerShellの構文を活用しており、タスクを使用することで既存のコマンドラインの知識を豊かにすることができます。
PSakeで生成するコードは、より読みやすく、保守しやすく、テストしやすくなります。練習を重ねることで、手順を異なるタスクに分割することがスクリプト化を容易にします。追加のわずかな作業によるメリットは、中長期的に大いに報われるでしょう。
あなたの仕事のプロジェクトにおいて、PSakeはどのように適していると思われますか?