gvim(+kaoriya) + WSL Part3

:prev の続き

※この内容は事前に Part1で記述したように shell,shellcmdflagとかの変数をWSL用に変更する必要があります。

とりあえず、gVim(+kaoriya) と WSLの連携をある程度スムーズにできるようになりましたが、問題が一つ発生。
ローカルドライブだと問題はないのですが、リムーバルディスクとかネットワークドライブだと、WSL内の /etc/fstab に記述して自動マウントしてても、Windows10アプリケーションからWSLに移行した時点でカレントディレクトリが引き継げません。

ネットワークドライブを ドライブレター(Z: とか)にアサインして、cmd.exeで cd /d z: としてカレントディレクトリを変更し、bash.exe(or wsl.exe)しても、ホームディレクトリに飛ばされます。。。
カレントディレクトリを引き継いでくれるのは、c:ドライブとか、ローカルハーディスクだけのようです。ディスクタイプによって判断しているんでしょうか・・・。

これが一番困るのは、:grep コマンド。:grep コマンドの結果をQuickFixで開けるようにしているけど、カレントディレクトリ以下でローカルドライブだとなんとか使えるけど、リムーバルドライブとか、ネットワークドライブだと、パスの関係で全滅。WSLのフルパスで検索対象を渡せば grep は機能するが、QuickFixウィンドウに表示されるのはWSL側のフルパスなので 当然 gVim ではそのパスが理解できないので、結局使えない。

解決方法は、3つ。

(1) :grep をあきらめ、:vim(grep) で代替。
  ⇒ (ネットワークドライブだと特に)遅い。常用できないほど遅い。

