LinuxにNode.js入れる時はPermissionのためにnvm使ったほうがいい
前回の記事ではyumでNode.jsをインストールしたが、それはServerlessをインストールしようと思ったためであった。
しかし、Node.jsのインストール後、Serverless公式に書いてあったコマンド
npm install serverless -g
を実行したらPermissionで怒られた。
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules' npm ERR! { Error: EACCES: permission denied, access '/usr/local/lib/node_modules' npm ERR! errno: -13, npm ERR! code: 'EACCES', npm ERR! syscall: 'access', npm ERR! path: '/usr/local/lib/node_modules' } npm ERR! npm ERR! Please try running this command again as root/Administrator.
Permissionで怒られたのでsudoつけて実行したら以下のようなエラーが出た。
┌───────────────────────────────────────────────────┐ │ serverless update check failed │ │ Try running with sudo or get access │ │ to the local update config store via │ │ sudo chown -R $USER:$(id -gn $USER) /root/.config │ └───────────────────────────────────────────────────┘
インストールはできていてコマンドは使えるようだったが、このようなエラーを放置するのはちょっと気持ち悪いのでnpmのPermission周りについて色々調べた。
すると以下のページを発見。
Resolving EACCES permissions errors when installing packages globally
ここの『Reinstall npm with a node version manager』に以下の記述がある。
This is the best way to avoid permissions issues.
node version managerでnpmをインストールする事がPermission問題を回避する最善の方法らしい。
そのままリンクを辿っていくとversion managerの紹介がされていた。
Using a Node version manager to install Node.js and npm
ここでnとnvmが紹介されていたのだが、nvmの方がスター数が多かったため今回はnvmを選択した。
nvmのインストール方法は割愛する。
以下nvmレポジトリの Installation を参照してください。
nvmのインストール後、 nvm install node
で最新のNode.jsがインストールされる。
その後Serverlessをインストールするとエラーは出なかった🎉
まとめ
LinuxにNode.js入れる時はPermissionのためにnvm使ったほうがいい!
Amazon Linuxで古いNode.jsがインストールされる時の解決方法
Amazon Linuxで何度Node.js v11をインストールしようとしてもv6が入ってしまう現象が起こったのでその解決策をメモ。
現象
v11用RPMのセットアップをする。
$ curl -sL https://rpm.nodesource.com/setup_11.x | sudo bash -
その後、yum installしても 2:6.14.4-1nodesource
がインストールされる。
$ sudo yum install -y nodejs ... Installed: nodejs.x86_64 2:6.14.4-1nodesource
解決策
以下のコマンドでRPMのキャッシュを消す。
$ sudo yum remove -y nodesource-release* nodejs $ yum clean all $ sudo rm -rf /var/cache/yum/* $ sudo rm /etc/yum.repos.d/nodesource-el.repo
その後、再度RPMセットアップコマンドを流してyum installすればよい。
$ curl -sL https://rpm.nodesource.com/setup_11.x | sudo bash - ... $ sudo yum install -y nodejs ... Installed: nodejs.x86_64 2:11.1.0-1nodesource
v11が入りました。
参考
削除済みリモートブランチを追跡しているローカルブランチを1発で全削除するコマンド
リモートブランチはマージ後GitHubが削除するか聞いてくれるのでその時点で削除するようにしている。
だが、そのリモートブランチを追跡しているローカルブランチの削除を忘れて溜まっていることがよくある。
$ git branch -v * develop fef1cdd Merge pull request #30 from abcdef/fix/bazbarfoo feature/foo e57408f [gone] Fix deploy feature/bar a9b73ad [gone] Upload image feature/baz b833113 [gone] Fix test feature/foobar 703e2ad [gone] Add foobar.c feature/foobaz 1587581 [gone] Fix foobaz.rb feature/barfoo 37265cb [gone] Add barfoo.php feature/barbaz 3c121ca [gone] Fix barbaz.py feature/bazfoo cb69767 [gone] Add bazfoo.go feature/bazbar bb8575f [gone] Fix bazbar.pl feature/foobarbaz 66d2807 [gone] Fix README.md fix/foobazbar 84a781e [gone] Add gitignore fix/bazfoobar cd36a6b [gone] Fix ci master 0a41ce8 Merge pull request #20 from abcdef/develop
[gone]
が付いているのがリモートブランチへの追跡が切れているローカルブランチ。
いつも git branch -d
の後ろに1つずつブランチ名をコピペして削除していた。
$ git branch -d feature/foo feature/bar feature/baz feature/foobar feature/foobaz feature/barfoo feature/barbaz feature/bazfoo feature/bazbar feature/foobarbaz fix/foobazbar fix/bazfoobar Deleted branch feature/foo (was e57408f). Deleted branch feature/bar (was a9b73ad). Deleted branch feature/baz (was b833113). Deleted branch feature/foobar (was 703e2ad). Deleted branch feature/foobaz (was 1587581). Deleted branch feature/barfoo (was 37265cb). Deleted branch feature/barbaz (was 3c121ca). Deleted branch feature/bazfoo (was cb69767). Deleted branch feature/bazbar (was bb8575f). Deleted branch feature/foobarbaz (was 66d2807). Deleted branch fix/foobazbar (was 84a781e). Deleted branch fix/bazfoobar (was cd36a6b).
面倒なので1発コマンド打つだけで全部消えるコマンドを組もうと思い調べた。
コマンド
git for-each-ref --format '%(if)%(upstream:track)%(then)%(refname:short)%(end)' | xargs git branch -d
解説
最初は git branch
コマンドを使って作ろうとしていた。
だが、先の記事にも書いた通り、 git branch
を使ってスクリプトを書かないほうがいいらしい。
なので git for-each-ref
を使って書いた。
これはGitレポジトリの各refの情報を条件に従って出力していくコマンド。
Git - git-for-each-ref Documentation
何点か解説を書いてみる。
ブランチ名
ブランチ名は %(refname:short)
で取得。
short
をつけないと refs/heads
がついてしまい、ブランチ名として認識されないので注意が必要。
# `refs/heads` がついてしまう。 $ git for-each-ref --format '%(refname)' refs/heads/develop refs/heads/feature/foo refs/heads/feature/bar refs/heads/feature/baz refs/heads/feature/foobar refs/heads/feature/foobaz refs/heads/feature/barfoo refs/heads/feature/barbaz refs/heads/feature/bazfoo refs/heads/feature/bazbar refs/heads/feature/foobarbaz refs/heads/fix/foobazbar refs/heads/fix/bazfoobar refs/heads/master refs/remotes/origin/HEAD refs/remotes/origin/develop refs/remotes/origin/feature/aaa refs/remotes/origin/feature/bbb refs/remotes/origin/ccc refs/remotes/origin/master refs/remotes/origin/try/ddd refs/remotes/origin/try/eee # shortをつければ正しいブランチ名が取得できる。 $ git for-each-ref --format '%(refname:short)' develop feature/foo feature/bar feature/baz feature/foobar feature/foobaz feature/barfoo feature/barbaz feature/bazfoo feature/bazbar feature/foobarbaz fix/foobazbar fix/bazfoobar master origin/HEAD origin/develop origin/feature/aaa origin/feature/bbb origin/ccc origin/master origin/try/ddd origin/try/eee
gone
削除対象は [gone]
が付いたブランチなのでこれを取得する。
upstream の項で以下のように説明されている。
:track
also prints "[gone]" whenever unknown upstream ref is encountered.
試すと
$ git for-each-ref --format '%(upstream:track)' [gone] [gone] [gone] [gone] [gone] [gone] [gone] [gone] [gone] [gone] [gone] [gone]
[gone]
のみでは分かりづらいと思うのでブランチ名をつけてみる。
$ git for-each-ref --format '%(upstream:track) %(refname:short)' develop [gone] feature/foo [gone] feature/bar [gone] feature/baz [gone] feature/foobar [gone] feature/foobaz [gone] feature/barfoo [gone] feature/barbaz [gone] feature/bazfoo [gone] feature/bazbar [gone] feature/foobarbaz [gone] fix/foobazbar [gone] fix/bazfoobar master origin/HEAD origin/develop origin/feature/aaa origin/feature/bbb origin/ccc origin/master origin/try/ddd origin/try/eee
リモートへの追跡が切れていない develop
, master
やリモートにのみ存在しているブランチには [gone]
がついておらず、リモートへの追跡が切れたローカルブランチにのみ [gone]
がついている事がわかる。
if
git for-each-ref
ではif文( %(if)…%(then)…%(end)
)が使える。
if文を使い、 [gone]
があるときだけブランチ名を表示するようにする。
$ git for-each-ref --format '%(if)%(upstream:track)%(then)%(refname:short)%(end)' feature/foo feature/bar feature/baz feature/foobar feature/foobaz feature/barfoo feature/barbaz feature/bazfoo feature/bazbar feature/foobarbaz fix/foobazbar fix/bazfoobar
xargs
取得できたブランチ名をxargsを使って git branch -d
に流す。
ちなみにxargsだけ実行すると git branch -d
にどんな値が渡っているのかわかる。
$ git for-each-ref --format '%(if)%(upstream:track)%(then)%(refname:short)%(end)' | xargs feature/foo feature/bar feature/baz feature/foobar feature/foobaz feature/barfoo feature/barbaz feature/bazfoo feature/bazbar feature/foobarbaz fix/foobazbar fix/bazfoobar
こんな感じ。
別解
サブコマンドとして実行してもよい。
git branch -d $(git for-each-ref --format '%(if)%(upstream:track)%(then)%(refname:short)%(end)')
$(git branch)でカレントディレクトリのファイル一覧も出てしまう時の対処法
とあるシェルでgitのブランチ一覧を取りたくて echo $(git branch)
と書いたのだが、なぜかファイル一覧も出てしまい戸惑った。
前提
下記のようなディレクトリがあって、それがgit管理されていたとする。
$ ls README.md main.go main_test.go
そして以下のようなブランチが存在する。
$ git branch develop feature/bar feature/baz feature/foo * master
事象
echo $(git branch)
を実行すると下記のようにブランチ一覧の間にファイル一覧が差し込まれてしまう。
$ echo $(git branch) develop feature/bar feature/baz feature/foo README.md main.go main_test.go master
原因
勘のいい人はもうお分かりかもしれませんが、 git branch
した時にmasterの前に *
がついていますよね。
それが echo
にワイルドカードとみなされてファイル一覧が出てしまいます。
$ echo * README.md main.go main_test.go
と同じになるわけです。
対処法
ダブルクオートで囲めばワイルドカードが展開されずに出力されます。
$ echo "$(git branch)" develop feature/bar feature/baz feature/foo * master
ブランチ一覧を1行で取得したい場合
tr
を使って *
をスペースに変換したリストをダブルクオート無しで echo
すれば取得可能です。
$ echo $(echo "$(git branch | tr '*' ' ')") develop feature/bar feature/baz feature/foo master
でも、そもそも git branch
を使ってスクリプトを書かないほうがいいらしい。
上記によれば、Gitはスクリプトで使用するために明示的に設計されたplumbingインターフェースを提供しているとのこと。
なので自分はplumbingインターフェースを使ってみようと思います。
参考
特定のディレクトリ内にあるjavascriptを全てMinifyする
例えば static/js
ディレクトリにjsが置いてあるとする。
$ tree . └── static └── js ├── bar.js ├── baz.js └── foo.js
そのディレクトリ内にあるjavascriptを全てMinifyしたい場合のbashスクリプト。
for f in $(ls static/js/*.js); do uglifyjs -cm -o "${f/.js/.min.js}" "${f}" done
Minifyには uglify-js
を使用する。
オプションの c
が単純なソース圧縮、 m
が変数名の圧縮(1文字にする)、 o
はアウトプットするファイルを指定。
これを minify.sh
というファイル名で作成し、実行する。
注意点としては ${f/.js/.min.js}
がbashの文字列置換を使用しているのでbashで実行すること。
$ bash minify.sh
すると全てのjavascriptがMinifyされる。
$ tree . ├── minify.sh └── static └── js ├── bar.js ├── bar.min.js ├── baz.js ├── baz.min.js ├── foo.js └── foo.min.js
ちなみにMinifyしたjavascriptをgit管理したくない場合は .gitignore
に *.min.js
を入れると無視してくれる。
もうひと工夫
シバンを入れて実行権限をつけるとスッキリして良い。
実行権限をつけるのでファイル名も minify
にすると綺麗かも。
#!/bin/bash for f in $(ls static/js/*.js); do uglifyjs -cm -o "${f/.js/.min.js}" "${f}" done
$ mv minify.sh minify $ chmod u+x minify $ ./minify $ tree . ├── minify └── static └── js ├── bar.js ├── bar.min.js ├── baz.js ├── baz.min.js ├── foo.js └── foo.min.js
参考
CircleCIのYAMLの仕様が変わった
CircleCIを使っている。
今週水曜(2018年10月10日)なぜか本番デプロイができなくなっていた。
調査すると設定を書いているYAMLの仕様が変更されたようで、キーの上書きができなくなっていた。
元々の仕様
デプロイにはFabricを使用している。
fab dev deploy
で開発環境、 fab prod deploy
で本番環境にデプロイされるように設定ファイルを書いている。
references: env_dev: &env_dev environment: ENV: dev env_prod: &env_prod environment: ENV: prod jobs: deploy_dev: &deploy docker: - image: circleci/python:3.6 environment: AWS_DEFAULT_REGION: ap-northeast-1 steps: - checkout - run: name: Install python package command: sudo pip install -r requirements.txt - run: name: Deploy command: fab $ENV deploy <<: *env_dev deploy: <<: *deploy <<: *env_prod
Anchor(&name)とAlias(*name)を使用してコンパクトに書いている。
CircleCIは各jobページのConfigurationタブで展開されたYAMLを確認することができる。
展開されたYAMLを確認すると下記のようになっている。
jobs: deploy_dev: environment: - ENV: dev steps: - checkout - run: name: Install python package command: sudo pip install -r requirements.txt - run: name: Deploy command: fab $ENV deploy docker: - image: circleci/python:3.6 environment: AWS_DEFAULT_REGION: ap-northeast-1 deploy: environment: - ENV: prod docker: - image: circleci/python:3.6 environment: AWS_DEFAULT_REGION: ap-northeast-1 steps: - checkout - run: name: Install python package command: sudo pip install -r requirements.txt - run: name: Deploy command: fab $ENV deploy
ちゃんと environment
に ENV
が上書きされて展開されているのがわかります。
仕様変更後
水曜日、本番デプロイのCIが失敗することで仕様変更を知る。
仕様変更後に展開されたYAMLを確認すると deploy
jobの ENV
が上書きされず、 dev
のままになってしまっていた。
jobs: ... deploy: ... environment: - ENV: dev
Twitterでつぶやかれている方も居た。
違うっぽい。circleciのYAMLパーザがおかしくなってないっすか
— こうげ (@koooge) October 10, 2018
修正
AnchorとAlias周りがおかしいのではないかという事はすぐわかったので、以下のように修正を行った。
deploy: - <<: *deploy - <<: *env_prod + <<: [*env_prod, *deploy]
元々は *deploy
を先に書き、そこに *env_prod
を上書きするという意図で書いていた。
しかし、上書きされないため書く順番を逆にし、 *env_prod
を先に書き、 *deploy
を後に書いた。
この時、Aliasの書き方もCircleCIで推奨されている []
を使用した書き方に変更した。
すると下記のように以前の想定通り展開されました。
jobs: ... deploy: environment: - ENV: prod docker: - image: circleci/python:3.6 environment: AWS_DEFAULT_REGION: ap-northeast-1 steps: - checkout - run: name: Install python package command: sudo pip install -r requirements.txt - run: name: Deploy command: fab $ENV deploy
そして無事デプロイされるようになった。
ブログ再始動
お久しぶりです。
178inabaです。
久しぶりにブログを書いています。
最近、技術書典で技術書を販売した方のブログを見ました。
このブログを見て
(自分もいつかは本が書けたら楽しいだろうな)
(沢山の人が来場していて交流できるし、報酬も得られる!)
などと思い、
でも本を出すにはまず、休止状態のブログを再始動して技術的な記事とか書くべきだろうと思いこのブログを書いています。
Kyash始めてみた
Kyashは同僚と食事に行った時に割り勘代金を渡すために入れてみたのですが便利です。
上の技術書典のブログを読んだときに、KyashのAndroidエンジニアのこにふぁーさんのブログを思い出しました。
このこにふぁーさんのブログには投げ銭の話が書いてあって、上の技術書典の話と 『技術情報の発信で報酬を得る』 という所で通ずるなと思いました。
なので真似してKyashのIDとQRコードを貼ってみます。
kyash_id: 178inaba
今後
今後は定期的に技術情報をブログに書いていけたらと思います。
よろしくです!