しばたテックブログ

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

PowerShellでmkdirしたディレクトリにcdする方法

クラスメソッドさんの

dev.classmethod.jp

が人気なので便乗してPowerShellだとどうすれば良いか軽く書いておきます。

本エントリの内容はWindows 10、PowerShell 5.1、PSReadline 1.2な環境で動作確認しています。

1. $$自動変数を使う

Bashでは$_が「ひとつ前に実行したコマンドラインの最後の引数」となっていますが、PowerShellで$_は「パイプラインで現在処理されているオブジェクト」を表す自動変数なので使えません。

PowerShellでは代わりに$$を使います。
$$は正確には「セッションが受け取った最後の行にある最後のトークン」なのですが、コマンド実行直後であれば「ひとつ前に実行したコマンドラインの最後の引数」と同じに使えます。

実行例はこんな感じです。

mkdir .\very\very\long-directory
cd $$

2. パイプラインでつなぐ

PowerShellではmkdir関数に成功すると作成されたディレクトリオブジェクト(System.IO.DirectoryInfo)を返します。
このため、この値をパイプラインでつなぎcd(Set-Location)に引き渡すことが可能です。

mkdir .\very\very\long-directory | cd

ただ、この方法でロケーションを移動した場合、プロンプトに表示されるロケーションが、

PS Microsoft.PowerShell.Core\FileSystem::C:\very\very\long-directory > 

の様に先頭にPSProvider(Microsoft.PowerShell.Core\FileSystem::の部分)が修飾されてしまう場合があり、見た目としては非常によろしくありません...

一応、

mkdir .\very\very\long-directory | % { $_.FullName } | cd

# or

mkdir .\very\very\long-directory | cvpa | cd

のように一旦%(ForEach-Object)や、cvpa(Convert-Path)をはさむことで回避はできるのですが、冗長で本末転倒です...

3. cd → Alt + . (PSReadline Windowsキーバインド)

PSReadlineを個別にインストールするか、標準でPSReadlineがインストール済みのWindows 10/Windows Server 2016環境でこの方法を使うことができます。

PSReadlineのデフォルトのキーバインドではAlt + .YankLastArgという機能で割り当てられており、「ひとつ前に実行したコマンドラインの最後の引数」を取得することができます。
このため、cdAlt + .の順に入力することで直近に入力したパスを補完することが可能です。

なお、キーバインドの割り当ては以下のコマンドで確認することができます。

Get-PSReadlineKeyHandler | ? { $_.Function -eq "YankLastArg" }

結果

Key   Function    Description
---   --------    -----------
Alt+. YankLastArg Copy the text of the last argument to the input

4. cd → ESC → . (PSReadline Emacsキーバインド)

PSReadlineではSet-PSReadlineOptionによりキーバインドを変更することができます。

Set-PSReadlineOption -EditMode Emacs

とすることでキーバインドをEmacs風にすることができ、この場合、cdESC.の順に入力すれば「ひとつ前に実行したコマンドラインの最後の引数」を取得することができます。

ちなみに、

Get-PSReadlineKeyHandler | ? { $_.Function -eq "YankLastArg" }

の結果は以下の様に変更されています。

Key      Function    Description
---      --------    -----------
Alt+.    YankLastArg Copy the text of the last argument to the input
Alt+=    YankLastArg Copy the text of the last argument to the input
Escape,. YankLastArg Copy the text of the last argument to the input
Escape,= YankLastArg Copy the text of the last argument to the input

5. ESC → k 0 cw cd (PSReadline viキーバインド)

PSReadlineはVer.1.2からvi風のキーバインドをサポートしています。

Set-PSReadlineOption -EditMode Vi

とするこでキーバインドをvi風にすることができます。
あとは元記事同様に、ESCk 0 cw cdで前回のコマンド呼び出し文字列置換を行う事ができます。

6. mkdir と cd を同時に実行する関数をあらかじめ定義しておく

独自の関数を作るのであれば好きなように作ってしまうのが良いと思います。

mkdir自体がNew-Itemコマンドレットをラップした関数なので、本格的な関数を作りたい人はmkdirの定義を確認してみると良いでしょう。
役に立つ情報を得ることができるはずです。

本エントリでは元記事に近い形の簡易な関数を紹介するにとどめておきます。

function mkdir-cd {
    mkdir $args[0] | cvpa | cd
}

※なお、PowerShellでは&&は予約語となっていますが、サポートされておらず使えません。

最後に

とりあえずこんな感じです。

BashやZshほどではないですがPowerShellでもいろいろな方法を選べますので是非試してみてください。

Desired State Configuration Core (DSC Core)が発表されました

発表されてからちょっと時間が経ってしまいましたがざっくりまとめておきます。

