ラベル 環境 の投稿を表示しています。 すべての投稿を表示
ラベル 環境 の投稿を表示しています。 すべての投稿を表示

2020/11/07

tmux 3.1c の window 分割線を ascii character にする

2020/10/30(Fri) に tmux 3.1c がリリースされました
という事で、恒例の EastAsianAmbiguous を ascii に変更したバージョンを作成します。
過去の作業履歴は 3.1b や 3.0a や 2.9a  に、そもそもの問題についてはこの記事にまとめています。


環境

  • OS: macOS Mojave 10.14.6
  • tmux: 3.1c-border-ascii 7e7a923b7cd2e7cc8d2450e8a8e20838ded13298
  • Homebrew: 2.5.8-118-g2ac5cff
    • Homebrew/homebrew-core (git revision ce1b1; last commit 2020-11-06)
  • Font: Ricty 4.1.1


インストール方法

  • $ brew install --HEAD atton/customs/tmux
でインストールできます。


今回の作業

 3.1b と 3.1c の違いはほぼ無いようなものなので、 cherry-pick で対応できました。

2020/06/09

GitHub Actions で複数の Dockerfile の build と DockerHub への push を自動化した

私は作成した Dockerfile を GitHub で公開しています(前回の記事の atton/webpage-title も含む)。
Docker Image を手動で管理するのは面倒なので、何らかの形で自動化する事にしました。
最終的に、 Dockerfile が更新された際に build して DockerHub に push する GitHub Actions を作成しました。


GitHub Actions を作成する際に考慮した条件

  • Dockerfile が増えた場合も自動で対応する(現時点では2つ)
  • Dockerfile や関連ファイルに更新が無い Image は Push しない
  • GitHub Actions だけでなく、ローカルの環境でも build できる


具体的な GitHub Actions の内容

作成した .github/workflows/build-and-push.yml とbuild.sh は以下です(commit: 427f143)。

自動化できたので手動 push の必要は無くなりました。べんり。

これ以降は作業ログなどを書いておきますが、かなり長いです。


第一条件: Dockerfile が増えた場合も自動で対応する

この条件については、特定の構成をしているディレクトリを build 対象にする事で対応しました。具体的には
  • ディレクトリ名は任意
    • ls と [ -d ] で確認
  • ディレクトリの直下に Dockerfile が存在する
    • ls と [ -f ] で確認
といったディレクトリです。なお、ディレクトリ名は Docker Image の tag を決める際に使っています。


第二条件: Dockerfile や関連ファイルに更新が無い Image は Push しない

Docker Image を自動 build する際、最初は elgohr/Publish-Docker-Github-Action@master を使っていました

ここで問題が発生。README.md を変更しただけの commit でも Docker Image の更新が行なわれました。
幸い、GitHub Actions の step では if が使えるようなので試してみましたが改善せず。
なので elgohr/Publish-Docker-Github-Action@master は利用しない方針に変更。
使わない事になりましたが、 entrypoint.sh に書かれた(docker login/logout など)内容は参考にできそうです。

さて、次は「Dockerfile や関連ファイルに更新が無い」事を判定をできれば解決しそうです。ググってみると
で確認できるとの事。ではこれを grep して exit code で判定すれば解決、しませんでした。
更新の有無に関わらず、全ての grep の exit code が 1 になっていました。
加えて、ローカル環境では想定通りの exit code が得られるので、どうやら原因は実行環境固有のようです。

「ローカルでは動くが、別環境では動かない」という悲しい事態なので、 printf debug で少しずつ状態を確認していきます。
  • git は存在するか
  • git の version は何か
  • git は実行できるか
  • remote origin は存在するか
  • commit log は辿る事ができるか
  • grep の version は何か
  • ...
結果、「actions/checkout@master を使うと repository の情報が消える(?)」事が判明しました。具体的には
  • git コマンドは実行できる
  • git show を行なうと、全ファイルが新規作成扱いになっている
  • origin を fetch しても commit が取得できない
という謎の状態でした。その為、 actions/checkout@master は利用せずに直接 git clone を実行。
clone した repository では diff-tree が実行可能で、更新の有無が判定可能になりました。


余談: 第二条件の部分を書いている時に思った事

  • elgohr/Publish-Docker-Github-Action@master のソースを確認すると、 action.yml に if はありませんでした。
    • Pull Request を作成して提案する手がある
  • 「ローカルでは動くが、別環境では動かない」
    • GitHub で動作 Image を提供している可能性がある
  • 「actions/checkout@master を使うと repository の情報が消える(?)」
    • 今は git clone で対応できるが、 branch の指定といったオプションに対応できない


第三条件: GitHub Actions だけでなく、ローカルの環境でも build できる

この条件は「ローカル環境でも Docker Image を作成可能」にする為につけました。メリットとしては
  • 問題発生時の再現に使用できる
  • commit 前の Dockerfile も試しに build できる
  • 新しい Image 作成時の build が楽
等があります。なお、この条件は build.sh に与える引数の有無で解決しました。


まとめ

結構な文量になりました。debug の説明を含めると長くなりますね。
結果的に「uses を排除して自前の run で記述する」というオレオレ GtiHub Actions で解決。
前回も書いた気がしますが、「個人的には十分満足しているので良しとします。」


参考文献や関連した文献など

2020/05/05

tmux 3.1b の window 分割線を ascii character にする

2020/05/04(Mon) に tmux 3.1b がリリースされました
という事で、いつも通り EastAsianAmbiguous を ascii に変更するバージョンを作成します。
過去の作業履歴は 3.0a や 2.9a や 2.8 に、そもそもの問題についてはこのこのポストにまとめています。


環境

  • OS: macOS Mojave 10.14.6
  • tmux: 3.1b-border-ascii 526f000f29abadeef9f804bb9aea5291b913a312
  • Homebrew:  2.2.15-2-gb06a7af
    • Homebrew/homebrew-core (git revision 0058c; last commit 2020-05-04)
  • Font: Ricty 3.2.2


インストール方法

  • $ brew install --HEAD atton/customs/tmux
でインストールできます。


