AWS CloudShellのPowerShell環境にデフォルトインストールされた AWSPowerShell.NetCore を削除する方法

2022.03.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

【2023/03/04追記】

AWS CloudShellにプリインストールされるモジュールがAWS.Tools.*なモジュールに変更されたため、本記事の手順は不要になりました。

【追記ここまで】


しばたです。

先週AWS Tools for PowerShellの入門記事を書いている際に気が付いたのですが、いつの間にかAWS CloudShellのPowerShell環境にAWS Tools for PowerShellのAWSPowerShell.NetCoreモジュールがデフォルトで組み込まれていました。

いつからAWSPowerShell.NetCoreモジュールが組み込まれたのか?

AWSのドキュメントなど調べまくったのですが、更新履歴が一切無く、いつからAWSPowerShell.NetCoreモジュールが組み込まれたのかのかは全く分かりませんでした...
はっきりしているのはAWS CloudShellがリリースされた当初は間違いなくAWSPowerShell.NetCoreモジュールは組み込まれていなかったことだけです。

私は当時のブログ(上記)で書いた様にCloudShellにデフォルトでAWSPowerShell.NetCoreモジュールが導入されなかった理由を

  • AWS Tools for PowerShell v4からはサービス別の AWS.Tools.* なモジュールが推奨になった
  • AWSPowerShell.NetCoreモジュールをPowerShell 6以降で使う場合に既知の問題がある

からだとと推測していたので、正直デフォルトで組み込まれて嬉しい気持ちより「既知の問題が解決してないのにどうして組み込んでしまったんだ...」というネガティブな気持ちの方が強いです。

とはいえ問題自体には回避策があるのと「PowerShellを常用しない方からすれば都度都度モジュールをインストールするのは手間でしかないだろうな」とも思うので、デフォルトで組み込んだのも止む無しと見ています。

AWSPowerShell.NetCoreモジュールの問題

ここまでを踏まえてAWSPowerShell.NetCoreモジュールの既知の問題について触れておきます。

CloudShellのPowerShell環境では全ユーザー共通の領域(/opt/microsoft/powershell/7/Modules/)にAWSPowerShell.NetCoreモジュールがインストールされています。
本日時点ではPowerShell 7.2.1 環境に AWSPowerShell.NetCore 4.1.17.0がインストールされていました。

# 本日時点のCloudShellのPowerShellは 7.2.1
PS /home/cloudshell-user> $PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      2      1             

# AWSPowerShell.NetCore モジュールのインストール情報を取得
PS /home/cloudshell-user> Get-Module -ListAvailable -Name AWS* | Select-Object Name, Version, Path

Name                  Version  Path
----                  -------  ----
AWSPowerShell.NetCore 4.1.17.0 /opt/microsoft/powershell/7/Modules/AWSPowerShell.NetCore/4.1.17.0/AWSPowerShell.NetCore.psd1

通常この領域にインストールされたモジュールは自動ロードされPowerShellを起動すると同時に各種コマンドレットを利用できるのですが、AWSPowerShell.NetCoreでは一つのモジュールで公開されるコマンドレット数が多すぎるため自動ロードに失敗する既知の問題があります。
このためAWSPowerShell.NetCoreを利用するには以下の様に明示的にImport-Moduleを実行してモジュールをロードしてやる必要があります。

Import-Module AWSPowerShell.NetCore

問題の回避策としてはこれだけなのですが、根本の「コマンドレット数が多すぎる」部分について、例えば前述のVer.4.1.17.0においては

  • モジュールで対応しているAWSサービス数は 290
  • モジュールで公開しているコマンドレットおよび関数 *1の総数は 11031

とあまりにも多く、インスタンススペックが低いCloudShellではモジュールのロードに8秒 - 10秒程度と非常に長い時間がかかってしまいます。
PowerShellをたまにしか使わない方であればギリギリ許容できるかもしれませんが、常用するのであればこのロード時間は全く許容できないでしょう。

AWS CloudShellに AWS.Tools.* なモジュールを追加インストールする

