この記事は、PowerShell Advent Calendar 2019の一日目です。
Windows のパッケージマネージャーの裏はPowerShellが多く使われています。
そんなWindows におけるパッケージマネージャーと言えば、Package Management Chocolatey が有名なのではないでしょうか?
私もChocolatey をパッケージマネージャーに用いて開発環境の構築をしてきましたが、課題が多かったため Scoopに切り替えました。
Chocolatey で何が問題だったのか、なぜscoop を選んだのか、この一年 scoop をどのように環境構築に利用しているのかを紹介したいと思います。
目次
TL;DR
Chocolatey から scoop に切り替えることで開発環境の自動化、ほとんどのアプリケーションをユーザー権限でのインストールに抑え込むことが可能になりました。
scoop に切り替えて得られたものをざくっと紹介します。
- UACの不要なインストール
- 簡単なアップグレード
- 常に最新環境への追随
- 確実なアンインストール
- アプリケーションのパス均一化
- ローカル開発環境構築の自動化
将来的にmsix が広く使われるようになったら、Scoopより利用しやい仕組みになるとうれしいです。
Chocolatey の利用
Scoop に切り替えるまでChocolatey を使っていました。長年利用して感じていた課題を見てみます。
どのように Chocolatey を利用していたのか
2014年にDSCを自動化しようとしていることから、Chocolateyとは5年の付き合いです。2018年までは個人、会社の開発環境構築にChocolatey を使っていました。
Weekend Scripter: PowerShell and Chocolatey http://t.co/EhJugCrAdc
— guitarrapc_tech (@guitarrapc_tech) August 24, 2014
Chocolatey は、Windows環境でのパッケージリポジトリの提供とCLI インターフェース choco
を通して、Windows においてコマンドラインからアプリケーションをインストールする体験を提供します。
最近聞かなくなりましたが、Package Management のバックエンドとすることで「リポジトリの1つとみなして利用」したり、「独自リポジトリにChocolateyフォーマットのnugetパッケージを置いてチームのプライベートリポジトリとする」こともできます。
前職においては、Unityのリリースを検知、自動的にNuGetパッケージを生成、社内NuGetサーバーに配置、Package Managementを使ってChocolateyパッケージをインストール可能な状態にしていました。こうすることで、Unityのインストールパスをチームで共通化し、Unityインストールの最大の敵であるダウンロードの遅さ、パッケージの分かりにくさに対応していました。
今なら Unity Hub があるので不要です。(当時は Unity Hubがなかった)
Chocolatey で困ること
Chocolatey で開発環境を構築したものの困ることがあります。アンインストールとUACです。
アンインストール
Chocolatey は、MSI や exe 形式のインストールをchocolateyinstall.ps1
で扱い、アンインストールをchocolateyuninstall.ps1
で扱います。しかしその実体は地道にインストーラをたたいており、実行の待ち受けやパスで失敗したり、インストールで行っていたWindows Serviceやレジストリは消し忘れていたりします。また、そもそも多くのパッケージでアンインストールスクリプトが提供されていません。
Chocolatey でも最大規模のインストールパッケージである、git.install のアンインストール処理でもこんな感じです。
Chocolateyを構築時だけに使うという割り切りならいいのですが、開発環境はどんどん変わっていきます。当然アンインストールをする機会も少なくないでしょう。アンインストールが不安定だったり、未提供だとインストールとは非対称に以前のWindowsでのアプリケーション管理をすることになります。
使ってきた経験から言えるのは、残念ながらChocolatey でインストールしたものであってもWindowsのApps & Feature
でアンインストールが必要なものがほとんどです。
私はChocolateyで今後もやっていくという判断ができませんでした。アンインストールはスパッと終わらせたいです。
UAC
UAC はWindowsでコマンドラインを使っていて感じるだるいと感じる筆頭かもしれません。Chocolatey でも残念ながらUACを求めてくるパッケージは多く存在します。 自動化するためのコマンドラインでchocolateyを使ってアプリケーションインストールの実行、席を立って戻ってみるとUACで止まっていた。という経験をお持ちの方もいるのではないでしょうか?
そもそも
choco install
などをするときに管理者に昇格したcmdやPowerShellを使うように言われます。
UACにはサンドボックスとしての安全さの提供という側面はあるものの、コマンドラインで作業していていきなりUACが表示されマウスクリックが必要だったりするのはストレスです。特にこれはLinux/macOS でコマンドラインによる操作に慣れていると顕著に感じるかもしれません。*1
Chocolatey が抱える問題点
Chocolatey が抱えている体験上の問題は2つに起因しているように思います。
- アンインストールの不完全な提供
- UACポップアップ
アンインストールに関しては、Chocolatey自体が MSI や exe といった各型式の実行ファイルを開発者が提供するスクリプトでなんとかする方式である以上避けられないように思います。Chocolatey 自身もValidation Program やChocolatey Install/uninstall/WebFile など各種サポート関数を提供していますが、たとえこれを使っても、Windows において回避するのは難しい側面があるのは否めません。
UAC も、MSIを使う以上シカタナイでしょう。%ProgramFiles%
は特権ユーザーでないとアクセスできないので。しかし可能であればアプリケーションインストールごときでUAC昇格はしたくないですし、環境によっては厄介に感じます。
Chocolatey つかれました。
Scoop への切り替え
Scoop は Chocolatey とはコンセプトを別にするコマンドラインインストーラーです。
Looking for familiar Unix tools? Tired of Powershell’s Verb-Noun verbosity? Scoop helps you get the programs you need, with a minimal amount of point-and-clicking.
Homebrew 的に、常に最新のアプリやUnix Toolを、UACの縛りなく、さくっと利用できるとうれしい。そういう使い方を想定されています、まさに私にはぴったりでした。
Scoop installs programs to your home directory by default. So you don’t need admin permissions to install programs, and you won’t see UAC popups every time you need to add or remove a program.
Scoopのインストール
PowerShell からワンライナーでインストールできます。
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') # or shorter iwr -useb get.scoop.sh | iex
使い方は scoop help
でわかります。
$ scoop help Usage: scoop <command> [<args>] Some useful commands are: alias Manage scoop aliases bucket Manage Scoop buckets cache Show or clear the download cache checkup Check for potential problems cleanup Cleanup apps by removing old versions config Get or set configuration values create Create a custom app manifest depends List dependencies for an app export Exports (an importable) list of installed apps help Show help for a command hold Hold an app to disable updates home Opens the app homepage info Display information about an app install Install apps list List installed apps prefix Returns the path to the specified app reset Reset an app to resolve conflicts search Search available apps status Show status and check for new app versions unhold Unhold an app to enable updates uninstall Uninstall an app update Update apps, or Scoop itself virustotal Look for app's hash on virustotal.com which Locate a shim/executable (similar to 'which' on Linux) Type 'scoop help <command>' to get help for a specific command.
Scoop でアプリを利用する
sudo や git など、Windows にデフォルトで入ってほしいけど入っていないCLIツールは、まさに Scoop が向いています。
scoop install git
まとめてインストールすることもできます。
scoop install 7zip sudo git jq time unzip openssl
インストールしたアプリは、jq
などアプリ名でそのまま利用できます。
$ jq --version jq-1.6
インストールされているアプリケーションも一覧表示できます。
scoop list
アンインストールも簡単です。 プロセスがロックされていない限りは確実にアンインストールできるので安心できます。*2
scoop uninstall git
Scoop のアプリを検索する
利用可能なアプリは、scoop search
で探すことができます。
GitHub にまとまっているので、そこを見て探してもいいでしょう。
Scoop のアプリをよりたくさんインストールする
Scoop は、アプリのダウンロード元に GitHub を利用しており これを Bucket と呼んでいます。 インストール直後は Main Bucketのみがインストールされています。
scoop bucket list
Bucket はscoop bucket add
で追加できます。
Bucketを追加することで多くのアプリケーションをscoopでインストールできるようになります。
例えば、公式で提供されているExtra
Bucket は、 Main
Bucket にはないけどよく利用されるアプリケーションが含まれています。
scoop bucket add extras
extras Bucketの追加で gitkraken
などもscoopでインストール可能になります。
scoop install gitkraken
インストールするときに、Bucket を気にしなくていいのでかなり楽です。
scoop にしたことで混乱したこと
scoopの特性を把握せずにいたときに混乱したこともあります。
- 複数のパスに実行ファイルが存在することによる意図しない動作
- グローバルパスに存在が期待されるソフトウェアの継続的な更新の困難さ
例えば、.NET Core SDK は Visual Studio でも入ったりし、あらゆるツールが利用しているため scoop でインストールすることは向きません。
「何をscoopで入れて、何を入れない。」という選択を自分で行う必要があるので、そういう意味では誰にでもオススメできるわけではありません。 自分で選んだ結果を自分で受け入れ、対応していける人向けだと思います。
Scoop で過去のバージョンのアプリをインストールする
Scoop は .env のような制御はないので素直に使うなら、常に最新を使うのが楽です。(scoop install / scoop update していくだけ)
もし過去バージョンを利用する場合、scoop reset
で可能です。
scoop reset <app>@<version>
もし過去バージョンがたまっているversions Bucket にアプリがあるならこれを使うのも手でしょう。
scoop bucket add versions
私は過去バージョンを Scoop で利用することはしません。するぐらいならScoopやめる。
Scoop を継続的に使っていくための工夫
scoop でパッケージがインストールができるといっても、アプリをインストールするコマンドをずっと書き連ね、そのコマンドをスクリプトにしたりするのはつらいものがあります。
scoop install xxx scoop install yyy scoop install xxx
やりたいのは、アプリのインストールで scoopがいい感じにしてくれればなんでもいいのです。 ということで、こんなYAMLを書くことで Ansibles like に Scoop のアプリをインストール/アンインストールできる仕組みがほしいです。
- name: "Install linux tools" scoop_install: state: present bucket: main name: - cmake - gcc - gow - jq - sudo - time - unzip - openssl - apache - name: "Install windows tools" scoop_install: state: present bucket: main name: - 7zip - aws - bat - chromedriver - git - git-lfs - ngrok - pwsh - terraform - gibo - helm - mysql-workbench
YAMLでの定義を実現するためのPowrShell モジュール ScoopPlaybook
を作ったので次回紹介しようかと思います。
TIPS: Scoop のアプリ実体
余り意識する必要がないのですが、興味のある人向けです。
scoop でインストールされたアプリは、基本的に ~\scoop\shims\アプリ名.EXE
のパスに存在します。shims でわかる通り、これらは ~/scoop/apps/アプリ名/current
を参照しており、アプリケーションのインストールと利用が分離されています。
apps のアプリディレクトリを見ると、バージョンフォルダと current が存在し、current は常に最新バージョンのシンボリックリンクになっています。
まとめ
Chocolatey はインストールの1回に限れば便利です。が、今後もモデル的にアンインストールやUACが改善するには msix が来ない限り難しいでしょう。 Scoop を使うと、Unix Toolやsれ以外のツールの多くもいい感じでインストール、アンインストールできます。
私もScoopの独自Bucketでフォントとかいくつかパッケージを公開しているので、独自のアプリケーションを Scoop で配布することもいずれ記事にします。