しばたテックブログ

気分で書いている技術ブログです。

Azure Cloud ShellのPowerShellは起動時に何をしているのか

Azure Cloud ShellでPowerShellを起動した場合、通常のPowerShellの起動とは異なる初期処理が行われAzureドライブ(Azure:\で始まるドライブ)にロケーションが移動された状態で開始されます。

  • Cloud Shell(PowerShell)起動時

f:id:stknohg:20180524170552p:plain

  • Cloud Shell(Bash)からPowerShell Coreを起動した場合

f:id:stknohg:20180524170600p:plain

(PowerShellのコンテナでPowerShell Coreを起動しても同様)

本エントリではこの処理がどの様にして行われているのか解説します。

Cloud Shell(PowerShell)の場合

Cloud Shell(PowerShell)の場合、シェルの起動時に初期処理が行われています。
PowerShellの初期化処理といえばプロファイルに記述するのが一般的ですが、Cloud Shell(PowerShell)ではWindows PowerShellのプロファイルには何も記述されていません。

Cloud Shell(PowerShell)ではpowershell.exeの引数に初期化処理が記述されています。
powershell.exeの起動時引数は以下の様にすれば確認でき、

Get-CimInstance Win32_Process -Filter "processid = $PID" | Select-Object -ExpandProperty CommandLine

その結果

PS Azure:\> Get-CimInstance Win32_Process -Filter "processid = $PID" | Select-Object -ExpandProperty CommandLine
powershell.exe  -NoProfile -NoExit -NoLogo -command "Set-PSReadlineOption -TokenKind String -ForegroundColor Cyan; . ~\PSCloudShellStartup.ps1"

$env:USERPROFILE\PSCloudShellStartup.ps1を実行する様になっています。

また、PowerShell Coreのプロファイル(C:\Program Files\PowerShell\<version>\profile.ps1)は

#
# This profile script is used by PowerShell Core.
# Windows Powershell is started with -NoProfile to optimize its start time.
#

if (Test-Path $env:USERPROFILE\PSCloudShellStartup.ps1)
{
    . $env:USERPROFILE\PSCloudShellStartup.ps1
}

if (Get-Module -Name PSReadLine)
{
    # Set PSReadLine colors to be compatible with Cloud Shell UX requirements
    Set-PSReadlineOption -TokenKind String -ForegroundColor Cyan
}

と記述されており、こちらもPSCloudShellStartup.ps1を呼び出す様になっています。

Cloud Shell(Bash)の場合

Cloud Shell(Bash)の場合は、PowerShell Coreのプロファイル(/opt/microsoft/powershell/<version>/profile.ps1)に直接初期化処理が記述されており、その内容はPSCloudShellStartup.ps1と同一です。

初期化処理の詳細

現時点のPSCloudShellStartup.ps1(とprofile.ps1)の内容をGistに上げていますのでスクリプトの詳細はそちらで確認してください。

初期化処理は主に

  • Azure関連のモジュールの読み込みと認証
  • プロファイルパスの差し替え
  • prompt関数の差し替え
  • Azureドライブへの移動

を行っています。

この中でも特徴的なのがプロファイルパスの差し替えで、4つあるプロファイルの内

  • CurrentUserAllHosts
  • CurrentUserCurrentHost

のパスをそれぞれ

プロファイル Windows Ubuntu
CurrentUserAllHosts $env:USERPROFILE\CloudDrive\profile.ps1 $env:HOME/.config/PowerShell/profile.ps1
CurrentUserCurrentHost $env:USERPROFILE\CloudDrive\Microsoft.PowerShell_profile.ps1 $env:HOME/.config/PowerShell/Microsoft.PowerShell_profile.ps1

に差し替えて*1実行します。

加えて$PROFILE変数に付与されるNotePropertyからAllUsersAllHostsAllUsersCurrentHostを削除しています。
(正確には$PROFILE変数を上書き定義する際にNotePropertyの追加をしない様にしている)

Format-Listを使ってNotePropertyを確認すると以下の様になります。

PS Azure:\> $PROFILE | Format-List -Force

CurrentUserAllHosts    : C:\Users\ContainerAdministrator\CloudDrive\profile.ps1
CurrentUserCurrentHost : C:\Users\ContainerAdministrator\CloudDrive\Microsoft.PowerShell_profile.ps1
Length                 : 75

*1:細かい話をするとLinuxではパスが差し替わっていませんが、これはLinuxでは$env:HOME配下がCloud Drive上のVHDでマウントされ永続化対象となっているためです。Windowsではその様なマウントがないので永続化されるパスにプロファイルを差し替えています