本家との diff : utf8proc を使わない

しかし、 utf8proc は現時点の最新バージョンである 2.5.0 でも EastAsianAmbiguous 対応はされていません。
前回(2.3, 2.2.0)のように utf8proc を変更する選択肢もありました。
ですが、 tmux のソースを読むと utf8proc が無い場合 wcwidth を使うようなので、変更しない選択肢もありそうです。
試しに utf8proc を抜いてビルドした tmux を軽く触っても、特段違和感は無し。
とりあえず YAGNI の精神で、今回は utf8proc を使わない事にしました。


前回との diff : atton/tmux の default branch を master から border-ascii に変更

これは tmux へパッチを当てる運用方法の変更です。

ローカルで設定している remote repository は以下の2つ。
  • origin: atton/tmux
  • upstream: tmux/tmux
upstream を fetch して origin に反映させつつ、リリースがあれば対応するパッチを当てる、という運用でした。

ここで面倒だったのが、両方の master の使い分け。
例えば upstream/master の変更を origin/master に適用する時は
  • $ git fetch upstream
  • $ git checkout origin/master
  • $ git rebase upstream/master
と、prefix を指定する必要があります。それに加えて、紛らわしいのも改善したい。

そこで、atton/tmux の master は削除して default branch を border-ascii に変更
そしてローカルの tmux は master の remote tracking branch を upstrem/master に指定。具体的には以下のような感じ
  • $ git checkout master
  • $ git branch -u upstream/master
これにより master は tmux/tmux に追従し、他のブランチは atton/tmux に反映される、という状態にできました。


前回との diff : GitHub Actions の追加

GitHub Actions を2ヶ所で利用しています。

1ヶ所目は atton/tmux で、centos 環境で make 可能かチェックしています。
2ヶ所目は atton/homebrew-customs で、macOS 環境で make 可能かチェックしています。

GitHub Actions では mac と docker が使えるので、様々な環境下でテストできる点が良いですね。

2020/04/19

Homebrew で awscli を upgrade して、依存の keg-only python@3.8 を link する

Homebrew が提供する awscli が 2.0 になる前辺り、必要な python が python@3.8 になりました
awscli を upgrade する際、 python を消して python@3.8 を使うようにしたログです。


環境(ブログ作成時)

  • OS: macOS Mojave 10.14.6
  • Homebrew: 2.2.13-74-gecea0e5
    • homebrew-core (git revision eb6d; last commit 2020-04-19)
    • python: Python3.7.7
    • python@3.8: Python 3.8.2
  • awscli: aws-cli/2.0.8 Python/3.8.2 Darwin/18.7.0 botocore/2.0.0dev12


keg-only formula と Homebrew の install 事情

Homebrew は元々、 /usr/local/bin へ直接 formula を install しません。
/usr/local/Cellar などの PATH に install して、そこから symlink を貼ります。

その中で key-only formula は「install しても /usr/local/bin に link しない」 formula です。
今回は python@3.8 が keg-only に指定されています。理由として executable の衝突回避が挙げられます。
  • 前提として、現時点で Homebrew が提供している python は 3.7 系列
  • python が存在する環境に python@3.8 も installすると /usr/local/bin/python3 が重複する
  • /usr/local/bin/python3 を 3.7 系列に譲るために、 3.8 は keg-only として link しない
という感じかと思われます。


keg-only formula を link する前の確認

 link の前に、念の為 python が使われていないか、以下のコマンドでチェックします。
  • $ brew uses --installed python
何も出力されない場合は install 済みの formulas 全てにおいて python を使っていません。
出力がある場合、その formula は python を使っています。 3.8 の link は止めた方が良いでしょう。


python@3.8 を /usr/local/bin に link する

上記のチェック時、私の環境では出力が無かった為 python@3.8 を link する事にしました。
なお、 keg-only formula を link する場合は --force が必要です。
  • $ brew upgrade awscli
    • 依存関係で python@3.8 が install される
  • $ brew link --force python@3.8
  • $ which python3 aws
    • /usr/local/bin/python3
    • /usr/local/bin/aws
  • $ python3 -V
    • Python 3.8.2
  • $ aws --version
    • aws-cli/2.0.8 Python/3.8.2 Darwin/18.7.0 botocore/2.0.0dev12
これで python3 と awscli が upgrade できました。良し良し。
ちなみに homebrew-bundle では、 link: true を付けると link してくれます

2020/01/30

python2 に依存した Vim plugin が無いか確認と修正対応をしたお話

2020/01/01(Wed) に python2 のサポートが終了しました。が、今の所私の周辺で問題は発生していません。

Neovim で :checkhealth を実行していると、まだ python2 provider が有効な事にふと気付きました。
「いつか python2 provider も消えるのだろうな」と悠長に考えたのが1つ目の感想。
「python2 に依存した plugin があったらマズいのでは」と思って焦ったのが2つ目の感想。
「問題は発生していない」と思っているけれど、本当にそうなのか念のために確認+対応したログです。


環境

  • OS: macOS Mojave 10.14.6
  • Neovim: 0.4.3
  • Python2: 2.7.16 (system builtin)
  • Python3: 3.7.6 (installed by homebrew)


has('python') している plugin が無いか確認

私は Neovim の plugin management に dein を使っています。
そして、plugin の install 先は ~/.config/nvim/dein を指定しているので、その先に cd して grep をかけてみます。
  • $ cd ~/.config/nvim/dein/repos/github.com
  • $ egrep 'has\(.python.\)' -R .
egrep のオプションの -R は、指定したディレクトリを起点に recursive に探索してくれます。
そして、渡しているディレクトリは '.' なので、 カレントディレクトリ以下の全てのファイルを対象にできます。