前節の通り「AWSPowerShell.NetCoreモジュールは自動ロードされない」のが問題であるため、「AWSPowerShell.NetCoreモジュールを無視してAWS.Tools.* なモジュールを追加インストールすれば良いのでは?」と思う方もいるでしょう。

実際それは正しく、追加でAWS.Tools.*なモジュールをインストールして構いません。

# まずは AWS.Tools.Installer モジュールをインストール
Install-Module AWS.Tools.Installer -Force
# 追加で EC2とSTSのモジュールをインストール
Install-AWSToolsModule EC2, SecurityToken -Force

ただ、この場合最初のコマンドレット実行時に長ったらしい警告がでるのでご注意ください。

WARNING: Multiple variants of AWS Tools for PowerShell (AWSPowerShell, AWSPowerShell.NetCore or AWS.Tools) are currently installed. Please run 'Get-Module -Name AWSPowerShell,AWSPowerShell.NetCore,AWS.Tools.Common -ListAvailable' for details. To avoid problems with cmdlet auto-importing, it is suggested to only install one variant.
AWS.Tools is the new modularized version of AWS Tools for PowerShell, compatible with PowerShell Core 6+ and Windows Powershell 5.1+ (when .NET Framework 4.7.2+ is installed).
AWSPowerShell.NetCore is the monolithic variant that supports all AWS services in a single large module, it is compatible with PowerShell Core 6+ and Windows Powershell 3+ (when .NET Framework 4.7.2+ is installed).
AWSPowerShell is the legacy module for older systems which are either running Windows PowerShell 2 or cannot be updated to .NET Framework 4.7.2 (or newer).

加えて、この状態でAWSPowerShell.NetCoreモジュールをロードすると以下の様な挙動となり期待した動作をしない場合があります。

  • AWS.Tools.*なモジュールの関数を一度でも実行している場合
    • → AWSPowerShell.NetCoreモジュールのロードに失敗する(実害なし)
  • AWS.Tools.*なモジュールの関数を一度も実行していない場合
    • → AWSPowerShell.NetCoreモジュールが先勝ちでロードされてしまう

AWS CloudShellのAWSPowerShell.NetCoreモジュールを削除する

この様にAWS.Tools.*なモジュールを追加インストールした場合は取り扱いに気を遣わないといけません。
というわけで、できることならAWSPowerShell.NetCoreモジュールを削除してしまいたいわけです。

ただ、AWSPowerShell.NetCoreモジュールは/opt/microsoft/powershell/7/Modules/にインストールされてしまっているので一度削除してもコンテナインスタンスが変われば復活してしまいます。

このためプロファイル(/home/cloudshell-user/.config/powershell/Microsoft.PowerShell_profile.ps1)に以下の様な感じで仕込みを入れてPowerShell起動の都度削除する様にしてやる必要があります。

# 誤削除防止のため一応環境変数をチェック
if ($env:AWS_EXECUTION_ENV -eq 'CloudShell') {
    # モジュールのインストール状況を見てディレクトリを削除
    $moduleBase = (Get-Module AWSPowerShell.NetCore -ListAvailable).ModuleBase
    if ($null -ne $moduleBase) {
        Write-Warning "Remove AWSPowerShell.NetCore module ..."
        $modulePath = Split-Path -Parent $moduleBase
        if (Test-Path $modulePath) { sudo rm -rf $modulePath }
    }
}

これで無事AWSPowerShell.NetCoreモジュールが削除されAWS.Tools.*なモジュールのみ利用可能になります。

最後に

以上となります。

私の様な人間からすると今回のAWSPowerShell.NetCoreモジュールの組み込みは「厄介なことをしてくれたな...」というのが率直な気持ちです。
これはモジュールロードの問題はPowerShellに慣れ親しんでないと適切な対処ができないためです。
本記事の内容がAWS CloudShellでAWS Tools for PowerShellを使う方の役に立つ事を願っています。

脚注

  1. Get-Command -Module AWSPowerShell.NetCore -CommandType Cmdlet, Function で計測