公式情報はコチラ

blogs.msdn.microsoft.com

以前PowerShell 6.0、PowerShell Coreのロードマップが発表された時はWindows PowerShell Desired State Configuration(以後PowerShell DSC)について言及されませんでしたが、今回はじめてPowerShell DSCの今後について言及されました。

本エントリではこの内容について説明していきます。

これまでのPowerShell DSC

PowerShell DSCとは何ぞや?といった話についてはぎたぱそ先生の記事が全てですのでそちらでご確認ください。

www.atmarkit.co.jp

adventar.org

これまでのPowerShell DSCについては、Windowsで動作するもの、Linuxで動作するものの2種類があり、それぞれ、

1. Windows PowerShell Desired State Configuration

  • WMIを基盤としている
  • Windows Management Framework (WMF)の一部として提供されており、管理にはPowerShell 4.0~5.1を必要とする
  • DSC ResourceはCまたはPowerShellで記述する

2. Desired State Configuration for Linux(DSC for Linux)

  • OMIを基盤としている
  • PowerShellがクロスプラットフォーム化する前に生まれているため、管理にPowerShellは使わずPython 2.4~3.4を必要とする
  • DSC ResourceはCまたはPythonで記述する

といった特徴があります。  

ちなみにDSC for Linuxについてはこのブログでも試していますので以下の記事を参考にしてください。

blog.shibata.tech

Desired State Configuration Core (DSC Core)

PowerShellがPowerShell Coreとなり.NET Coreを基盤としたクロスプラットフォームなツールになることにあわせて、PowerShell DSCも.NET Core/PowerShell Coreを基盤としたDesired State Configuration Core (以後DSC Core)として発展させていくとの事です。

DSC Coreについて以下の方向性が挙げられています。

  • WMIへの依存をなくす
  • WMFへの依存をなくす
  • xcopyで配布可能なパッケージとする
  • WMIを使わないC/C++、Python、PowerShellで書かれたDSC Resourceをサポートする
  • PowerShell Core/.NET Coreを必要とする

ざっくり言ってしまえばクロスプラットフォーム化のためにPowerShell Core/.NET Coreを基盤とし、WMIやWMFへの依存(要はWindows依存)を取り除く方向になります。

DSC Coreの目指すことろ

こちらについてはPowerShell Blogの内容をそのまま引用します。

Our goals with DSC Core are to minimize dependencies on other technologies, provided a single DSC for all platforms, and position it better for cloud scale configuration while maintaining compatibility with Windows PowerShell Desired State Configuration.

DSC Coreの下位互換性

目指すところは分かりますが、これまでのPowerShell DSCとの互換性をどう取るのかは非常に重要であり、もっとも難しい問題だと思います。

この点についてPowerShell Blogでは以下の様に述べられています。

  1. DSC Resourceに関しては.NET Standard 2.0の互換性で既存のリソースはそのまま動く様にする

  2. コマンドレットに関しては従来のPowerShell DSCとの互換を取らず、新しいコマンドセットを提供する

  3. Azure DSC ExtensionはDSC Core用に新規のものを提供する

  4. Pullサーバーとの通信に関して、DSC Coreでもこれまで通りのプロトコルを使い既存のPullサーバーと通信できる様にする

  5. Configurationに関しては、これまで通り変更が無い様にし、PowerShell 6.0でコンパイルしなおすだけで使える様にする

PowerShell Blogでも注記されていますが、これらの点についてはあくまでも現時点での計画です。

私見ですが、正直これらをすべて完璧に満たすのは難しいと思っていますので、今後の状況によっていろいろ変化があると思われます。

DSC Coreのリリース時期

DSC Coreのリリース時期に関して、先ずはAzure向けに年末までに最初のリリースを出すそうです。
(流石に早すぎるのでここでの"リリース"はアルファ版とかだと思います...)

PowerShell DSCがクロスプラットフォーム化するメリットを一番享受できるのがAzureでしょうし、環境自体が日々更新され新しくなっていくAzureにフォーカスするのは妥当な判断だと思います。
(逆にWindowsを中心としたオンプレ環境だと今のPowerShell DSCを新しくするメリットがほとんどないように思われます...)

まとめ

ざっくりとですがDSC Coreについてまとめてみました。

正直なところ、DSC Coreの仕組みやPowerShell Blogで述べられている事がどこまで実現可能かについて結構疑問点があります。

ですが、今それについてあれこれ言っても仕方ないとも思っているので今後の情報で疑問を解決していきたいと思います。

Windows 10でPowerShell Remoting over SSHを試す

【2017/10/25追記】

先日リリースされた、Fall Creators Update(1709)でPowerShell Remoting over SSHができなくされていました。
これまで利用可能だったのが間違った更新なのか、単純に一時的な使用不可なのかはよくわかりません...

