PowerShell を便利に使うための設定

PowerShell を

  • エクスプローラーから右クリックで開く
  • elevate コマンドを導入する
  • Emacs 風キーバインドを使う
  • posh-git と Start-SshAgent を使う
  • which コマンドを作る

ように設定すると便利だという話.ついでに,ビープ音を消す話, .ssh のシンボリックリンクを貼る話,win-ssh-agent.sh を使う話,標準エイリアスを消す話, refreshenv の話, Windows 7 の PowerShell v2 を v5 にアップデートするときの罠の話もする.


よく知られた情報が大半だと思いますが,まとめておきます.

Windows で種々の開発がしたいとき, Cygwin がいやなら, PowerShell + Chocolatey + MSYS2 がおすすめです.私の場合,何かコマンドがほしくなったらまず Chocolatey の choco で公式 Windows 版みたいなのを探して,なければ MSYS2 の pacman で入れます.

今回は PowerShell に関連して私がやっているカスタマイズを書きます.

エクスプローラーから右クリックで開く

今いる場所をカレントフォルダにしてパッと開けるので極めて便利です.

追記 (2018-09-14)

そういえば,何もしなくても Shift + 右クリック で同等のメニューアイテムが得られます(デフォルト機能)。それでも私は Shift を押すのが面倒なので,本節の手順を実行しています。

右クリックメニューにOpen Powershell Hereを追加 – Qiita

親切な人が作ってくださっています.ありがとうございます.上の記事のとおりの .reg ファイルを作成してインストールするだけです.

後述の elevate コマンドと組み合わせると管理者権限の PowerShell も +1 ステップで開けます.

.ps1 ファイルを実行可能にする

以降のカスタマイズのための前提として必要です.

PowerShell スクリプト (.ps1) ファイルは,疎い人がホイホイ実行してしまわないようにデフォルトでは実行不可になっています.疎くない人は解禁しましょう(※ Chocolatey のインストールにも必要).

管理者権限で PowerShell を開いて,

Set-ExecutionPolicy RemoteSigned CurrentUser

して警告に Y すると完了です.実行ポリシーについては,わかりやすい表が Powershellを楽に実行してもらうには – Qiita にあります.

プロファイルを作成する

以降のカスタマイズのための前提として必要です.

個人設定ファイル,たとえば Bash でいう .bash_profile のようなものを作ることができます.

PowerShell 上で

notepad $profile

するとプロファイルが開けます(初めての場合は存在しないファイルとして開ける).ここで $profile がそのパスを表しています(確認するには,単に $profile とだけ書いて実行してみてください).

ここに種々のスクリプトを書いていくとだんだん幸せになれます.

コマンドで su 的な権限昇格

「あ,このコマンド管理者権限要るやん」というときに幸せになれます.

昇格したPowerShellコンソールおよびPowerShell ISEを起動させるファンクションを書きました – しばたテックブログ

偉い人が非常に便利なスクリプトを公開してくださっています.ありがとうございます.上の記事のとおりの Start-ElevatedPowerShell.ps1 を適当な場所に保存してプロファイルから読み込むとよいです.たとえば D:\PSScripts\Start-ElevatedPowerShell.ps1 に保存したなら,プロファイルに

# elevate command
. "D:\PSScripts\Start-ElevatedPowerShell.ps1"

などと追記すれば(ドット演算子による実行), PowerShell を立ち上げたときにこれが読み込まれます.こうすれば,任意のタイミングで elevate を実行するだけで管理者権限の PowerShell が同じカレントフォルダで立ち上がります.

ところで,上の記事のスクリプトは,デフォルトでは elevate 実行時に元のウィンドウを閉じます.私は元のも残しておいてほしいので,デフォルト設定を変えています:24 行目を

[switch]$ExitCurrentProcess = $false,

にします ( $true を $false に変える).

elevate -ExitCurrentProcessとすれば元を閉じます. elevate -Wait とすれば元のウィンドウが終了待ちをします.非常によくできていてありがたい.PowerShell の機能でオプション名の短縮や省略もできます.このあたりは Windows PowerShell: パラメーターを定義する が詳しいです.

Emacs 風キーバインドを使う