egrep で指定した正規表現は 'has\(.python.\)' です。これは
  • まず、 vim/neovim で特定の feature が有効か確認する方法として 'has' function があります。
  • そして python2 provider が有効かどうかは has('python') の実行結果で分かります。
  • 加えて考慮する事として、python を括る文字が ' と " のどちらかの問題があります。
    • これは面倒なので . にしました。 ['"] 2つなどでもOKです。
  • 最後に、'()' は egrep パターンマッチに使う記号なので \ でエスケープします。

さて、実行結果は以下のようになりました。
前後のソースを読んではいないので、 現段階では対応が必要かもしれない plugin 一覧とします。


一時的に python2 provider を無効にする

Neovim で :help provider とすると、各 provider の説明が確認できます。
その中には provider を無効化する方法も存在しており、 python2 の場合は
  • let g:loaded_python_provider = 0
と ~/.config/nvim/init.vim に書くと無効化できます。

なお、この状態で :checkhealth を実行すると
  • - INFO: Disabled (g:loaded_python_provider=0).
と表示されます。

さて、これで仮に python2 provider が消えた時状態を再現できました。
先程 egrep で見付けたプラグインの動作確認を行なった結果、
が動作しませんでした。


VimCalc 対応: VimCalc -> VimCalc3

安直に「VimCalc python3」で検索をかけてみます。
そうすると、fedorenchik/VimCalc3 が見付かりました。なお、 fork 元は本家の gregsexton/VimCalc です。
お試しでインストールすると、ほぼ同じ動作。ということで VimCalc3 に乗り換えます。


gundo.vim 対応: let g:gundo_prefer_python3 = 1

さて、二度目も安直に「gundo.vim python3」でググります。
そうすると bitbucket の issue のページがヒットしました。どうやら既に対応済みだったらしく
  • let g:gundo_prefer_python3 = 1
と書くことで python3 を利用するようです。動作確認もできたので、 gundo.vim はそのまま使う事にします。


まとめ

これで Neovim がいつ python2 provider を消しても大丈夫になりました。

蛇足ですが、対応した2つのプラグインは利用頻度が低く、 LazyLoad していました。
なので、仮に Neovim が python2 provider を消したとしても、気付くのに時間がかかった可能性は十分にあります。
それを排除できたので、備えあれば何とやら、ですね。

2019/12/21

tmux 3.0a の window 分割線を ascii character にする

2019/12/01 に tmux  の version 3.0a がリリースされました
いつも通りに分割線を multibyte character から ascii にする作業をします。
過去の作業ログは 2.9a や 2.8 や 2.7 など。そもそもの問題についてはこの記事にあります。


環境



インストール方法

  • $ brew install --HEAD atton/customs/tmux
でインストールできます。


今回の変更

tmux は window や pane を表示するための文字情報を tty-acs.c に持っています。
なので、毎度この定義を修正する事で対応しています。
2.9a の時等は tty-acs.c に変更が無かった為、過去の commit の cherry-pick のみで目的が達成できました。
が、今回は修正が入っているので cherry-pick をすると conflict します。
conflict を解消する形で対応しても良いのですが、今回は新しく修正用の commit を作ることにしました。

過去のパッチ を参考にすると、置換が必要な文字とその対応関係は
  • j,k,l,m,n,t,u,v,w が "+"
  • x が "|"
  • q が "-"
  • ~ が "*"
のようです。これらを元に tty-acs.c を修正。make すると今まで通り動きました。
もちろん後から何か踏む可能性はありますが、今の所問題は発生していません。
ということで tmux のソースコードの更新は以上。
あとは branch 名を homebrew の atton/customs 用に付けてあげればおしまいです。

formula の更新は本家 tmux の --HEAD 版の定義を借りて、branch 名を指定すればOK。

と、いうことで tmux 3.0a-border-ascii の更新ログでした。


おまけ

分割線の定義を間違えると、分割した瞬間に tmux が crash します。こわい。
きちんと定義できれば以下のように割りたい放題しても動きます。


2019/09/21

git clean を使って untracked なファイルを削除する

Mercurial には hg purge というコマンドがあって、 hg で control していないファイルを一括削除できます。
具体的には add してないファイルとか、.c から作った .o とか、間違って作った Rails の migration とか。
それを Git でもできないかなー、と調べたメモ。


環境

  • OS: macOS Mojave 10.14.6
  • Git: 2.23.0


git clean

hg purge のようなコマンドは Git にも default でも存在していて、git clean だそうです。

untracked なファイルを消す際は
  • $ git clean -fd
とかすると add してないファイルが消えます。

あとは、すぐに消すのではなく、消す対象が何かを教えてくれる -n (--dry-run) option が便利です。
  • $ git clean -fdn
で削除対象一覧を出してくれます。ちなみに
  • git clean -f -d -n
と書いても良いみたいです。

他には 
  • -X option: .gitignore で指定されたファイルのみを消す
    • .o とかが消えてくれる。
    • あと untracked なファイルは消えない
    • 新規にファイルを作った上で rebuild したい時に便利だよ、とのこと
  • -x option: .gitignore で指定されたファイルも削除対象 + untracked のファイルも削除対象
    • かなり危険なので事前に dry-run を付けた方が良いです
    • git clean -fdx とかすると clone 直後くらい綺麗な状態になります
とかですかね。
さらに詳細を知りたい場合は man git-clean を読んで頂ければ。


参考

2019/09/01

neovim で plugin を利用せずに sudo を使う

root 権限が必要なファイルを neovim や vim で編集する事があると思います。
その際、 sudoers で許可されているユーザならば
  • :write ! sudo tee % > /dev/null
で sudo を使って root として書き込むことができます。

ですが、 neovim では
  • :write ! sudo tee % > /dev/null
    • sudo: no tty present and no askpass program specified
    • shell returned 1
と言われて sudo が使えません。


解決策

以下のようなコマンドを定義することで対応できます。 このコマンドは vim と neovim の両方で利用できます。

vim で利用する場合は ~/.vimrc に追記します。
neovim で利用する場合は ~/.cofig/nvim/init.vim に追記します。


使い方

  • $ nvim /etc/hosts
    • root 権限が必要なファイルを開いて編集します。保存の際は
  • :SudoWriteCurrentBuffer
    • を実行します。
    • パスワードを入力すれば root で書き込む事ができます。


動作確認をした環境

大元の環境(vim と neovim で動作確認済)
  • OS: macOS Mojave 10.14.6 (18G95)
  • Homebrew: 2.1.11
    • Homebrew/homebrew-core: (git revision 883ee; last commit 2019-09-01)
  • neovim: v0.3.8
  • vim: 8.0.1365
  • sudo: version 1.8.17p1
    • Sudoers policy plugin version 1.8.17p1
    • Sudoers file grammar version 45
    • Sudoers I/O plugin version 1.8.17p1
  • docker: 19.03.1, build 74b1e89

    docker を使っていくつかの distribution でも動作を確認
    • Alpine linux: 3.10.2
      • neovim: v0.3.7
      • vim: 8.1.1365
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • CentOS: release 7.6.1810 (Core)
      • vim: 7.4.1099
      • sudo: version 1.8.23
        • Sudoers policy plugin version 1.8.23
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.23
    • Fedora: release 30
      • vim: 8.1.1912
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27
    • Ubuntu: 18.04.3
      • vim: 8.0.1453
      • sudo: version 1.8.21p2
        • Sudoers policy plugin version 1.8.21p2
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.21p2
    • Debian: 10.0 (buster-20190812)
      • vim: 8.1.1401
      • sudo: version 1.8.27
        • Sudoers policy plugin version 1.8.27
        • Sudoers file grammar version 46
        • Sudoers I/O plugin version 1.8.27


    何故 neovim では sudo が使えないのか

    ここから先は先程の Vimscript を作るに至った経緯を書きます。
    興味のある方はご覧ください。

    まず sudo の error message
    • sudo: no tty present and no askpass program specified
    を見ると、 tty と askpass が無いと言っています。


    tty と askpass

    実際、vim では
    • : ! tty
      • /dev/ttys004 
    などが得られますが、 neovim では
    • : ! tty
      • not a tty
      • shell returned 1
    と言われてしまいます。

    askpass は使ったことが無いのですが、fedora の container で dnf search すると
    の様に、いくつかの askpass が確認できます。のでちょっと試してみます。
    • x11-ssh-askpass
    • openssh-askpass
    • ksshaskpass
    という感じで全然起動してくれません。
    ですがエラーの内容的に display を開こうとしているのが分かります。
    なので、おそらく GUI で password を聞くような物だと思われます。


    askpass を作る

    askpass について調べていると、どうやら
    • password を stdout に出力するもの
    であることが分かりました

    よって
    • neovim 内で password を取得
    • password を stdout に出力する
    • password の履歴はどこにも残さない
    ようなものを作れば解決できそうです。

    それで完成したのが /tmp/askpass を作るこの Vimscript です。

    本当はファイル名は固定でなく tempfile 的な物で対応するなど、改善点はいくつも存在するかと思います。
    ですが私は Vimscript に明るくないので、"3つの条件を満たして動けばOK" という条件で作成しました。
    他により良い対応方法があればご指摘頂けると幸いです。


    その他の解決策

    調べた結果、 suda.vim というプラグインがあるようです。
    また、他にも sudo.vim など、似たようなプラグインはいくつかあるらしいです。

    これを使わなかった理由としては
    • docker のコンテナ内で作業をする事が多々ある
    • init.vim を配置するスクリプトは既にある
    • plugin を install するスクリプトはまだ無い
    • 全コンテナに plugin を入れるのも面倒だし結構サイズがある
      • $ du -sh ~/.config/nvim/repos
        • 100M    /Users/atton/.config/nvim/repos
    などがあります。

    また、"sudo が使えるならこの際 root になってしまう" という解決策もあるのですが
    • 前述した理由の後半3つ
    • 複数人数のユーザが使う環境だと、 /root 配下に自分専用の設定を置くことになる
    のでこちらも無しで。

    他には、 "sudoers で NOPASSWD を設定する" という解決策もあります。
    が、sudo を no password でガンガン使えば実質 root で作業しているのと変わらず、危険すぎるのでこちらも無し。

    ということでこの Vimscript を書くに至った、という訳なのです。


    おまけ: 環境変数の unlet

    スクリプト内部では askpass の場所を示す SUDO_ASKPASS を設定している部分があります。
    具体的には
    • let $SUDO_ASKPASS  = s:askpass_path
    ですね。

    この環境変数を定義していると、 sudo -A した際に指定したファイルが実行されます。
    一応、 :SudoWriteCurrentBuffer の実行後にはなるべく元の環境に戻すために
    • unlet $SUDO_ASKPASS
    を書いていた時もありました。

    ですが動作確認中、 Vim 8.0.1365 で unlet 時にエラーが出てしまいました。
    また 、-A を指定しなければ sudo の動作は変わらないので 、残っていても無害と判断して unlet しない形になりました。


    おまけ: shebang を指定しないとどうなるのか

    ちなみに askpass の shebang を消すと
    • sudo: unable to run /tmp/askpass: Exec format error
    • sudo: no password was provided
    と言われる為、きちんと書いておく必要があります。


    おまけ: x flag を付けないとどうなるのか

    setfperm(s:askpass_path, "rwxr-xr-x")  をせずに 644 のままだと
    • sudo: unable to run /tmp/askpass: Permission denied
      • sudo: no password was provided
      と言われるので、こちらもきちんと指定しておく必要があります。


      参考

      2019/08/29

      tmux 2.9a の window 分割線を ascii character にする

      2019/05/01 に tmux 2.9a がリリースされていました
      残念ながら 2.9 は見逃がしてしまいました。
      ということで恒例の分割線を EastAsianAmbiguous から ascii の線に変更するバージョンを作成。
      2.8の時とか2.7 の時とかの作業履歴とかもまとめてあります。
      そもそもどういう問題なのかはこの記事で。


      環境

      • OS: macOS mojave 10.14.6 (18G95)
      • tmux: 2.9a-border-ascii ( f976aed943f322a3652f51846b0fe472534ab6d6 )
      • Homebrew: 2.1.11
      • Homebrew/homebrew-core: (git revision 269c; last commit 2019-08-29)
      • Font: Ricty: 3.2.2(no option)


      作業

      今回も割とあっさりできました。cherry-pick して tag 更新して終わり。
      • $ git pull upstream
      • $ git checkout 2.9a
      • $ git cherry-pick border-ascii
      • $ git checkout -b 2.9a-border-ascii
      make できるかの確認は
      • $ sh autogen.sh
      • $ ./configure 
      • $ make
      で。

      ちなみに brew edit tmux して本家のビルド手順を参考にしてます。
      あと、 dependencies から utf8proc が消えて ncurses が追加。

      make すると current directory に tmux command ができるので、動作確認も可能。
      • $ ./tmux -V
        • tmux 2.9a
      • $ ./tmux
        • border-ascii 版の tmux が起動します。
      あとは自分用の tap に反映しておしまい。


      インストール方法

      1からインストールする場合のコマンドは
      • $ brew install --HEAD atton/customs/tmux
      でいけます。
      必要あらば自動で atton/cusoms を tap してくれるようになってました。便利。

      2019/08/13

      nodenv を使って複数のバージョンの Node.js を管理する

      プロジェクト毎に指定の Node.js のバージョンがあったり、常に最新の Node.js を使いたかったりすると、Homebrew だけで管理するのは面倒になってきます。

      今回は nodenv を使って Node.js の環境を作ろうと思います。
      ちなみに私は Ruby では rvm より rbenv 派。
      なので nvm よりは nodenv かな、と。

      環境

      • OS: macOS Mojave 10.14.6
      • zsh: 5.7.1
      • Homebrew: 2.1.9
      • Homebrew/homebrew-core (git revision 2548c; last commit 2019-08-11)
      • nodenv: 1.3.0
      • node-build: 4.6.3


      インストール

      • $ brew install nodenv
      • $ nodenv init
        • eval "$(nodenv init -)"
        • を .zshrc に追加せよ、と言ってきますので追記
      • $ nodenv install 12.8.0
        • とかで好きなバージョンを指定
      • $ nodenv global 12.8.0
        • とかで通常使用するバージョンを指定できます。
      • $ nodenv local 12.7.0
        • とかで特定ディレクトリの下で使用するバージョンを指定します。
        • 具体的には .node-version というファイルが作られて、そこにバージョンが書かれる。


      nodenv init をちょっと追ってみる

      ちなみに zsh 上で
      • $ nodenv init -
      とすると


      のような設定がされることが分かります。つまり、
      • executables がある PATH を追加する
      • NODENV_SHELL の設定
      • 補完スクリプトを source
      • nodenv rehash (executables の再配置)
      • nodenv の wrapper
        • rehash と shell の両コマンドは特別扱い(eval する感じ)みたいですね
        • 興味がある人はさらに読んでみても良いかと思います。

      nodenv init と shell 指定

      rbenv を設定していた時に見つけたのですが、特定の shell であることを指定することもできます。
      具体的には $SHELL が zsh の状態でも
      • $ nodenv init - bash
      とすると

      のような、bash 向けの設定が生成されます。
      nodenv init - zsh と具体的に違うのは NODENV_SHELL と補完スクリプトの場所くらい。
      zsh で bash の設定を読み込むなんてことはほぼ無いと思うので、 nodenv init - で問題無いと思います。


      nodenv rehash

      ちなみに zshrc に nodenv init - が記述される訳ですから、シェルを立ち上げる度に nodenv init - が実行されます。
      気持ち程度の問題だとは思いますが、 rehash を省略するオプションがあって
      • $ nodenv init - --no-rehash zsh
      とすると nodenv rehash が実行されません。

      とはいえ普通はこのオプションのある無しで実行時間はほとんど変わらないです。
      大量に package を入れたバージョンから新バージョンに上がった直後とかなら rehash にコストがかかるかも? 程度

      とりあえず、私は .zprofile には rehash 無しの init script を書いてます。
      それで、npm install -g とかしたら手で nodenv rehash を打つ、という運用をしています。

      2019/06/03

      utf8proc が 2.3 から East Asian Ambiguous の文字幅を 2 と判定するようになった

      Homebrew でインストールできる tmux は文字幅判定の方法をいくつか持っています。
      その中に utf8proc というソフトウェアに任せる、という方法があります。
      しかし、その utf8proc は East Asian Ambiguous の幅を固定で 1 にするよう実装していました。
      なので、自分用に patch を当てた formula を作ったりして対応していました。

      ですが、utf8proc 2.3 から East Asian Ambiguous を 2 と判定する用になりました。
      とりあえず自分が使っている patched 2.8 な tmux では問題無さそうなので公式の utf8proc を使うようにします。

      蛇足
      本当は LC_CTYPE を見て動的に判定する、という実装が理想っぽいですが流石にそこまではしてもらえないようです。

      2019/02/20

      zsh で c flag を指定すると .zshrc が読み込まれない

      .zshrc に定義している function f を zsh -c 'f' 等で実行したいが、 f が無いとエラーが発生する。
      なお、Terminal.app から起動した zsh では f は実行可能。


      結論

      function を .zshrc ではなく .zprofile に書いて zsh -l -c 'f' とする。(もしくは zsh -lc 'f')


      zsh の -l option について

      -l option は LOGIN option (man zshoptions)で、login shell として zsh を起動する。
      何も指定しない場合と異なり、設定ファイルをいくつか読み込む。その中に .zprofile が含まれている。


      .zprofile と .zshrc の読み込まれるタイミング

      • .zprofile: login 時に読み込まれる
      • .zshrc: terminal session が発生した時に読み込まれる
      との事。つまり、 zsh -c では .zprofile も .zshrc も読み込まれない。
      そこに -l を追加して .zprofile が読み込まれるようにする。そこに function を書けば良い。


      環境

      • OS: macOS Sierra 10.12.6
      • zsh: 5.7.1 (x86_64-apple-darwin16.7.0)

      2019/01/23

      EastAsianAmbiguous の幅を2に固定した utf8proc のバージョンを 2.2.0 に上げた

      さて、今私が使っている tmux は

      ようにしています。
      が、 utf8proc 側の更新は何気に初ですね。


      How to version up

      brew で tap 済みなら
      • $ brew upgrade
      で終わりです。丁寧に再インストールするのなら
      • $ brew uninstall utf8proc
      • $ brew install atton/customs/utf8proc
      でしょうか。便利。


      脱線: 楽をするための苦労の話

      brew で install できるようにするまでで一番面倒だったのが環境構築。
      なのですが、関連ファイルの生成は結構面倒。
      www.unicode.org から Unicode の定義ファイルを落としてきてスクリプトで処理とかしているので。
      スクリプトには ruby とか julia とか使われてるので微妙に mac の上に作るのはダルい。
      今回は docker で fedora 28 の上に使い捨ての環境を作って解決。

      fedora 29 だと julia が新しすぎてダメとか、CentOS7 にはデフォルトで julia が無かったりとか、寄り道はいろいろ。
      最終的には fedora 28 の上に call-by-need で環境を作って patch を cherry-pick して make update をかけて終了。
      brew の formula 回りは tmux で何度も触ってるので特筆すべきことは発生せず。
      途中であった謎現象としては www.unicode.org 自体が落っこちていて make update が上手くくいかない事がありました。
      何度も make してスパム判定されたとかなのかもしれない。

      2018/10/31

      tmux 2.8 を全角記号対応させる

      ということで恒例の分割線を EastAsianAmbiguous から ascii の線に変更するバージョンを作成。
      2.7 の時とか 2.6 の時とかの作業履歴とかもまとめてあります。
      そもそもどういう問題なのかはこの記事で。


      環境

      • macOS Sierra 10.12.6
      • tmux: 2.8-border-ascii (4283f6b6e3f3c46b8665ce398a164063a7ef0aab)
      • utf8proc: 2.1(562edab805b82d66622914d06a5da3f53cd54a17)
      • Homebrew: 1.8.0-76-gcbb2e1b
      • Homebrew/homebrew-core: (git revision 95614; last commit 2018-10-30)
      • Ricty: 3.2.2(no option)


      作業

      今回は割とあっさりできました。cherry-pick して tag 更新して終わり。
      • $ git pull upstream
      • $ git checkout 2.8
      • $ git cherry-pick border-ascii
      • $ git checkout -b 2.8-border-ascii
      くらい。

      make できるかの確認は
      • $ sh autogen.sh
      • $ ./configure --enable-utf8proc
      • $ make
      くらいで。

      current directory に tmux command ができるので、動作確認とかもできます。
      • $ ./tmux -V
        • tmux 2.8
      • $ ./tmux
        • border-ascii 版の tmux が起動します。
      あとは自分用の tap に反映しておしまい。


      インストール方法

      1からインストールする場合のコマンドは
      • $ brew tap atton/customs
      • $ brew install atton/customs/utf8proc
      • $ brew install --HEAD atton/customs/tmux
      でいけます。


      ぼやき

      これで分割時の線が ascii になりました。良し良し。

      自分用にメンテし続けてるけれど、tui を使う時とかはどうしても崩れてしまう。
      特定の文字を表示する時かけられる hook があれば、置換表を config に書くと tui も問題無く表示できるとは思うのだけれど、そんなの無いかなー。

      2018/07/22

      Docker Registry の backup と restore

      前回は Image の Backup/Restore について書きました。
      これで Image を指定してバックアップ可能になったのですが、Registry に登録される Image が1つとは限らない。
      ということで Docker Registry ごと全イメージをバックアップしてみる。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      Docker Registry を tar にする

      さて、Registry はコンテナ内部に登録イメージのファイルを持ってます。
      ファイルごとバックアップを取りたいので、戦略としてはコンテナのバックアップを取る。
      今度使うのは docker export コマンド

      • $ docker run -d -p 5000:5000 --name registry registry:latest
      • $ docker push hogehoge
      • $ docker export registry > registry-backup.tar
      これで Registry のコンテナが tar ファイルになります。


      Docker Registry を復元する

      さて、 tar ファイルから復元したいと思います。
      • $ docker import - registry:latest < registry-backup.tar
      今回はタグの情報とかは無いので自分で指定する。
      というかコンテナからイメージを作るので実質 docker commit みたいなものか。

      tar から作られた registry:latest を実行します。
      • $ docker run -d -p 5000:5000 --name registry registry:latest
      お? 動かない。 
      /usr/bin/docker-current: Error response from daemon: No command specified.
      と言ってくる。CMD の情報が吹っ飛んでるのか。
      Github にある Registry の Dockerfile を見ると、'docker-registry' とすれば良いかな。
      • $ docker run -d -p 5000:5000 --name registry registry:latest docker-registry
      動かない。今度は
      /usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"docker-registry\": executable file not found in $PATH
      か。そんなコマンドは無いらしい。 
      もうコンテナ内に入ってしまうかな。export 前の registry に対して
      • $ docker exec -it registry bash
      すると
      rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "exec: \"bash\": executable file not found in $PATH"
      おお、bash すら無いのか。sh も無ければ最早 user interactive に何もできないコンテナだ。

      • $ docker exec -it registry sh
      流石に sh はありました。find もある。
      find で docker-registry を探しても無い。
      他に探索していると registry というのが /bin/registry にあった。
      実行すると serve か garbage-collect と help がサブコマンドにある。serve してみます。
      • $ registry serve
      文句言ってきました。具体的には
      configuration error: configuration path unspecified
      と。 docker-registry の configuration path って何だろう。
      どこかに mount してたらそれを参照してくれるから設定変更可能、とかそういう意図なんだろうか。

      とかとか、いろいろ試した結果、ps で path が分かりました。
      Process ID 1 のやつが
      registry serve /etc/docker/registry/config.yml
      で動いていました。
      と、いうことで、実行するコマンドは
      $ docker run -d -p 5000:5000 --name registry registry:latest registry serve /etc/docker/registry/config.yml
      で Import した Registry を復元できました。やったね。


      おまけ

      /etc/docker/registry/config.yml を読むと storage.filesystem.rootdirectory が /var/lib/registry
      だったので、run する時に -v で /var/lib/registry に Host の Directory を mount しておけば Image の保存が楽だった説が。

      それと、Docker EE だと、 DTR (Docekr Trusted Registry) の backup/restore 手順が提供されています
      きちんとサポートを受けたい場合は Docker EE を使うのもアリかも。


      参考

      2018/07/15

      Docker Image の backup と restore

      さて、Docker Registry を立てたは良いものの、マシンが壊れたりすると悲しい事態になります。
      Build 元と Registry で二重になってはいるのですが、両方が同じマシンだと悲しい事態が発生する可能性がありますね。
      と、いうことで Build した Docker の Image をファイルに書き出したり、そのファイルからイメージを復元します。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Docker: version 1.13.1, build 774336d/1.13.1
      • Kernel: 3.10.0-693.5.2.el7.x86_64


      Docker Image をファイルへバックアップする

      Docker そのものはファイル群を /var/lib/docker の下に持ってます。
      Image は default だと overlay2 で作成されます。
      overlay2 は差分でファイルを管理するファイルシステムなので、そういったメタ情報もバックアップしないといけない。
      つまりは cp とか rsync だと事故る可能性があります。

      さて、何を使うのが正しいかと言えば公式です。具体的には docker save コマンド
      Image を構成する全レイヤをきちんと tar に書き出してくれます。
      実行例として、hogehoge Image をバックアップするのはこんな感じ。
      • $ docker image save hogehoge > backup.tar
      この tar をバックアップ先 HDD 等に持っていけば良い。


      Docker Image をファイルから復元する

      バックアップする方法は分かりました。
      次はバックアップからの復元。
      docker load コマンドを使います。具体的には
      • $ docker image load < backup.tar
      で終わり。
      Image の repository name や tag も tar に入っているので、それらの情報も全部復元されます。楽。


      参考

      2018/06/17

      Mac に fontforge を直接入れずに Docker を使って Ricty を作成する

      私は普段 Terminal で作業する時、フォントは Ricty を使っています。
      Ricty は Inconsolata と Migu 1M の合成フォントで、生成スクリプトが公開されています。
      合成には fontforge を使うのですが、 brew で入れると結構な数の依存パッケージが入ります。
      fontforge  は普段使いしていないので、おそらく Ricty の生成以外に使わない。
      なので Mac に直接 fontforge を入れず、コンテナに入れて合成してみます。


      環境

      • OS: macOS Sierra 10.12.6
      • Docker for mac: 18.03.1-ce, build 9ee9f40
        • Distribution: CentOS Linux release 7.4.1708 (Core)
        • fontforge: 20120731
      • Ricty: 4.1.1
        • Inconsolata: v2.001
        • Migu 1M: 20150712


      mac 側の事前準備(ダウンロード)

      事前にダウンロードが必要なのはフォント2つ。
      具体的には Inconsolata と Migu 1M の .ttf ファイルです。
      加えて、Ricty の生成スクリプト ricty_generator.sh もダウンロードしておきます。
      Migu 1M は unzip して、とりあえず全ファイルを ~/Downloads へ mv。

      最終的な ~/Downloads はこんな感じになりました。
      $ ls Downloads
      Inconsolata-Bold.ttf  Inconsolata-Regular.ttf  ipag00303  migu-1m-bold.ttf  migu-1m-regular.ttf  migu-README.txt  mplus-TESTFLIGHT-060  ricty_generator.sh


      Docker に ~/Downloads を mount して合成

      さて、合成に必要なファイル群は ~/Downloads に集まりました。
      これを mount したコンテナを立ち上げて合成します。

      具体的なコマンドはこんな感じ。run に渡す用のスクリプトを書いた方がスマートかも。
      • $ docker run -v ~/Downloads/:/root/fonts -it centos:7
        • # yum install -y fontforge
        • # cd /root/fonts
        • # chmod u+x ricty_generator.sh
        • # ./ricty_generator.sh -n 4.1.1 Inconsolata-{Regular,Bold}.ttf migu-1m-{regular,bold}.ttf
      生成されたフォントにバージョン番号を付けておきたいので、 "-n 4.1.1" オプションを指定しておきます。
      実行した結果、~/Downloads はこんな感じになりました。
      $ ls ~/Downloads
      Inconsolata-Bold.ttf Inconsolata-Regular.ttf Ricty4.1.1-Bold.ttf Ricty4.1.1-BoldOblique.ttf
      Ricty4.1.1-Oblique.ttf Ricty4.1.1-Regular.ttf Ricty4.1.1Discord-Bold.ttf
      Ricty4.1.1Discord-BoldOblique.ttf Ricty4.1.1Discord-Oblique.ttf Ricty4.1.1Discord-Regular.ttf
      ipag00303 migu-1m-bold.ttf migu-1m-regular.ttf migu-README.txt mplus-TESTFLIGHT-060
      ricty_generator.sh
      きちんと生成されていますね。良し良し。

      2018/06/10

      Docker Universal Control Plane を CentOS7 で起動してみる

      前回の記事では CentOS7 に Docker EE を入れました
      さて、何故入れたかと言えば Docker Universal Control Plane(UCP) を使ってみたかったからです。

      Unix User を dockergroup に所属させることで、複数のユーザが root でなくても docker を利用できます。
      しかし、他人が run した container に attach 可能。場合によってはよろしくない。
      何か解決策が無いかと調べたところ UCP を見付けました。

      UCP には Permission Control があって、Full Control の権限をユーザに与えても
      The user can view and edit volumes, networks, and images, They can create containers without any restriction, but can't see other users' containers.
      とのことで、別のユーザのコンテナは見られない。
      なので、root でない複数ユーザが、相互に干渉せず docker を使えそうです。


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Kernel: 3.10.0-693.5.2.el7.x86_64
      • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64
      • Docker Universal Control Plane: 2.2.6


      run UCP

      公式の document に従って UCP のイメージを run します。
      • $ docker image pull docker/ucp:2.2.6
      • $ docker container run --rm -it --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --host-address 127.0.0.1 --interactive
        • --interactive が付いてるので適宜入力します
        • 具体的には Admin username や password とかですね
      さてこれで起動……しません。
      INFO[0000] Initializing a new swarm at 127.0.0.1     
      FATA[0034] the following required ports are blocked on your host: 12385, 12376, 12383, 443, 12384, 12379, 12387, 12386, 12381, 12382, 2376, 12380.  Check your firewall settings 
      と言われました。おお、結構な数の port 使うな。

      ということで firewall に穴を開けます。
      • # for i in 12376 4789 12386 2376 443 12381 12380 12382 12383 12384 12385 12379 12387 ; firewall-cmd --add-port=$i/tcp --permanent
      • # firewall-cmd --reload
      くらいかな。

      そして再度 run してみる。今度は
      FATA[0031] The following required ports are already in use on your host - 2377.  You may specify an alternative port number to 2377 with the --swarm-port argument.
      と言われた。あれ。何が 2377 使ってるんだ?
      • $ netstat -lntp
      すると確かに 2377 が listen になってる。 process name は dockerd か。

      結論から言うと、一回目で起動した swarm が生きてたのが原因でした。なので
      • $ docker swarm leave --force
      して抜ける。さて三度目のトライ。コマンドは変わらず
      • $ docker run -it --rm --name ucp -v /var/run/docker.sock:/var/run/docker.sock docker/ucp:2.2.6 install --interactive
      で実行します。お、起動したっぽいですね。三度目の正直。
      INFO[0007] Generating UCP Client Root CA
      INFO[0007] Deploying UCP Service
      INFO[0035] Installation completed on raven (node abcdefghijklmnopqrstuvwxy)
      ...
      INFO[0035] Login to UCP at https://127.0.0.1:443
      https//127.0.0.1 にアクセスすると UCP の画面が出てきました。ログインも可能。良し良し。


      参考

      2018/06/03

      Docker EE を CentOS 7 に install する

      Enterprise Edition の Docker を CentOS 7 に入れてみたのでそのメモ


      環境

      • OS: CentOS Linux release 7.4.1708 (Core)
      • Kernel: 3.10.0-693.5.2.el7.x86_64
      • Docker: docker-ee-17.03.0.ee.1-1.el7.centos.x86_64


      yum-config-manager --add-repo

      まずは公式のドキュメントに従います。
      Enterprise Edition の Docker は無料では使えないので、 subscription を買う必要があります。
      なのですが、一ヶ月無料お試しもできるので、s

      trial が始まるとユーザアカウント固有の URL が貰えます。
      • $ export DOCKERURL="<DOCKER-EE-URL>"
      のところですね。ちなみに具体的なURL は
      • $ export DOCKERURL='https://storebits.docker.com/ee/centos/<uuid>'
      でした。たぶん uuid は user ごとに違いそうなのでここには書きません。

      DOCKERURL も分かったので、後は公式ドキュメント指示通りに続けます。
      • $ sudo -E sh -c 'echo "$DOCKERURL/rhel" > /etc/yum/vars/dockerurl'
      • $ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
      • $ sudo yum -y install docker-ee
      でインストール……されないですね。
      [Errno 14] curl#6 - "Could not resolve host: storebits.docker.com; Unknown error"
      と言ってきますが、 dig では storebits.docker.com は返ってくる。謎。


      DOCKERURL

      結論から言うと、 DOCKERURL が間違っていました。
      RHEL のドキュメントの DOCKERURL は
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/rhel/docker-ee.repo"
      ですが、store.docker.com から提供された URL は
      • https://storebits.docker.com/ee/centos/<uuid>
      なので、どうも帳尻が合っていない。
      いろいろ試した結果、 CentOS 用のキュメントは RHEL とは別にありました。
      おお、そこまで区別してるのか。 sensitive だ。

      ということで CentOS 用のドキュメントに従って
      • $ sudo -E yum-config-manager --add-repo "$DOCKERURL/centos/docker-ee.repo"
      • $ sudo yum -y install docker-ee
      で Install できました。良し。


      おまけ: docker-ee.repo

      ちなみに DOCKERURL をブラウザで開くとファイル一覧が見られます。
      ちょっと見た結果 yum の repo と rpm が置かれていました。
      にしても、 yum の repo の仕様なのか、 docker-ee.repo が
      • DOCKERURL/docker-ee.repo
      • DOCKERURL/centos/docker-ee.repo
      みたいに2つあって、どっちが正しいのか悩んだり。両方とも正しい可能性もあるな。



      参考

      2018/05/27

      Oracle Java SE 8 JDK を CLI で Install する

      さて、Java を CLI でインストールしたい時があります。
      例えば Docker の Image を作る時などですね。 Dockerfile に書きたい。
      OpenJDK ならば yum や apt-get で Install できるのですが、Oracle の JDK だとそうはいかない。
      なので、作業ログを残しておこうかと思います。


      環境

      • macOS Sierra: 10.12.6
      • Docker for mac: version 18.03.0-ce, build 0520e24
      • Base Image: ubuntu:16.04
      • Oracle JDK: 1.8(build 1.8.0_161-b12)


      ppa:webupd8team repository

      Oracle JDK を公式のサイトから落っことしてきても良いのですが、zip と rpm しか無い。
      Ubuntu の dpkg で install したいので deb ファイルが欲しい。
      どうも調べてみると、 apt の追加 repository にあるらしい

      ので追加して Install してみる。
      • apt-get install -y software-properties-common # install apt-add-repository command 
      • apt-add-repository -y ppa:webupd8team/java
      • apt-get update
      • apt-get install -y oracle-java8-installer
      License に同意するか聞かれるので yes 。そうしたら Install される。


      License Agreement with debconf

      License に同意する部分には stdin に yes と入れたら済むだろう、ということでやってみる。
      • yes yes | apt-get install -y oracle-java8-installer
      ところが上手くいかない。
      apt-get が license を表示するやつ(自前かlessか?)に stdin を渡していないっぽい。

      ということで調べてみたらやっぱり解決策がある
      debconf で License を読んだことと、同意したことを事前に登録すればOKとのこと。
      • echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
      • echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections
      • apt-get install -y oracle-java8-installer
      これで yes を入力しなくても Java が Install できる。良し良し。


      参考