【追記ここまで】


公式のアナウンスなどは全く無く、いつの間にかWindows 10 Creators Update(1703)でPowerShell Remoting over SSHが使える様になっていたので試してみました。

PowerShell Remoting over SSHについて

PowerShell Remoting over SSHとは何ぞやといった話はこちらのエントリをご覧ください。

blog.shibata.tech

どのPowerShellで使えるのか?

当初PowerShell Remoting over SSHはPowerShell 6.0向けの機能として発表され、現在も絶賛開発中です。
このためPowerShell Core 6.0であればこの機能はふつうに使えます。

で、他のバージョンに関してはいまのところWindows 10 Creators Update(1703)以降のWindows PowerShell 5.1にのみ実装された様です。
確認が取れなかったのでCreators Updateが出た直後のビルドから利用可能だったのかまでは不明ですが、少なくとも2017年8月現在のビルド(PSVersion = 5.1.15063.502)では利用可能になっています。

また、Windows PowerShell 5.1でもWindows Server 2016*1WMF 5.1として他のOSにインストールしたものに関しては利用できません。

PowerShell Remoting over SSHを試す

以前に試した時と同様にCentOSをサーバーとしてWindows 10から接続してみます。
CentOSのバージョンは7.3に上げています。

項目 Windows 10(1703) CentOS 7.3
基本設定 最新のWindows Updateを実施した状態 bento/centos7.3のBoxにyum updateを実施
IP - VirtualBoxのゲスト(localhostで接続する)
ユーザー - vagrant, root

1. CentOSの設定

CentOSの設定手順は前と同様ですが、PowerShellをyumからインストールする様に変更しています。
また/etc/ssh/sshd_configの設定をsedで行う様にしました。*2

# CentOS(Bash)
# PowerShell Core for Linuxのインストール
curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo
sudo yum install -y powershell

# /etc/ssh/sshd_config の設定
# '# override default of no subsystems'のコメント行の下に設定を追加
# ※位置指定をかなり決め打ちにしているので注意
sudo sed -i.orig -e "/# override default of no subsystems/a Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile" /etc/ssh/sshd_config

# sshdの再起動
sudo systemctl restart sshd.service

2. Windowsの設定

PowerShell Remoting over SSHはPowerShellとOpenSSHを組み合わせた機能であるため、OpenSSHをインストールしてssh.exeのあるディレクトリに対してPATHを通しておく必要があります。

以下の手順でC:\Program Filesにインストールします。

# 要管理者権限
# OpenSSHのインストール
Invoke-WebRequest -Uri "https://github.com/PowerShell/Win32-OpenSSH/releases/download/v0.0.18.0/OpenSSH-Win64.zip" -OutFile "OpenSSH-Win64.zip"
Expand-Archive -Path ".\OpenSSH-Win64.zip" -DestinationPath "$env:ProgramFiles"

# Pathの追加
[Environment]::SetEnvironmentVariable('PATH', [Environment]::GetEnvironmentVariable('PATH') + ";$(Join-Path $env:ProgramFiles "OpenSSH-Win64")")

3. 接続確認

前と同様にNew-PSSessionおよびEnter-PSSessionを使用して接続確認をします。

PowerShell Remoting over SSHでは-HostName(-ComputerNameではない)や-UserNameパラメーターで接続先を指定します。*3

# セッション生成
# 検証環境の都合-HostNameがlocalhostになっているが実際には接続先のホスト名を指定する
$Session = New-PSSession -HostName "localhost" -UserName vagrant
# 接続
Enter-PSSession -Session $Session

下図の様にSSHのセッションが生成され問題なくCentOSのサーバーに接続できました。

f:id:stknohg:20170814171926p:plain

f:id:stknohg:20170814171940p:plain

ちなみに、OpenSSHをインストールせずに接続しようとすると以下の様なエラーになってしまいますので注意してください。

f:id:stknohg:20170814171908p:plain

制限事項

PowerShellのバージョンを問わず現時点のPowerShell Remoting over SSHの制限事項として接続先のポート指定ができません。

New-PSSessionには-Portパラメーターがあるのですが、これは通常のPSRemoting専用のパラメーターであり、PowerShell Remoting over SSHで使おうとすると不正なパラメーター扱いされエラーとなってしまいます。

この点に関しては以下のPull Requestが出ており目下対応中といったところなのでいずれ解消されると思います。

github.com

*1:先日提供されたInsider Preview版でも使えませんでした

*2:位置指定がかなり決め打ちなのであまり良いやり方ではないと思いますが楽だったのでつい...

*3:他に-KeyFilePathパラメーターもあります