tech.guitarrapc.cóm

Technical updates

Windows開発環境の構築をChocolateyからscoopに切り替える

この記事は、PowerShell Advent Calendar 2019の一日目です。

qiita.com

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 を使っていました。

Chocolatey は、Windows環境でのパッケージリポジトリの提供とCLI インターフェース choco を通して、Windows においてコマンドラインからアプリケーションをインストールする体験を提供します。

chocolatey.org

最近聞かなくなりましたが、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.org

gist.github.com

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.

https://scoop.sh/scoop.sh

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 にまとまっているので、そこを見て探してもいいでしょう。

github.com

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>

github.com

もし過去バージョンがたまっているversions Bucket にアプリがあるならこれを使うのも手でしょう。

scoop bucket add versions

github.com

私は過去バージョンを 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 を作ったので次回紹介しようかと思います。

github.com

TIPS: Scoop のアプリ実体

余り意識する必要がないのですが、興味のある人向けです。

scoop でインストールされたアプリは、基本的に ~\scoop\shims\アプリ名.EXE のパスに存在します。shims でわかる通り、これらは ~/scoop/apps/アプリ名/current を参照しており、アプリケーションのインストールと利用が分離されています。

scoopのshimsフォルダー

apps のアプリディレクトリを見ると、バージョンフォルダと current が存在し、current は常に最新バージョンのシンボリックリンクになっています。

shims が参照しているappsのディレクトリ

まとめ

Chocolatey はインストールの1回に限れば便利です。が、今後もモデル的にアンインストールやUACが改善するには msix が来ない限り難しいでしょう。 Scoop を使うと、Unix Toolやsれ以外のツールの多くもいい感じでインストール、アンインストールできます。

私もScoopの独自Bucketでフォントとかいくつかパッケージを公開しているので、独自のアプリケーションを Scoop で配布することもいずれ記事にします。

*1:私はGUI操作時よりコマンドライン操作時の方がUACをストレスに感じます

*2:Windowsなのでプロセスが実行中はファイルがロックされます