PSReadLine というすばらしいモジュールがあって,これは PowerShell を全体的に強化してくれます.

Windows 10 以降の PowerShell には標準で含まれていて勝手にインポートされます.それ以前におけるインストール手順は dahlbyk/posh-git: A PowerShell environment for Git を参照してください(インストール後,インポートも自分でプロファイルに書く必要があります).

プロファイルに以下を追記することで,キーバインドが Emacs 風になります.

Set-PSReadlineOption -EditMode Emacs

ほかにも様々なカスタマイズ能力が提供されています. dahlbyk/posh-git: A PowerShell environment for Git を参照してください.

補足:ビープ音を消す

PSReadLine が有効であるとき,文字を Backspace で消しすぎると,ピピピというビープ音が律儀に鳴ります.これがいちいち律儀な反応をしてくれるので,私はオフにしています.プロファイルの PSReadline 設定行を

Set-PSReadlineOption -EditMode Emacs -BellStyle None

とするとよいです.

posh-git を使う

PowerShell から Git を使うときに活躍します.

dahlbyk/posh-git: A PowerShell environment for Git

インストール,インポートの方法は上の README を参照してください. Windows 10 以降なら PowerShellGet\Install-Module posh-git -Scope CurrentUser したあとプロファイルに Import-Module posh-git を追記するだけでよいはずです.

MSYS2 ssh-agent を posh-git と併用する

Windows から公開鍵認証を使って SSH 接続するとき,日本語版の PuTTY シリーズは RSA 4096 bit や ECDSA, Ed25519 などの署名方式に対応しておらず,さすがに乗り換えが必要です. (追記:ごった煮版 PuTTY を本家最新版に追随させた iceiv+putty というパッチがあるようです.中の方,がんばってください.)

私は普段の SSH 接続には RLogin を使用しているのですが, Git コマンド内部で SSH する際にはそうはいかないので, Unix 系で標準的な ssh-agent を使います.

PowerShell ウィンドウを閉じるたびにやり直さなくて済むように ssh-agent を固定します.はじめは ほげめも: win-ssh-agent.sh  を利用させてもらっていたのですが, posh-git を有効化するとうまくいかなくなったので乗り換えました.

実は( README に書いていない気がするのですが) posh-git に ssh-agent 起動コマンドがついてきます(profile.example.ps1 にひっそり使われている).プロファイルに, Import-Module posh-git の後に

Start-SshAgent -Quiet

を追記することで, PowerShell を立ち上げたときに ssh-agent が起動して,適宜秘密鍵のパスワードが訊かれます.一度入力すれば ssh-agent が生きている限り ( PowerShell を一度閉じても) 存続します.

補足:鍵の置き場所

