- 投稿日:2019-05-30T23:25:10+09:00
一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -
ストーリー
- 一足遅れて Kubernetes を学び始める - 01. 環境選択編 -
- 一足遅れて Kubernetes を学び始める - 02. Docker For Mac -
- 一足遅れて Kubernetes を学び始める - 03. Raspberry Pi -
- 一足遅れて Kubernetes を学び始める - 04. kubectl -
- 一足遅れて Kubernetes を学び始める - 05. workloads その1 -
- 一足遅れて Kubernetes を学び始める - 06. workloads その2 -
- 一足遅れて Kubernetes を学び始める - 07. workloads その3 -
- 一足遅れて Kubernetes を学び始める - 08. discovery&LB その1 -
- 一足遅れて Kubernetes を学び始める - 09. discovery&LB その2 -
- 一足遅れて Kubernetes を学び始める - 10. config&storage その1 -
- 一足遅れて Kubernetes を学び始める - 11. config&storage その2 -
- 一足遅れて Kubernetes を学び始める - 12. リソース制限 -
- 一足遅れて Kubernetes を学び始める - 13. ヘルスチェックとコンテナライフサイクル -
前回
一足遅れて Kubernetes を学び始める - 12. リソース制限 -では、requestsやlimitなどのリソース制限について学習しました。今回は、ヘルスチェックとコンテナライフサイクルについて学習します。
ヘルスチェック
Kubernetesでは、Podの正常生判断のためのヘルスチェックが2種類用意されています。
- Liveness Probe
- Podが正常か判断。異常だった場合、Podを再起動。
- Readiness Probe
- Podがサービスインする準備ができているか判断。準備できていなかったら、トラフィックを流さない。
たとえば、Pod内でメモリリークが発生し応答しなくなった場合に有効です。
LoadBalancerのサービスは、ICMPによる簡易ヘルスチェックがデフォルトで用意されています。また、Liveness、Readinessどちらにも3つの方式があります。
- exec
- コマンドを実行し、終了コードが0でなければ失敗
- httpGet
- HTTP GETリクエストを実行し、statusCodeが200~399でなければ失敗
- tcpSocket
- TCPセッションが確立できなければ失敗
では、試してみましょう。
sample-healthcheck.yamlapiVersion: v1 kind: Pod metadata: name: sample-healthcheck labels: app: sample-app spec: containers: - name: nginx-container image: nginx:1.12 ports: - containerPort: 80 livenessProbe: httpGet: path: /index.html port: 80 scheme: HTTP timeoutSeconds: 1 successThreshold: 1 failureThreshold: 2 initialDelaySeconds: 5 periodSeconds: 3 readinessProbe: exec: command: ["ls", "/usr/share/nginx/html/50x.html"] timeoutSeconds: 1 successThreshold: 2 failureThreshold: 1 initialDelaySeconds: 5 periodSeconds: 3
- timeoutSeconds
- タイムアウトまでの秒数
- successThreshold
- 成功と判断するまでのチェック回数
- failureThreshold
- 失敗と判断するまでのチェック回数
- initialDelaySeconds
- 初回ヘルスチェック開始までの遅延
- periodSeconds
- ヘルスチェックの間隔
pi@raspi001:~/tmp $ k apply -f sample-healthcheck.yaml pi@raspi001:~/tmp $ k describe pod sample-healthcheck | egrep "Liveness|Readiness" Liveness: http-get http://:80/index.html delay=5s timeout=1s period=3s #success=1 #failure=2 Readiness: exec [ls /usr/share/nginx/html/50x.html] delay=5s timeout=1s period=3s #success=2 #failure=1設定どおりに動作していますね。では、失敗させましょう。
livenessを失敗させるにはindex.htmlを削除すれば良いですね。
pi@raspi001:~/tmp $ k exec -it sample-healthcheck rm /usr/share/nginx/html/index.html pi@raspi001:~/tmp $ k get pods --watch NAME READY STATUS RESTARTS AGE sample-healthcheck 1/1 Running 1 9m54s sample-healthcheck 0/1 Running 2 10m sample-healthcheck 1/1 Running 2 10m一度削除されて、再起動しましたね。
今度は、readinessを失敗させましょう。こちらは50x.htmlを削除すれば良いですね。pi@raspi001:~/tmp $ k exec -it sample-healthcheck rm /usr/share/nginx/html/50x.html pi@raspi001:~/tmp $ k get pods --watch NAME READY STATUS RESTARTS AGE sample-healthcheck 1/1 Running 2 16m sample-healthcheck 0/1 Running 2 16m pi@raspi001:~/tmp $ k exec -it sample-healthcheck touch /usr/share/nginx/html/50x.html pi@raspi001:~/tmp $ k get pods --watch NAME READY STATUS RESTARTS AGE sample-healthcheck 0/1 Running 2 17m sample-healthcheck 1/1 Running 2 17m期待通り、50x.htmlを削除すると、READYから外れて、追加するとREADYに戻りました。
コンテナの再起動
コンテナのプロセスが停止、またはヘルスチェックの失敗によってコンテナを再起動するかどうかは、spec.restartPolicyによって決まります。
種類は下記3つです。
- Always
- 常にPodを再起動させる
- OnFailure
- 終了コード0以外の予期せぬ停止の場合、Podを再起動させる
- Never
- 再起動させない
試してみましょう。
sample-restart-always.yamlapiVersion: v1 kind: Pod metadata: name: sample-restart-always spec: restartPolicy: Always containers: - name: nginx-container image: nginx:1.12 command: ["sh", "-c", "exit 0"] # 成功の場合 # command: ["sh", "-c", "exit 1"] # 失敗の場合pi@raspi001:~/tmp $ k apply -f sample-restart-always.yaml # 成功の場合 pi@raspi001:~/tmp $ k get pods sample-restart-always --watch NAME READY STATUS RESTARTS AGE sample-restart-always 0/1 ContainerCreating 0 13s sample-restart-always 0/1 Completed 0 19s sample-restart-always 0/1 Completed 1 27s sample-restart-always 0/1 CrashLoopBackOff 1 28s sample-restart-always 0/1 Completed 2 37s # 失敗の場合 pi@raspi001:~/tmp $ k get pods sample-restart-always --watch NAME READY STATUS RESTARTS AGE sample-restart-always 0/1 ContainerCreating 0 7s sample-restart-always 0/1 Error 0 12s sample-restart-always 0/1 Error 1 17s sample-restart-always 0/1 CrashLoopBackOff 1 18s sample-restart-always 0/1 Error 2 37s成功、失敗どちらも再起動していることがわかります。
sample-restart-onfailure.yamlapiVersion: v1 kind: Pod metadata: name: sample-restart-onfailure spec: restartPolicy: OnFailure containers: - name: nginx-container image: nginx:1.12 command: ["sh", "-c", "exit 0"] # 成功の場合 # command: ["sh", "-c", "exit 1"] # 失敗の場合pi@raspi001:~/tmp $ k apply -f sample-restart-onfailure.yaml # 成功の場合 pi@raspi001:~/tmp $ k get pods sample-restart-onfailure --watch NAME READY STATUS RESTARTS AGE sample-restart-onfailure 0/1 ContainerCreating 0 3s sample-restart-onfailure 0/1 Completed 0 15s # 失敗の場合 pi@raspi001:~/tmp $ k get pods sample-restart-onfailure --watch NAME READY STATUS RESTARTS AGE sample-restart-onfailure 0/1 ContainerCreating 0 4s sample-restart-onfailure 0/1 Error 0 22s sample-restart-onfailure 0/1 Error 1 28s sample-restart-onfailure 0/1 CrashLoopBackOff 1 29s sample-restart-onfailure 0/1 Error 2 50s成功時は、Completedの終了していますね。CrashLoopBackOffしていません。失敗時は、Errorとなり、CrashLoopBackOffしています。
期待通りですね。initContainers
Podのメインとなるコンテナを起動する前に別のコンテナを起動させるための機能です。
spec.containersがもともとありますが、こちらは同時並列で起動するので、順序が必要な場合には向いていません。
initContainersは、spec.initContainersで設定でき、複数指定できます。複数の場合は上から順に起動します。試してみましょう。
sample-initcontainer.yamlapiVersion: v1 kind: Pod metadata: name: sample-initcontainer spec: initContainers: - name: output-1 image: nginx:1.12 command: ['sh', '-c', 'sleep 20; echo 1st > /usr/share/nginx/html/index.html'] volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ - name: output-2 image: nginx:1.12 command: ['sh', '-c', 'sleep 10; echo 2nd >> /usr/share/nginx/html/index.html'] volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ containers: - name: nginx-container image: nginx:1.12 volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html/ volumes: - name: html-volume emptyDir: {}pi@raspi001:~/tmp $ k get pod sample-initcontainer --watch NAME READY STATUS RESTARTS AGE sample-initcontainer 0/1 Init:0/2 0 3s sample-initcontainer 0/1 Init:0/2 0 9s sample-initcontainer 0/1 Init:1/2 0 30s sample-initcontainer 0/1 Init:1/2 0 38s sample-initcontainer 0/1 PodInitializing 0 51s sample-initcontainer 1/1 Running 0 59s pi@raspi001:~/tmp $ k exec -it sample-initcontainer cat /usr/share/nginx/html/index.html 1st 2nd確かに、initContainersが順序通り起動できています。ふむふむ。
起動時と終了時のコマンド実行(postStart,preStop)
コンテナ起動後に実行するコマンドをpostStart,
コンテナ終了前に実行するコマンドをpreStopという機能で実現できます。sample-lifecycle.yamlapiVersion: v1 kind: Pod metadata: name: sample-lifecycle spec: containers: - name: nginx-container image: nginx:1.12 command: ["/bin/sh", "-c", "touch /tmp/started; sleep 3600"] lifecycle: postStart: exec: command: ["/bin/sh", "-c", "sleep 20; touch /tmp/poststart"] preStop: exec: command: ["/bin/sh", "-c", "touch /tmp/prestop; sleep 20"]pi@raspi001:~/tmp $ k apply -f sample-lifecycle.yaml pi@raspi001:~/tmp $ k exec -it sample-lifecycle ls /tmp started # 数秒後 pi@raspi001:~/tmp $ $ k exec -it sample-lifecycle ls /tmp poststart started pi@raspi001:~/tmp $ k delete -f sample-lifecycle.yaml # すぐ! pi@raspi001:~/tmp $ k exec -it sample-lifecycle ls /tmp poststart prestop startedたしかに、postStart, preStopが動いています。
注意しないといけないのが、postStartは、spec.containers[].commandの実行とほぼ同じだそうです。(非同期)Podの安全な停止とタイミング
terminationGracePeriodSecondsに指定した秒数は、podが削除開始時からの猶予です。
デフォルトで30秒となっています。30秒の間にpreStop+SIGTERMの処理が終わらなければ、
強制的にSIGKILLされて停止されます。ただし、preStopが終わっていなくて30秒たった場合、
SIGTERM処理を2秒だけ実施できます。
terminationGracePeriodSecondsの値は、prePostを必ず終える秒数に設定しましょう。Nodeをスケジューリング対象から外す
Nodeをkubernetesのスケジューリング対象から外すcordonというコマンドがあります。
Nodeの状態には、SchedulingEnabledとSchedulingDisabledがあり、後者の状態になると、
kubernetesからのスケジューリング対象外となり、たとえばReplicaSetの更新などが機能しなくなります。cordonコマンドを使うと、指定するNodeがSchedulingDisabledになります。(uncordonは逆)
ただし、現在動作しているPodはスケジューリング対象になったままで、新たに追加するものが
スケジューリング対象外になります。現在動作しているものも対象にしたい場合は、drainコマンド
を使います。
実際に試してみます。pi@raspi001:~/tmp $ k get nodes NAME STATUS ROLES AGE VERSION raspi001 Ready master 33d v1.14.1 raspi002 Ready worker 33d v1.14.1 raspi003 Ready worker 32d v1.14.1 pi@raspi001:~/tmp $ k cordon raspi002 pi@raspi001:~/tmp $ k get nodes NAME STATUS ROLES AGE VERSION raspi001 Ready master 33d v1.14.1 raspi002 Ready,SchedulingDisabled worker 33d v1.14.1 raspi003 Ready worker 32d v1.14.1 pi@raspi001:~/tmp $ k uncordon raspi002 pi@raspi001:~/tmp $ k get nodes NAME STATUS ROLES AGE VERSION raspi001 Ready master 33d v1.14.1 raspi002 Ready worker 33d v1.14.1 raspi003 Ready worker 32d v1.14.1 pi@raspi001:~/tmp $ k drain raspi002 node/raspi002 cordoned error: unable to drain node "raspi002", aborting command... There are pending nodes to be drained: raspi002 error: cannot delete DaemonSet-managed Pods (use --ignore-daemonsets to ignore): kube-system/kube-flannel-ds-arm-7nnbj, kube-system/kube-proxy-wgjdq, metallb-system/speaker-tsxdkdrainすると、ReplicaSetのように管理したPodであれば、別Nodeに作成されるので良いのですが、
単体Podなど管理されていないものは、削除されてしまいます。上記の警告は、DaemonSetで管理されているPodは、
削除するしかないけど、良いですか?というものです。
そのため、drainをすると、いくつか警告されます。警告内容に従って適宜操作する必要があります。お片付け
pi@raspi001:~/tmp $ k delete -f sample-healthcheck.yaml -f sample-restart-always.yaml -f sample-restart-onfailure.yaml -f sample-initcontainer.yaml -f sample-lifecycle.yaml最後に
今回は、ヘルスチェックの動作と、コンテナを停止するまでのステップを学習しました。
わざわざヘルスチェックの処理をアプリケーションに用意せずとも、kubernetesに機能として
存在することに、驚きました。
- 投稿日:2019-05-30T17:47:57+09:00
PythonからC/C++を呼ぶ
初投稿です。最近要望があってPython触って見たけど、遅い。でもPythonで書かなきゃいけないときに「C呼んでしまえばよくね!?」ってなっていろいろ調べてみた。でも他の人が書いた記事の通りにやってもうまくいかなかった。パスか何かが間違ってたのかなぁって感じだったが、強引に動かしたら動いたのでメモ。
概要
Boost.Pythonというやつを使えばいいらしい。ライブラリを参照するのがうまくいかなかったので、一つのディレクトリ内に全部入れて動かす方法。
環境
macOS 10.13.6
Python3.7
BoostPython1.68.0必要なものを用意する
このプログラムを実行するディレクトリを用意した。どこでもいいと思うが、僕は
~/Python/BoostPythonTest/にした。ここに以下のものを用意する。
- libboost_python37.dylib
- libpython3.7.dylib
- C/C++ソース
- Pythonソース
libboost_python37.dylib
以下でBoost.Pythonをインストールする。
% brew install boost-python3インストールしたら
/usr/local/Cellar/boost-python3/1.68.0/lib/libboost_python37.dylibがあるはずなので、これを実行するディレクトリにコピーする。libpython3.7.dylib
Pythonをインストールしておく。
% brew install python3
/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Pythonを実行するディレクトリにコピーして、libpython3.7.dylibという名前に変更する。C/C++ソース
テスト用に
hello.cppっていうソースを用意した。hello.cpp#include <boost/python.hpp> #include <stdio.h> char greet(int x){ printf("printHELLO!!\n"); return '0' + x + 1; } char const* fine(){ return "How are you?"; } BOOST_PYTHON_MODULE(hello){ using namespace boost::python; def("greet", greet); def("fine", fine); }Pythonソース
テスト用に
test.pyっていうソースを用意した。test.pyimport hello x = hello.greet(2) print(x) y = hello.file() print(y)コンパイル
以下でコンパイルできるはず。実行するディレクトリのファイルを参照するだけ。
% g++ -fPIC -Wall -O2 -shared -o hello.so hello.cpp libboost_python37.dylib libpython3.7.dylib実行
実行してみる。
% python3 test.py printHELLO!! 3 How are you?ちゃんとできてそう。
まとめ
一つのディレクトリに全部ぶっ込んで動かすっていうちょっと強引な方法でしたが、とりあえず動いたのでよしとする。
- 投稿日:2019-05-30T17:47:57+09:00
MacでPythonからC/C++を呼ぶ
初投稿です。最近要望があってPython触ってみたけど、遅い。でもPythonで書かなきゃいけないときに「C呼んでしまえばよくね!?」ってなっていろいろ調べてみた。でも他の人が書いた記事の通りにやってもうまくいかなかった。参照か何かが間違ってたのかなぁって感じだったが、強引に動かしたら動いたのでメモ。
概要
Boost.Pythonというやつを使えばいいらしい。ライブラリを参照するのがうまくいかなかったので、一つのディレクトリ内に全部入れて動かした。
環境
macOS 10.13.6
Python 3.7
BoostPython 1.68.0必要なものを用意する
このプログラムを実行するディレクトリを用意した。どこでもいいと思うが、僕は
~/Python/BoostPythonTest/にした。ここに以下のものを用意する。
- libboost_python37.dylib
- libpython3.7.dylib
- C/C++ソース
- Pythonソース
libboost_python37.dylib
以下でBoost.Pythonをインストールする。1
% brew install boost-python3インストールしたら
/usr/local/Cellar/boost-python3/1.68.0/lib/libboost_python37.dylibがあるはずなので、これを実行するディレクトリにコピーする。libpython3.7.dylib
Pythonをインストールしておく。1
% brew install python3
/usr/local/Cellar/python/3.7.2/Frameworks/Python.framework/Versions/3.7/Pythonを実行するディレクトリにコピーして、libpython3.7.dylibという名前に変更する。C/C++ソース
テスト用に
hello.cppっていうソースを用意した。hello.cpp#include <boost/python.hpp> #include <stdio.h> char greet(int x){ printf("printHELLO!!\n"); return '0' + x + 1; } char const* fine(){ return "How are you?"; } BOOST_PYTHON_MODULE(hello){ using namespace boost::python; def("greet", greet); def("fine", fine); }Pythonソース
テスト用に
test.pyっていうソースを用意した。test.pyimport hello x = hello.greet(2) print(x) y = hello.file() print(y)コンパイル
以下でコンパイルできるはず。実行するディレクトリ内のファイルを参照するだけ。
% g++ -fPIC -Wall -O2 -shared -o hello.so hello.cpp libboost_python37.dylib libpython3.7.dylib
hello.soが実行するディレクトリに作られる。実行
実行してみる。
% python3 test.py printHELLO!! 3 How are you?ちゃんとできてそう。
まとめ
一つのディレクトリに全部ぶっ込んで動かすっていうちょっと強引な方法でしたが、とりあえず動いたのでよしとしよう。
Ubuntuでも動かそうとしたけどできなかった。
dylib使ってるからMacじゃないとダメみたい。参考
[1]c/c++をラップしてpythonで使えるように
https://www.quark.kj.yamagata-u.ac.jp/~hiroki/python/?id=19[2]boost インストールから実行(boost::python)まで。
http://nonbiri-tereka.hatenablog.com/entry/2014/02/01/004547
brewを使うときにパーミッションエラーがでたら、sudo brew ...ってやる。 ↩
- 投稿日:2019-05-30T12:27:43+09:00
[Python3.6]サーバで作成してダウンロードしたCSVをExcelで開くと日本語が文字化けする時の対処法
- 投稿日:2019-05-30T11:41:37+09:00
mac で rails new した後の bundle install 時に ffi 1.11.0 のインストールが失敗したのでバージョン固定で解決
バージョン
名前 バージョン macOS 10.13.6 ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17] rails 5.2.3 起きたエラー内容
$ bundle exec rails new ../sample create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile (略) Fetching gem metadata from https://rubygems.org/............ Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Fetching rake 12.3.2 Your user account isn't allowed to install to the system RubyGems. You can cancel this installation and run: bundle install --path vendor/bundle to install the gems into ./vendor/bundle/, or you can enter your password and install the bundled gems to RubyGems using sudo. Password: Installing rake 12.3.2 Fetching concurrent-ruby 1.1.5 Installing concurrent-ruby 1.1.5 (略) Fetching coffee-rails 4.2.2 Installing coffee-rails 4.2.2 Fetching ffi 1.11.0 Installing ffi 1.11.0 with native extensions Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -r ./siteconf20190519-47252-1at7a63.rb extconf.rb checking for ffi.h... no checking for ffi.h in /usr/local/include,/usr/include/ffi... yes checking for ffi_call() in -lffi... yes checking for ffi_closure_alloc()... no checking for shlwapi.h... no checking for rb_thread_call_without_gvl()... yes checking for ruby_native_thread_p()... yes checking for ruby_thread_has_gvl_p()... yes creating extconf.h creating Makefile To see why this extension failed to compile, please check the mkmf.log which can be found here: /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/mkmf.log current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c make "DESTDIR=" clean current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c make "DESTDIR=" mkdir -p "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386; (if [ ! -f "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure ]; then echo "Running autoreconf for libffi"; cd "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi" && /bin/sh /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/autogen.sh > /dev/null; fi); (if [ ! -f "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/Makefile ]; then echo "Configuring libffi for i386"; cd "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386 && env CC=" xcrun clang" CFLAGS="-arch i386 " LDFLAGS="-arch i386" "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure --disable-static --with-pic=yes --disable-dependency-tracking --disable-docs --host=i386-apple-darwin > /dev/null; fi); env MACOSX_DEPLOYMENT_TARGET=10.4 /Applications/Xcode.app/Contents/Developer/usr/bin/make -C "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386 (略) libtool: link: ranlib .libs/libffi_convenience.a libtool: link: ( cd ".libs" && rm -f "libffi_convenience.la" && ln -s "../libffi_convenience.la" "libffi_convenience.la" ) /bin/sh ./libtool --tag=CC --mode=link xcrun clang -arch i386 -Wall -fexceptions -no-undefined -version-info `grep -v '^#' /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/libtool-version` '-arch' 'i386' -arch i386 -o libffi.la -rpath /usr/local/lib src/prep_cif.lo src/types.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo src/x86/ffi.lo src/x86/sysv.lo libtool: link: xcrun clang -dynamiclib -o .libs/libffi.7.dylib src/.libs/prep_cif.o src/.libs/types.o src/.libs/raw_api.o src/.libs/java_raw_api.o src/.libs/closures.o src/x86/.libs/ffi.o src/x86/.libs/sysv.o -arch i386 -arch i386 -arch i386 -install_name /usr/local/lib/libffi.7.dylib -compatibility_version 9 -current_version 9.0 -Wl,-single_module ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS) Undefined symbols for architecture i386: "___x86.get_pc_thunk.bx", referenced from: _ffi_call_i386 in sysv.o _ffi_closure_raw_SYSV in sysv.o _ffi_closure_raw_THISCALL in sysv.o "___x86.get_pc_thunk.dx", referenced from: _ffi_closure_i386 in sysv.o _ffi_closure_STDCALL in sysv.o ld: symbol(s) not found for architecture i386 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[3]: *** [libffi.la] Error 1 make[2]: *** [all-recursive] Error 1 make[1]: *** [all] Error 2 make: *** ["/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/.libs/libffi_convenience.a] Error 2 make failed, exit code 2 Gem files will remain installed in /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0 for inspection. Results logged to /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/gem_make.out An error occurred while installing ffi (1.11.0), and Bundler cannot continue. Make sure that `gem install ffi -v '1.11.0'` succeeds before bundling. In Gemfile: spring-watcher-listen was resolved to 2.0.1, which depends on listen was resolved to 3.1.5, which depends on rb-inotify was resolved to 0.10.0, which depends on ffi run bundle exec spring binstub --all bundler: command not found: spring Install missing gem executables with `bundle install` $macOS が 10.13.6 なのがきっといけないのだろうと思うが、そこじゃない場所で解決を試みる。
解決後に
Gemfile.lockを見ると、ffiの依存指定は一箇所のみで、こうなっていた。rb-inotify (0.10.0) ffi (~> 1.0)
ffi (~> 1.0)とあるので、ffiの1.xの最新版を取ろうとして、それがインストールできていない。解決方法
~> 1.0ということは1.11.0が必要なわけじゃないはずので、Gemfileを書き換えて、インストールできるバージョンに固定した。1.9.21は、あくまで例ですgem 'ffi', '= 1.9.21'(これは要らないかもしれない) 事前にインストールしておく。
$ sudo gem install ffi -v '1.9.21' Fetching: ffi-1.9.21.gem (100%) Building native extensions. This could take a while... Successfully installed ffi-1.9.21 Parsing documentation for ffi-1.9.21 Installing ri documentation for ffi-1.9.21 Done installing documentation for ffi after 3 seconds 1 gem installed $で、改めて bundle install
$ bundle install --path vendor/bundle The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`. Fetching gem metadata from https://rubygems.org/............ Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Using rake 12.3.2 Using concurrent-ruby 1.1.5 (略) Using railties 5.2.3 Using coffee-rails 4.2.2 Fetching ffi 1.9.21 Installing ffi 1.9.21 with native extensionsうまくいった
バージョンの選び方
ffi 1.9.21を選ぶべきだというわけではないのですが、あらかじめ mac 側にインストールしてある可能性(他の ruby プログラムを動かすためにインストールしたことがあった、など)を考えれば、たとえばgem listで調べればインストール可能なバージョンがわかるはず$ gem list ffi *** LOCAL GEMS *** ffi (1.9.21) public_suffix (3.0.3)それ以外では、 https://rubygems.org/gems/ffi/versions を見て、一つ前のバージョンの最新を選ぶと良いと思います。今回だと、失敗したのは
1.11.0なので、1.10.xの中での最新の1.10.0を試す、それでもダメなら1.9.25を試す、...を繰り返す、など。時間がある人は、もちろん原因を特定してそれが解決できる最新のバージョンを選びましょう。
- 投稿日:2019-05-30T11:41:37+09:00
mac で (rails new した後の bundle install 時に) ffi 1.11.0 のインストールが失敗したのでバージョン固定で解決
バージョン
名前 バージョン macOS 10.13.6 ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17] rails 5.2.3 コメントでご指摘あったように、問題そのものは Rails とは関係ないです。
起きたエラー内容
$ bundle exec rails new ../sample create create README.md create Rakefile create .ruby-version create config.ru create .gitignore create Gemfile (略) Fetching gem metadata from https://rubygems.org/............ Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Fetching rake 12.3.2 Your user account isn't allowed to install to the system RubyGems. You can cancel this installation and run: bundle install --path vendor/bundle to install the gems into ./vendor/bundle/, or you can enter your password and install the bundled gems to RubyGems using sudo. Password: Installing rake 12.3.2 Fetching concurrent-ruby 1.1.5 Installing concurrent-ruby 1.1.5 (略) Fetching coffee-rails 4.2.2 Installing coffee-rails 4.2.2 Fetching ffi 1.11.0 Installing ffi 1.11.0 with native extensions Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -r ./siteconf20190519-47252-1at7a63.rb extconf.rb checking for ffi.h... no checking for ffi.h in /usr/local/include,/usr/include/ffi... yes checking for ffi_call() in -lffi... yes checking for ffi_closure_alloc()... no checking for shlwapi.h... no checking for rb_thread_call_without_gvl()... yes checking for ruby_native_thread_p()... yes checking for ruby_thread_has_gvl_p()... yes creating extconf.h creating Makefile To see why this extension failed to compile, please check the mkmf.log which can be found here: /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/mkmf.log current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c make "DESTDIR=" clean current directory: /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c make "DESTDIR=" mkdir -p "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386; (if [ ! -f "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure ]; then echo "Running autoreconf for libffi"; cd "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi" && /bin/sh /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/autogen.sh > /dev/null; fi); (if [ ! -f "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/Makefile ]; then echo "Configuring libffi for i386"; cd "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386 && env CC=" xcrun clang" CFLAGS="-arch i386 " LDFLAGS="-arch i386" "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi"/configure --disable-static --with-pic=yes --disable-dependency-tracking --disable-docs --host=i386-apple-darwin > /dev/null; fi); env MACOSX_DEPLOYMENT_TARGET=10.4 /Applications/Xcode.app/Contents/Developer/usr/bin/make -C "/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386 (略) libtool: link: ranlib .libs/libffi_convenience.a libtool: link: ( cd ".libs" && rm -f "libffi_convenience.la" && ln -s "../libffi_convenience.la" "libffi_convenience.la" ) /bin/sh ./libtool --tag=CC --mode=link xcrun clang -arch i386 -Wall -fexceptions -no-undefined -version-info `grep -v '^#' /private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c/libffi/libtool-version` '-arch' 'i386' -arch i386 -o libffi.la -rpath /usr/local/lib src/prep_cif.lo src/types.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo src/x86/ffi.lo src/x86/sysv.lo libtool: link: xcrun clang -dynamiclib -o .libs/libffi.7.dylib src/.libs/prep_cif.o src/.libs/types.o src/.libs/raw_api.o src/.libs/java_raw_api.o src/.libs/closures.o src/x86/.libs/ffi.o src/x86/.libs/sysv.o -arch i386 -arch i386 -arch i386 -install_name /usr/local/lib/libffi.7.dylib -compatibility_version 9 -current_version 9.0 -Wl,-single_module ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS) Undefined symbols for architecture i386: "___x86.get_pc_thunk.bx", referenced from: _ffi_call_i386 in sysv.o _ffi_closure_raw_SYSV in sysv.o _ffi_closure_raw_THISCALL in sysv.o "___x86.get_pc_thunk.dx", referenced from: _ffi_closure_i386 in sysv.o _ffi_closure_STDCALL in sysv.o ld: symbol(s) not found for architecture i386 clang: error: linker command failed with exit code 1 (use -v to see invocation) make[3]: *** [libffi.la] Error 1 make[2]: *** [all-recursive] Error 1 make[1]: *** [all] Error 2 make: *** ["/private/var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0/ext/ffi_c"/libffi-i386/.libs/libffi_convenience.a] Error 2 make failed, exit code 2 Gem files will remain installed in /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/gems/ffi-1.11.0 for inspection. Results logged to /var/folders/_h/xgr__5xn3kscjx0f8m7v3qbr0000gn/T/bundler20190519-47252-1smbwrlffi-1.11.0/extensions/universal-darwin-17/2.3.0/ffi-1.11.0/gem_make.out An error occurred while installing ffi (1.11.0), and Bundler cannot continue. Make sure that `gem install ffi -v '1.11.0'` succeeds before bundling. In Gemfile: spring-watcher-listen was resolved to 2.0.1, which depends on listen was resolved to 3.1.5, which depends on rb-inotify was resolved to 0.10.0, which depends on ffi run bundle exec spring binstub --all bundler: command not found: spring Install missing gem executables with `bundle install` $
macOS が 10.13.6 なのがきっといけないのだろうと思うが、そこじゃない場所で解決を試みる。コメントにて、OS も関係ないとのご指摘。ld: warning: The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)の辺りを調べればいいかもしれないのですが、それはまたの機会に。解決後に
Gemfile.lockを見ると、ffiの依存指定は一箇所のみで、こうなっていた。rb-inotify (0.10.0) ffi (~> 1.0)
ffi (~> 1.0)とあるので、ffiの1.xの最新版(当時は1.11.0)を取ろうとして、それがインストールできていない。解決方法
~> 1.0ということは1.11.0が必要なわけじゃないはずので、Gemfileを書き換えて、インストールできるバージョンに固定した。(1.9.21は、あくまで例です)gem 'ffi', '= 1.9.21'(これは要らないかもしれない) 事前にインストールしておく。
$ sudo gem install ffi -v '1.9.21' Fetching: ffi-1.9.21.gem (100%) Building native extensions. This could take a while... Successfully installed ffi-1.9.21 Parsing documentation for ffi-1.9.21 Installing ri documentation for ffi-1.9.21 Done installing documentation for ffi after 3 seconds 1 gem installed $で、改めて bundle install
$ bundle install --path vendor/bundle The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`. Fetching gem metadata from https://rubygems.org/............ Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Using rake 12.3.2 Using concurrent-ruby 1.1.5 (略) Using railties 5.2.3 Using coffee-rails 4.2.2 Fetching ffi 1.9.21 Installing ffi 1.9.21 with native extensionsうまくいった
バージョンの選び方
ffi 1.9.21を選ぶべきだというわけではないのですが、あらかじめ mac 側にインストールしてある可能性(他の ruby プログラムを動かすためにインストールしたことがあった、など)を考えれば、たとえばgem listで調べればインストール可能なバージョンがわかるはず$ gem list ffi *** LOCAL GEMS *** ffi (1.9.21) public_suffix (3.0.3)それ以外では、 https://rubygems.org/gems/ffi/versions を見て、一つ前のバージョンの最新を選ぶと良いと思います。今回だと、失敗したのは
1.11.0なので、1.10.xの中での最新の1.10.0を試す、それでもダメなら1.9.25を試す、...を繰り返す、など。時間がある人は、もちろん原因を特定してそれが解決できる最新のバージョンを選びましょう。
- 投稿日:2019-05-30T10:54:54+09:00
rails new の手順メモ
メモ: アプリケーションを作るときに必要な Gemfile と、アプリケーションで使う Gemfile は別でよい。
Rails アプリケーション作成用のプロジェクトを作る
Gemfile
rails_generator みたいなディレクトリを作って、そこに Gemfile って名前のファイルを置く。内容は下記
Gemfile# frozen_string_literal: true source 'https://rubygems.org' gem 'rails'bundle install
デバッグ用なので path を指定する
$ bundle install --path vendor/bundleこんな感じになるはず
$ ls vendor Gemfile Gemfile.lock $rails new
ディレクトリを指定して rails new をする。今回は
-+- (root) |- rails_generator (今操作していたディレクトリ) `- sampleとなるように下記を実行してみる。
$ bundle exec rails new ../sample終わったら、 rails_generator 配下は消して良い
- 投稿日:2019-05-30T00:45:04+09:00
Go入門①[Mac]VSCodeでGolangのハロワをしてみる~インストールからハロワまで~
golangを勉強し始めたので備忘録的にまとめてみる
Golangとは
特徴
- コンパイル型言語
- VMは無く、ネイティブコードを生成する
- 実行環境が不要であり、オーバーヘッドが少なくて高速に動作する
- クロスコンパイルができ、マルチプラットフォームで動作する
- 並行処理が得意(ゴルーチン)
多言語と比較すると(かなりざっくり)
C言語に似ている
- ポインタ型
- 構造体
- 基本型
- でもGCはサポートされている
Java/C#
- オブジェクト指向ではない
- VM要らず
- IDEなくても十分開発可能
JS/PHP/Ruby/Pythonなど
- 型推論はあるが静的型付け言語
- パフォーマンスが優れている(10倍以上)
インストール
- Goのダウンロードページからダウンロード
- Macの場合はbrewでインストールできる→
brew install go- インストーラでインストールする
パス追加(zshの場合)
echo 'export GOPATH=$HOME/go' >> ~/.zshrc echo 'export GOBIN=$GOPATH/bin' >> ~/.zshrc echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrcGOPATHが使用するディレクトリ作成
mkdir -p $GOBIN/goGOPATHとは
外部のライブラリが格納されているディレクトリの場所を認識するために必要な環境変数
→イマイチよくわからんけど必要らしいので設定しておく
Version確認してみる
> go version go version go1.11.5 darwin/amd64エディター
Visual Studio Codeを使用
VSCodeのインストール
https://code.visualstudio.com/ からダウンロードする
golang用の拡張機能をインストール
goで検索してインストール数が一番多いものを選択してインストールするhttps://github.com/Microsoft/vscode-go
必要なツールのインストール
拡張機能の説明欄に
You will see Analysis Tools Missing in the bottom right, clicking this will offer to install all of the dependent Go tools. You can also run the command Go: Install/Update tools to install/update the same.
とあり、
Go: Install/Update toolsを実行するにはコマンドパレットを開けと書いてある
Cmd+Shift+PかCtrl+Shift+Pでコマンドパレットをを開き、Go: Install/Update toolsを実行するどれをインストールするか聞いてくるので、全て選択し、OKを押す
Outputに以下のようにインストールされた旨が表示されればOK
ハロワしてみる
新しくファイルを作成し、以下のように記載する
hello.gopackage main import "fmt" func main() { fmt.Println("Hello, World!") }
go run hello.goで実行してみる(デバッグモードでrunしてもよい)
無事ハロワできた!
- 投稿日:2019-05-30T00:45:04+09:00
[Mac]VSCodeでGolangのハロワをしてみる~インストールからハロワまで~
golangを勉強し始めたので備忘録的にまとめてみる
Golangとは
特徴
- コンパイル型言語
- VMは無く、ネイティブコードを生成する
- 実行環境が不要であり、オーバーヘッドが少なくて高速に動作する
- クロスコンパイルができ、マルチプラットフォームで動作する
- 並行処理が得意(ゴルーチン)
多言語と比較すると(かなりざっくり)
C言語に似ている
- ポインタ型
- 構造体
- 基本型
- でもGCはサポートされている
Java/C#
- オブジェクト指向ではない
- VM要らず
- IDEなくても十分開発可能
JS/PHP/Ruby/Pythonなど
- 型推論はあるが静的型付け言語
- パフォーマンスが優れている(10倍以上)
インストール
- Goのダウンロードページからダウンロード
- Macの場合はbrewでインストールできる→
brew install go- インストーラでインストールする
パス追加(zshの場合)
echo 'export GOPATH=$HOME/go' >> ~/.zshrc echo 'export GOBIN=$GOPATH/bin' >> ~/.zshrc echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.zshrcGOPATHが使用するディレクトリ作成
mkdir -p $GOBIN/goGOPATHとは
外部のライブラリが格納されているディレクトリの場所を認識するために必要な環境変数
→イマイチよくわからんけど必要らしいので設定しておく
Version確認してみる
> go version go version go1.11.5 darwin/amd64エディター
Visual Studio Codeを使用
VSCodeのインストール
https://code.visualstudio.com/ からダウンロードする
golang用の拡張機能をインストール
goで検索してインストール数が一番多いものを選択してインストールするhttps://github.com/Microsoft/vscode-go
必要なツールのインストール
拡張機能の説明欄に
You will see Analysis Tools Missing in the bottom right, clicking this will offer to install all of the dependent Go tools. You can also run the command Go: Install/Update tools to install/update the same.
とあり、
Go: Install/Update toolsを実行するにはコマンドパレットを開けと書いてある
Cmd+Shift+PかCtrl+Shift+Pでコマンドパレットをを開き、Go: Install/Update toolsを実行するどれをインストールするか聞いてくるので、全て選択し、OKを押す
Outputに以下のようにインストールされた旨が表示されればOK
ハロワしてみる
新しくファイルを作成し、以下のように記載する
hello.gopackage main import "fmt" func main() { fmt.Println("Hello, World!") }
go run hello.goで実行してみる(デバッグモードでrunしてもよい)
無事ハロワできた!