(2) Msys の grep.exe で代替
 ( _vimrc にて set grepprg=/mnt/c/Msys64/usr/bin/grep.exe\ -n

  ⇒ WSLのみでなんとかする、という最初の趣旨から外れてしまうが・・・しょうがない。

(3) WSL側に grepの結果からパス名部分を変換するフィルタスクリプトをかます
 ( _vimrc にて set grepprg=grepwsl\ -n

  ⇒ ネットワークドライブ内のファイルを編集している時だけ検索パスをフルパス(WSL)を指定しないといけない。
  ⇒ また、若干遅くなるが、許容範囲内。。。WSLだけで完結できる。

というわけでとりあえず しばらく(3)を常用することにした。すでに Msys入れている場合は(2)の方が簡単かも・・・。ネットワークドライブのときだけ検索パスを絶対パスにする必要があるが、まぁしょうがない。

まずネットワークドライブ(例: Y)をドライブレターにアサインし、 sudo mkdir /mnt/yでディレクトリを作成し、/etc/fstabに登録する。

# /etc/fstab
LABEL=cloudimg-rootfs   /        ext4   defaults        0 0
Y: /mnt/y drvfs defaults,noatime,uid=1000,gid=1000 0 0

WSL側のpathが通っているところに(たとえば /usr/local/bin/ とか)grepwsl を作成しsudo chmod +x /usr/local/bin/grepwsl

#!/bin/sh
##############################################################################
#  wslgrep  .... WSLに入っているwslpathコマンドを使用してパスを変換 
#  2018/08/29 絶対パスに変換するオプション(-a)を追加/正規表現ちょい修正
##############################################################################
grep $@ | perl -pe 's/^([^:]+)/`wslpath -m -a $1 | tr -d "\n"`/e;'

これは単にgrepの結果を perl に渡して変換処理をしてるだけ。sedでもawkでもなんでも。単にperlに慣れているだけ。

んで、~/_vimrc に追記

;;; ~/_vimrc
set grepprg=grepwsl\ -n

ってなけで、とりあえず、なんとかなった!(^^;

gvim(+kaoriya) + WSL Part2

:prev
この前のつづきです。

シェルをWSL(ubuntu bash)にすることで、:terminalの他、外部コマンド実行(“!” から始まるやつ)をWSL内で完結することができました。
が、ただ一点、:terminal {command} にする場合、:terminal bash -c '{command}' としないとエラーになってしまうので、これが不満。

そこで、Wslterm というユーザー定義のコマンドを _gvimrc に追加することで、ラクしよう、と、こういうわけです(^^;
ヘルプを斜め読みしてとりあえず関数とコマンドの定義の仕方を最低限覚えて、以下の記述に辿り着く。
ほんとはもっとスマートなやり方があるんだと思いますが・・・素人の思いつきです。。。

" terminal の WSLラッパー コマンド (かなり修正:2018/7/13 0:02)
" ・・・なんかトンチカンなことをやってる気がしてきた・・・
" append to ~/_gvimrc 
set shellslash
set shell=C:/WINDOWS/system32/bash.exe
set shellcmdflag=-c
set shellquote=\"
set shellxescape=
set shellxquote=

function! Wslterms(c,f,l,...)
  let cmdline = []
  let option = []
  let i = 0
  while i < a:0
    if stridx(a:000[i],'++') == 0
      call add(l:option,a:000[i])
    else
      call add(l:cmdline,a:000[i])
    endif
    let i += 1
  endwhile
  let l:options = len(l:option) ? join(l:option," ")." " : ""
  let l:cmd = "terminal " . l:options

  if len(l:cmdline) > 0
    let l:cmd = printf("%s%s %s %s",l:cmd,&shell,&shellcmdflag,shellescape(join(l:cmdline," ")))
  endif

  if a:c 
    let l:cmd = join([a:f,a:l],",") . l:cmd
  endif

  execute(l:cmd)
endfunction
command! -nargs=+ -complete=file -range=0 Wslterm call Wslterms(<count>,<line1>,<line2>,<f-args>) 

これで、:Wslterm perl %とか、’<,'>Wslterm hogehoge とかやると、bash -c をつけて簡易的に :terminalの真似ができました(^^;; おまけで、gvimのterminalの中で、WSL(ubuntu)内のvimでファイルを編集(左)とかできちゃう!w

ただ、vim自体操作は慣れてきたとはいえ、まだよく分かっていないのでこういうアプローチでいいのか、よく分かんないです。またvimスクリプトの本でも買って勉強しよ。

■補足 2018/09/24
guioptions に “!” を追加すると :shell コマンド時、コンソールウィンドウが立ち上がるのではく、gVimのウィンドウを使用するみたい。知らんかった・・・・。

:set guioptions+=!

_gvimrcに書いとくと、かなりイケてる感が味わえるかも(^^;
ちなみに僕の guioptions は・・・

"snip
guioptions=egmrL!
"snip

となっております。。。

なんやかんやでエディタ宗旨変え

いろいろあって転職を思案中。持病持ち・身障者オッサンの転職は正直厳しく難しい。後片付けしながら就活するか、雇用保険もらいながらダラダラとやるか・・・。年度内で一区切りしようと思っているけど、どっちにしろメンドっちーなー。

そんなことはともかく。。。

10数年以上、テキストエディタはxyzzyを使っていました。
なんの不満もなく、僕的には最強のエディタだと、自分に言い聞かせ(^^;使っていました。ここ最近は Linuxなどの非WindowsなOSをいじることが多くなって、そういう時は操作感が非常に似通っているEmacsを、と使い分けていたのですが・・・Emacsを使えないサーバーが多々あり、やむなく 端末上で vim を使う練習・・・というか修行をここ1年ほどしてました。

最近・・・xyzzy で CTRL-N,CTRL-P,CTRL-B,CTRL-F でカーソル移動するところを・・・気付けば J,K,H,L と、打ち間違うことが多発 トホホ(笑)

で!、なんの気なしに『Windows版のGUIなvim ってあるのかな・・・?』と探している自分が居まして・・・、Kaoriya版のWindows向けvimをインストールして、まずはシェルスクリプトを編集するときだけ、gvim を極たまに使っておりました。
この頃はまだ、xyzzy 最強ー、と思ってました。vimってやっぱ、使いにくい!!! なんだ、あの、ノーマルモードやら挿入モードやらコマンドモードやらを行ったり来たりめんどくせーーーー、って。

でも、amazonで買ったkindle版の解説本で紹介されていた、vim-surroundというプラグインを知り、このプラグイン、すげー、カッコやら引用符やら、波カッコの挿入、変更、削除が一発でできるやん!!!ってことにコロッと一目ぼれして、気づけば、ソースコードファイルの拡張子をレジストリいじって gvim に関連付けしてた(ーー;

僕的に↓良書。

でもWindows版 だと外部コマンド実行の時、コンソールウィンドウが開いてダサーーってなる。
んー、まぁ、このダサさもWindowsの味なんで・・・(^^;

あと、エディタで使うフォントでしっくりくるものが未だに見つからない。

それに英語配列以外のキーボードだと激しく使いづらい。。。まぁこれは慣れの問題だけども。

それと、vim使ってない時の他のアプリでテキスト入力するとき時で、入力が終わった後なんでもかんでもCTRL-[ をタイプしてしまうという謎の癖がついてしまった・・・orz

開発環境見直し for WORDPRESS on WSL

2017/12/21 追記:
bashを終了すると、立ち上げたデーモン全部落ちてしまいますが、Windows10の次のなんちゃら UPDATE で、bashを終了してもデーモンが生き残るようになるとのこと。朗報ですな。うんうん(^▽^)/ っていうか、僕的に、もうWindows要らね、って・・・。 Apple iTunesと Adobe Creative Cloud が linux 対応してくれたらももうWindows使うの終わりかもw

2017/11/09 追記:
LAN内の他のPCからアクセスするには、コントロールパネル ≫ Windows Defender ファイヤーウォール の新規受信規則で、ポート80番を開けないといけません。


ちょっと前に今の仕事の開発環境を新しくしたのですが、Windows 10 Fall Creators Update(以下、FCU)で、Windows Subsystem for Linux(WSL)がベータ版から正式版に変わったんで、また見直し。見直しというか、Wordpress用。

HyperVを使った前のやつは、こっち、でCIFSマウントしているディレクトリへのアクセスがたまにエラー?で読み取れなくなるぐらいで、特に不自由もなかったんですが、WSLの記事をググると、思いの他進化しているので、WORDPRESSでのお手軽サイト構築用の環境として整備することにした。

Windows10 FCU からは、限定的ですが、ネットワークフォルダをマウントすることができて、WSLはかなり実用的な開発ツールセットになってきています。しぶしぶMac使っている人(そんな奴いるのか?)は、やっと大好きな(笑) 使い慣れたWindowsでウェブ系のお仕事ができます!( ̄▽ ̄)

BoWそのものは、マイクロソフトストアからインストールできるので、もう説明要らないでしょう。Windows10 FCUから開発者モードにする必要もなくなったし。

手順を記録しとこう、という備忘録です。特にこれといって新しいことが書かれているわけではなく、グーグル先生に聞いた内容を自分用にまとめたものなので、あまり参考にはなりません。あしからず。

>>以下の手順を全自動で行うシェルスクリプト

■ パッケージのインストール
apt コマンドで、必要なパッケージをインストールしていきます。sudo するのがかったるいので、全部 root で作業します。
の、前に・・・、まず、/etc/apt/source.list の中のリポジトリを日本のものに差し替えるのが定石だそうですので、変更してからにします。
また、mysql-serverをインストールする最中に、root パスワードを入力するように促されるので適当に。

sudo su -

sed -i.orig -e 's%http://archive.ubuntu.com/ubuntu/%http://ftp.jaist.ac.jp/pub/Linux/ubuntu/%g' /etc/apt/sources.list
apt update
apt -y upgrade

apt -y install apache2 apache2-doc mysql-server mysql-client
apt -y install php php-mbstring php-mysql php-sqlite3 php-gd php-mcrypt libapache2-mod-php 

php の方は、必要なモジュールを別途 apt でインストールする必要があります。・・・その辺はまぁ適当に。

■ Apache2 設定
まず、そのまま “service apache2 start” とかやると、ワーニングがでます。まぁ、無視すりゃいいんですが、気になるので・・・。
/etc/apache2/apache2.conf を開いて下記2行を追記します。

AcceptFilter http none
AcceptFilter https none

あと、開発するファイル等が入った、ドライブなり、フォルダなりを apacheから見えるようにしないといけません。
windows.confは、僕の環境では、下記のような感じ

#
# /etc/apache2/sites-available/windows.conf
#
&lt;Directory "/mnt/d/devel"&gt;
AllowOverride All
Options All
Require all granted
&lt;/Directory&gt;
Alias /devel /mnt/d/devel

で、有効化します。

a2ensite windows

php.iniの修正も若干必要ですかね。デフォルトで2MBしかアップロードできませんし、開発環境なんで、memory_limitは無制限にしたい。
ってなわけで、/etc/php/7.0/apache2/php.ini で、以下の項目を修正

  • date.timezone
  • memory_limit
  • post_max_size
  • upload_max_filesize

それと、まぁ、ほとんど使わないと思いますが・・・DocumentRootが /var/www/html で設定されているのですが、これのオーナーとグループを自分のユーザーにしときましょう。いちいち sudo してコピーするのメンドクサイでしょう。ついでにホームディレクトリにリンクを作っときましょう。

#一度 root を exit して・・・
exit
#myuserは自分のアカウントで置き換える
sudo chown -R myuser:myuser /var/www/html
ln -s /var/www/html ~/wwwroot
# root に戻る
sudo su -

■ MySQL 設定
次、mysql。apacheと同じく、”service mysql start” とかやると、僕の環境ではワーニングが出ます。これも無視すればいいんでしょうけど・・・。
mysqlユーザーのホームディレクトリを作ってやります。すでにあればやる必要なし。

mkdir /home/mysql
chown mysql:mysql /home/mysql
usermod -d /home/mysql mysql

mysql の 文字コードを UTF8にしときます。
/etc/mysql/my.cnf を開いて、下記を追記

[client]
default-character-set = utf8

[mysql]
default-character-set = utf8

[mysqld]
character-set-server = utf8

ここで、一旦 mysql を起動して、mysqlクライアントからユーザー、データベースを作っちゃいましょう。

service mysql start
mysql -u root -p

ここから mysql シェル

まずユーザー(wpuser)を作成。パスワードは適当に 0000 とか。
> CREATE USER wpuser IDENTIFIED BY '0000';

WORDPRESS用のデータベースを作っときます。
> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;

作ったユーザーに、データベースの権限を全許可します。
> GRANT all privileges ON wordpress.* TO wpuser

> quit

あと、phpMyAdmin は必須っすね。aptコマンドでインストールしてもいいんですが、最新のものをマニュアルで入れときます。

#一旦rootを抜けて、一気に片付けましょう。
exit
cd /var/www/html
wget -O - https://files.phpmyadmin.net/phpMyAdmin/4.7.5/phpMyAdmin-4.7.5-all-languages.tar.gz | tar xvzf -
mv phpMyAdmin-4.7.5-all-languages phpMyAdmin
cd phpMyAdmin
cat config.inc.sample.php | sed -r 's/^(\$cfg\['\''blowfish_secret'\''\]) *= *'\''.*'\''/\1 = '\''32_moji_no_randamu_na_ei_suuji_x'\''/g' > config.inc.php

WSLではサービスとして動かすことができないので、bash を終わらせるとapache,mysqlのデーモンが全部落ちます。まぁバックグラウンドで走らせてしまうと、Windows Serverの顔が立たない(^^;ので致し方ありません。
bashを立ち上げるたびに、

sudo sh -c 'service mysql start; service apache2 start' 

とかやる必要があります。まぁこれは、alias 一個作っとけばいいだけなんすけどね。

WORDPRESSでのサイト構築ではもう十分な感じ。でも WSLのubuntuで docker が動いたらこんなメンドクサイことしないで済むのになぁ・・・。いずれ対応してくれることを祈る。

実際にはシェルスクリプトにすることで、インストールしてコマンド一発で、LAMP環境をセットアップできるようしています。
そのスクリプトは、こっち。

開発環境の見直し。

「Byte range lock とは何ぞや???」

結論から言うと、その方面に詳しくないので全然わからない。検索結果を拾い読みしていくと、ファイル全体をロックするのではなく、バイト単位で範囲を指定してロックする、というものらしい。

事の始まりは、開発環境を一新したことがきっかけだった。

長年 Windowsユーザーである私は、Win32版のApache/MySQL/Perl,PHP(俗にいうWAMP環境)をセットアップして使ってきた。しかし、これらサーバー類のWindows版とLinuxなどのUNIX互換OS上のそれらとの挙動の違いなどが最近非常に気になり出しはじめ、その違いを吸収するようなコードをアプリケーションに組み込む量が多くなってきた。本来なら必要のないコード。

で、ApacheやMySQLなどのWindows版を使うのをやめ、Hyper-Vの仮想マシン(内部仮想スイッチ+WinNATで外に出るよう構築)にサーバー類を移すことにした。幸いここ数年 CentOSをいじるようになってきたのでLinuxサーバーの構築は慣れているので開発環境の移行は結構すんなりできた。

仮想化ソフトは色々あるんですが・・・まぁある程度のスペックのPCとWindows8.1以降なら迷わずWindowsに標準でついてくるHyper-V がベストだと思います。

仮想マシンを立ち上げるには、 Powershell(要権限昇格) を使うとスマート。GUIなHyperVマネージャは仮想マシン作るときだけでいいかなと。

仮想マシンの列挙
>> Get-VM

起動とシャットダウンは・・・
>> Start-VM -Name CentOS7
>> Stop-VM -Name CentOS7

コンソールにアクセスしたければ、vmconnectを実行
>> vmconnect localhost CentOS7 

もし仮想マシンがWindowsなら、リモートデスクトップで立ち上げとか。
>> mstsc /v:仮想マシンのIPアドレス

しかし、ファイルの編集などは使い慣れた Windows上のエディタ環境を使いたいしソース管理もTortoiseSVNで引き続き行いたいので、仮想マシン上に cifs-utilsをyumでインストール。Windows上のDドライブをまるごと共有し、Linux側から マウントさせ、そのディレクトリをhttpd.confで適切なURLにマッピングしてやれることでWindows上でファイルを編集しつつ、そのコードは仮想マシン上のLAMPで動くという、理想的な環境のできあがり。
図にすると、下記のような感じ。

実際に、構築して使ってみると、これが快適すぎて、もっと早くにしとけばよかった。仮想マシンをエクスポートしてバックアップしとけばPC買い替えたときもラク。

はじめ仮想スイッチを内部専用にしたせいで仮想マシン側からホスト外にアクセスできず困ってたんですが・・・PowerShellの下記コマンドでNATを設置?することで解決。

PS>> New-NetNat -Name VMNatNetwork -InternalIPInterfaceAddressPrefix 10.0.0.0/24

確認には、
PS >> Get-NetNat | fl *
Store                            : Local
TcpFilteringBehavior             : AddressDependentFiltering
UdpFilteringBehavior             : AddressDependentFiltering
UdpInboundRefresh                : False
Active                           : True
Caption                          :
Description                      :
ElementName                      :
InstanceID                       : VMNatNetwork;0
ExternalIPInterfaceAddressPrefix :
IcmpQueryTimeout                 : 30
InternalIPInterfaceAddressPrefix : 10.0.0.0/24
InternalRoutingDomainId          : {00000000-0000-0000-0000-000000000000}
Name                             : VMNatNetwork
TcpEstablishedConnectionTimeout  : 1800
TcpTransientConnectionTimeout    : 120
UdpIdleSessionTimeout            : 120
PSComputerName                   :
CimClass                         : root/StandardCimv2:MSFT_NetNat
CimInstanceProperties            : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties              : Microsoft.Management.Infrastructure.CimSystemProperties

しかし、問題が一つ。Windows側に置いておいた SQLiteのデータベースファイルに読むことはできても、変更(書き込み)することが一切できなくなっていた。どうやら仮想マシン上のPHP等から CIFS経由で変更しようとすると、ロックされてタイムアウトしてしまう事象が発生。

いろいろ調べた結果、どうやら 仮想マシンのCentOSからCIFS でホスト上の共有フォルダをマウントする際に、Byte range lock を無効しないとロックされてアクセスできないよー的な記事(ほとんど英語だらけの外国の方の記事ばっかりヒットする)を見つけ、下記のように /etc/fstab に記述すると解決できた。

/etc/fstab  -----

//10.0.0.1/Devel  /mnt/devel cifs user=nakagawa,password=xxxxxx,uid=nakagawa,gid=admin,nobrl,defaults  0 0

ポイントは、nobrl というオプション。これをつけるとバイト範囲のロックを無効にする・・・らしい。が、意味は分からんが、とりあえず、SQLiteファイルの変更中(書込み処理)ロックされることはなくなった。

めでたし、めでたし。

※追記)
Windows API の LockFile/LockFileEx とか、Linuxとかだとfcntl とか? で CIFSマウントされたディレクトリ内のファイルの「byte range lock」に対応していないってことなのかな・・・う~む?