目的
今日日(2019年4月)、BashとPythonは、Windows、Linux、macOSを含む主要なOSで動作する共通の環境であり、BashとPythonで処理を書くことでOSへの依存を避けることができる。そこでWindowsでBashとPythonが動作する環境を構築する。具体的な要件は以下の通りとする。
- 64-bit Windows 10で、BashとPythonの対話およびバッチ実行を行う。
- BashからWindowsのファイルシステムを直接扱う。
- Unix/Linuxの各種ツールをWindowsで利用する。
- 文字コードはUTF8とする。
方針
現在、WindowsでのBashシェル環境で、主要なものは以下の通り。
- Cygwin
- MSYS2/MinGW
- Git for Windowsの付属のBash
- Windows Subsystem for Linux (WSL)
- Docker等を利用した仮想的なLinux環境
BashからWindowsのファイルシステムに直接アクセスしたいので、4. WSL と 5. Docker は選択肢から外す。仮想的な環境はストレージの容量を消費することも問題だ。1. Cygwin はよく知られている。GUIのパッケージ管理ツールがあり、長年保守されている。3. Git for Windowsは導入が楽であるが、パッケージ管理の仕組みはない。
今回は、将来にWindowsネイティブアプリのフリーな開発環境を整備することを視野に入れ、2. MSYS2 を採用する。開発環境が必要なら、MSYS2からMinGWを導入する。MSYS2にはPacmanと呼ぶパッケージ管理の仕組みがある。
【参考】Windowsで使えるターミナルとシェルのまとめ
https://qiita.com/Ted-HM/items/9a60f6fcf74bbd79a904
インストールと設定
Windowsのユーザー名の確認
まず、Windowsのユーザー名が空白文字を含まない半角英数字のみであることを確認する。空白文字や日本語文字がユーザー名やユーザーフォルダのパスに含まれると、後々トラブルを抱えることになる。その場合は、Windowsのユーザーをローカルアカウントで作り直す。
Miniconda/Anacondaのインストール
Pythonには環境分離の仕組みが欲しい。今回はWindowsで広く採用されているMiniconda/Anacondaを採用する。Miniconda/Anacondaは、Linux版やmacOS版もあると聞く。公式サイトからMinicondaのインストーラをダウンロードして実行する。インストーラで、環境変数PATH
を通すように指定する。
https://docs.conda.io/en/latest/miniconda.html
Miniconda/Anacondaの管理ツールであるCondaの設定を行う。Condaの古い一部のバージョン(例えば4.6.11)はMSYS2との相性が悪いので、最新版にアップグレードする(4.6.14ではfixされている)。詳細は以下のURLを参照。
https://github.com/conda/conda/issues/8486
conda upgrade conda
conda --version # バージョン確認
MSYS2のインストールと設定
続いてMSYS2に進む。公式サイトから MSYS2 のインストーラーをダウンロードして実行する。
https://msys2.github.io/
MSYS2インストーラーのデフォルトでは、MSYS2の /home
の実体は、C:\msys64\home
となる。Linuxから移植された様々なWindowsネイティブのツールが、C:\Users
下のユーザーフォルダに設定ファイルを置くことがあり、それをシェル環境でも使いたい。そこで、MSYS2のホームディレクトリをWindowsのユーザーフォルダとするように設定を変更する。テキストエディタで以下のように編集する。
#db_home: cygwin desc # コメントアウト
db_home: windows # 追加
C:\msys64\home
フォルダはもう不要なので削除する。
ついでに、パッケージ管理ツールPacmanの設定ファイルを編集する(任意)。
Color # コメントアウト
さて、Windowsのスタートメニューで MSYS2 64-bit のフォルダを見ると、以下の3つのアイコンを確認できる。
- スタートメニュー
- MSYS2 64-bit
- MSYS2 MinGW 32-bit
- MSYS2 MinGW 64-bit
- MSYS2 MSYS
- MSYS2 64-bit
これらはそれぞれ独立した環境を指しており、パッケージも別に管理される。以降、使用するのは MSYS2 MinGW 64-bit とする。他の環境は使用しない。(間違って起動しないように、使わないアイコンを削除しても良いかもしれない。)
MSYS2のパッケージを整備する。スタートメニューから MSYS2 MinGW 64-bit を起動し、以下を実行する。
### Download fresh package databases from the server
pacman --sync --refresh
### Upgrade installed packages
pacman --sync --sysupgrade
### Install GNU toolchain, including a MinGW-version of Git (Optional)
pacman --sync base-devel
#pacman --sync mingw-w64-x86_64-toolchain # もし必要なら
### Install Git
pacman --sync ca-certificates
pacman --sync git
git --version # バージョン確認
### Remove old packages from cache directory
pacman --sync --clean
なお、MSYS2 64-bitパッケージの一覧は、以下で確認できる。
http://repo.msys2.org/msys/x86_64/
些末な話だが、util-linuxパッケージの最新版(2.26.2-1)には、script
コマンドが移植されていない。経緯は以下のURLを参照。
https://github.com/Alexpux/MINGW-packages/issues/4497
どうしても欲しければ、以下のようにscript
コマンドを含む過去の版から取得する方法がある。なお、完全な動作確認はしていない。
wget http://repo.msys2.org/msys/x86_64/util-linux-2.26.2-1-x86_64.pkg.tar.xz
pacman --upgrade util-linux-2.26.2-1-x86_64.pkg.tar.xz
mkdir -p /usr/local/bin
cp /usr/bin/script.exe /usr/local/bin/
pacman --sync --sysupgrade
Bashの設定を行う。以下を追記した。
# 自分好みのコマンドエイリアス
alias ls='ls --color=auto --show-control-chars --time-style=long-iso --human-readable --classify'
alias ll='ls -l' # long list
alias la='ls -A' # all but . and ..
alias grep='grep --color' # show differences in colour
alias less='less --raw-control-chars' # raw control characters
alias whence='type -a' # where, of a sort
# Miniconda/Anacondaの設定
#. 'C:/ProgramData/Anaconda3/etc/profile.d/conda.sh' # Anaconda3ならこちら
. '/c/ProgramData/Miniconda3/etc/profile.d/conda.sh' # Miniconda3ならこちら
利用方法
Bashの起動
Windowsと他の環境(Linux、macOS等)との差があれば、~/.bash_profile
等の設定で吸収する。
対話的にBashを利用するには、コマンドプロンプトで以下を実行する。コードページをUTF8としている点に注意。環境変数MSYS
の意味は後述。
CHCP 65001
SET MSYS=winsymlinks:lnk
CALL "C:\msys64\msys2_shell.cmd" -mingw64 -defterm -here -full-path -no-start
WindowsのバッチファイルからBashスクリプトを実行するには、以下のようにする。
CHCP 65001
SET MSYS=winsymlinks:lnk
CALL "C:\msys64\msys2_shell.cmd" -mingw64 -defterm -here -full-path -no-start TARGET_SCRIPT.bash
EXIT /B %ERRORLEVEL%
Windowsのバッチファイルから単独のMSYS2のコマンドを実行するには、以下のようにする。
CHCP 65001
SET MSYS=winsymlinks:lnk
CALL "C:\msys64\msys2_shell.cmd" -mingw64 -defterm -here -full-path -no-start -c TARGET_COMMAND
EXIT /B %ERRORLEVEL%
上記で使用したものを含め、MSYS2関連の主な環境変数には以下がある。細かい挙動については、msys2_shell.cmd
(これはバッチファイルである)の内容を参考のこと。
-
MSYS
-
ls -s
等のリンクに関する挙動を決める。 ここの設定は、msys-2.0.dll
を利用するすべてのプログラムに影響する。winsymlinks:lnk
を指定すると、シンボリックリンクの作成は、Windowsショートカットの作成となる。 この環境変数が存在しないと、シンボリックリンクを作成しようとすると、ファイルがコピーされるようになる。
-
-
MSYSTEM
-
MINGW64
を指定すると、MSYS2 MinGW 64-bit 環境向けの環境変数PATH
を構成する。msys2_shell.cmd
の-mingw64
オプションに対応。 詳細は/etc/profile
を参照。
-
-
MSYS2_PATH_TYPE
-
inherit
とすると、シェル環境変数PATH
の末尾にWindows環境変数PATH
の項目を追加する。msys2_shell.cmd
の-full-path
オプションに対応。 AnacondaのPython含め、Windowsネイティブのコマンドを利用するには、これを使うのが便利である。strict
とすると、Windowsの環境変数PATH
を継承しない。 詳細は/etc/profile
を参照。
-
-
CHERE_INVOKING
-
1
とすると、Bashログイン時に現在のディレクトリを変更しない(つまり、HOME
環境変数の場所に移動しない)。msys2_shell.cmd
の-here
オプションに対応。
-
-
MSYS2_ARG_CONV_EXCL
- 親切なことに、MSYS2は、Windowsネイティブなコマンドを実行するとき、 コマンド自身のパスとその引数に見つかった絶対パスを Windows形式(ドライブ文字付き)の絶対パスに変換する。 コマンド引数に指定したパスがこの値と前方一致する場合、この変換処理の対象から除外する。 複数指定する場合は、セミコロンで区切る。
MSYS2では、ルートディレクトリにWindowsのドライブが、ドライブレターの小文字でマウントされている。例えばC:\Users
を指定するには、/c/Users
とする。
参考までに、MSYS2コンソールからWindowsのプログラムを別ウィンドウで開くには、START
コマンドを使う。以下に例を示す。
START CMD # 別画面でコマンドプロンプトを開く
START CHROME # Chromeを起動する
START https://www.google.com/ # Windows既定のWebブラウザでURLを開く
START EXPLORER . # カレントディレクトリをWindows Explorerで開く
Pythonの起動
PythonはBash上で使用する。BashでMiniconda/AnacondaのPython環境を切り替えるには、良く知られているように、conda
コマンドを使う。
conda activate base
参考までに、コマンドプロンプトでMiniconda/AnacondaのPython環境を切り替えるには、(これもWindowsユーザーにはよく知られていることと思うが、)conda.exe
でなくconda.bat
を使う。
call conda.bat activate base
今後の調査
Proxy環境での設定を要確認。以下らしいが、今後検証する。
# 以下を追記
proxy-user = "user:passwd"
proxy = "http://proxy.com:8080"
# 以下の行コメントを解除
XferCommand = /usr/bin/curl -C - -f %u > %o
# 以下を追記
keyserver-options http-proxy=http://user:passwd@proxy.com:8080/
# 以下を追記
export HTTP_PROXY=http://user:passwd@proxy.com:8080/
export HTTPS_PROXY=http://user:passwd@proxy.com:8080/
export FTP_PROXY=http://user:passwd@proxy.com:8080/
おわり。