MSYS2 に入っているコマンドには, $HOME 環境変数を読む子と読まない子がいます. ssh-agent はこれを読んでくれません. ssh-agent にとってのデフォルトの鍵の置き場所は /home/(ユーザー名)/.ssh/* ですので,たとえば Chocolatey で MSYS2 64bit をインストールした場合は C:\tools\msys64\home\(ユーザー名)\.ssh\* が読まれます.一方, $HOME の設定やソフトウェアによっては C:\Users\(ユーザー名)\.ssh\* を読む子や, C:\Users\(ユーザー名)\AppData\Roaming\.ssh\* を読む子もいるかもしれません.私は鍵ファイルを単一の場所に置いて,他の場所からシンボリックリンクを貼っています.たとえば

cd C:\tools\msys64\home\(ユーザー名)
ln -s C:\Users\(ユーザー名)\.ssh .ssh

とすると, C:\tools\msys64\home\(ユーザー名)\.ssh はまやかしになるので, C:\Users\(ユーザー名)\.ssh 以下に鍵を置くだけで済むことになります.

補足:win-ssh-agent.sh を使う

前述の方法は git-posh に依存するため, PowerShell でのみ利用できます.コマンドプロンプトで ssh-agent を使いたい場合は以下になります.

ほげめも: win-ssh-agent.sh にて配布されている win-ssh-agent.sh を利用すると,(posh-git 不存在下で)ssh-agent の存続が可能です.

私の場合, C:\tools\msys64\usr\local\bin\win-ssh-agent.sh として保存し, C:\tools\msys64\usr\local\bin への $PATH を通し,スタート画面に %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "bash win-ssh-agent.sh; refreshenv" へのショートカットを貼って使っていました.(この場合,実行後 PowerShell が閉じるので refreshenv はなくても動くと思います. refreshenv については備考にて後述.)

なぜ posh-git 存在下でうまくいかないかは定かではありませんが,以下のような事実があります. ssh-agent を固定するために 2 つの環境変数 $SSH_AGENT_PID, $SSH_AUTH_SOCK が用いられます. ssh-agent を実行するとこの 2 つの環境変数を設定し export する文が出力されます.通常 Linux 系では eval `win-ssh-agent.sh` とすることでこれを実行します. win-ssh-agent.sh においても,実装を読むとわかりますが, ssh-agent から吐き出された 2 つの環境変数を PowerShell を使って保存する処理を行っています.したがって,たとえば PowerShell 上で bash win-ssh-agent.sh; refreshenv するとすぐに ssh-agent の効果が有効になります.実際, $env:SSH_AGENT_PID を評価すると確かに ssh-agent の吐き出した PID が設定されています. PowerShell を閉じて開き直しても $env:SSH_AGENT_PID は維持されています.一方, posh-git 存在下で bash win-ssh-agent.sh; refreshenv するとすぐに ssh-agent の効果が有効になるものの, PowerShell を閉じて開き直すと $env:SSH_AGENT_PID がなくなって,または古い値になっています.そこで refreshenv するとそのウィンドウでは $env:SSH_AGENT_PID が最新の値になりますが,閉じて開き直すと再び古くなります.おそらく git-posh がセッションまたは環境変数に関して特殊な扱いをしており, Import-Module git-posh 時にどこか別のところから環境変数がセットされているのだろうと思います.

which コマンドを作る

PowerShellでwhichコマンド – Qiita

上記の記事によれば, Unix における which hogehoge と似たようなことが gcm hogehoge | fl でできます.これは以下のようにコマンドレット化できます.

# quasi-which
function which($arg) {
  gcm $arg | fl
}

これをプロファイルに追記するとよいです.(ただし, MSYS2 を使っている場合は MSYS2 の which は覆い隠されます.)

備考:エイリアスを消す

PowerShell では Compare-Object のエイリアスとして diff が設定されています.ただ, MSYS2 に入っている diff のほうが好きである場合はこれが覆い隠されてしまうので,困ります.以下のようにすればエイリアスを削除できます.

Remove-Item alias:diff -force

標準エイリアスは読み取り専用になっているので -force が必要です.これをプロファイルに追記するとよいです.

備考:refreshenv

Chocolatey をインストールすると refreshenv コマンド(正式名称: Update-SessionEnvironment )がついてきます.これを実行すると, PowerShell を開き直すことなく最新の環境変数を読み込むことができます.

備考:PowerShell v2 のアップデート

Windows 7 には PowerShell v2 が入っています. $PSVersionTable を評価すると確かに 2 っぽい数字が含まれます.これは PowerShell v5 にアップデートすることができます.

v2 から v5 にアップデートする際には罠があります.それは v4 を経由することです. PowerShell v5 は WMF 5.0 に含まれているのですが, WMF 5.0 の System Requirements | MSDN を注意深く読むと

  • Latest service pack is installed.
  • WMF 4.0 is installed.
  • .NET Framework 4.5 or above is installed.

が前提条件である旨の説明が書いてあります.したがって, WMF 5.0 を正しくインストールするには,前もって Windows 7 SP1 であることを確認し,最新版などの適当な .NET Framework をインストールし, WMF 4.0 をインストールする必要があります.

System Requirements | MSDN に貼ってある WMF 4.0 と .NET Framework へのリンクやその先の Install Instructions を参照して,適切なファイルをダウンロード,インストールしてください.

なお, PowerShell/Windows7にPowerShell5.0をインストールしてみた – Windowsと暮らす の記事はたくさんのスクリーンショットを含んでいて参考になります.ただし WMF 4.0 のインストールについては触れられていませんので自力で補いましょう.