「プログラミング」カテゴリーアーカイブ

MSYS2+Ruby on RailsでPumaが終了できないときの対処法

MSYS2とRuby 2.4.0をこちらの情報をもとにインストールしました。

Ruby on Rails 5.1.1もインストールできました。

でも、rails serverコマンドでPumaを起動した後、Ctrl-Cで終了しようとしてもできません。プロンプトは返ってくるのですが、Pumaにシグナルが送られていなくてプロセスは起動したままになっています。こうなるとタスクマネージャーでRuby Interpreterを探してタスクを終了するしかなくなります。

対処方法として、MinttyをあきらめてWindows Consoleを使う方法と、winptyを使う方法、ConEmuを使う方法の3つがあります。

Windows Consoleを使う方法だと、lsで出力に色がついたときに、赤色と青色が暗くて読めなくなります。

winptyを使う方法だと、いちいちwinptyをつけてコマンドを実行しなくてはならず面倒です。

そこで、ConEmuを使ってみることにしました。

ConEmuは、こちらからダウンロードしてインストールします。

PATHに追加してconemu64で起動できるようにします。

次に、スタートメニューのMinGW 64-bitやMSYS2の項目を右クリックしてファイルの場所を開くでショートカットを表示します。

ショートカットのプロパティーで、-conemuを付け加えます。

C:\msys64\msys2_shell.cmd -mingw64 -conemu

これで、ConEmuが使えるようになります。

右上の三本のアイコンでsettingsを選ぶと、フォントの大きさも変えられます。また、マウスで選択することでコピーペーストもできるのでとりあえずいいかなと思っています。

ただ、irbやrails consoleで日本語が文字化けします。どうするか考え中です。

Ruby on Railsはバージョン管理が大変

Ruby on Railsチュートリアルをやり始めました。開発環境は、Ruby 2.4.0p0[x64-mingw32] + MSYS2です。

ちなみに、これまでRuby 2.4.0ではRailsがインストールできませんでした。nokogiri 1.7.2がRuby 2.3系しか対応していなかったためです。

2017/6/5になってnokogiri 1.8.0がリリースされてようやくインストールできるようになりました。

チュートリアルをやり始めてすぐエラーが出ました。

key must be 32 bytes

ということで、こちらの情報をもとにRailsを5.0.1に変更しました。

でも、これでHerokuにデプロイしてみるとH20(App boot timeout)というエラーになります。起動に時間がかかりすぎているというエラーです。

そこで、Railsのバージョンを5.0.3にしました。すると、普通に起動するようになりました。

Gemfile

gem 'Rails', '5.0.3'

また、rails testでエラーになります。こちらの情報をもとにminitestを5.10.1に指定しました。

minitestの5.10.2でtestが動作しないときに試すこと

これで、とりあえず動いています。

なんだか、少しバージョンが違っただけで動いたり動かなかったりするんですね。

このほかにも、win32consoleを入れた方がいいというメッセージが出て入れてみたりしました。rails testの時に色がつくそうです。

Herokuにデプロイしてみると、Windowsで作られたGemfile.lockは使えませんということで、作り直してくれているようです。RubyをWindowsで使うのはなかなか難しいなと思います。

Django Girls Tutorialをやり終えて

Django Girls Tutorialをやり終えました。

このTutorialの良いところは、Webアプリケーションを作る過程を一通りできることです。

作ったアプリケーションをHerokuで公開するところまで含まれていますので、簡単そうでしたが結構骨が折れました。

実際にやってみないとわからないことが多くありました。

Djangoを触ってみて一番驚いたのは、データの削除をするとき関連するデータまで削除してくれることです。

Tutorialの中で、ブログの記事とコメントを作るのですが、記事を削除すると関連する複数あったコメントまで同時に削除してくれます。データベースを見て確認しました。

自分で関連するコメントを選別して削除する必要はありませんでした。

データベースをきれいに保つには欠かせないと思います。

困った点は、Django Girls Tutorialの日本語版はバージョンが古いらしく、英語版のDjango Girls Tutorial:extensionsをやろうとすると、修正が必要だったことです。ただ、その原因を突きとめる過程で学ぶことが多くありました。

PythonでWebアプリケーションを作りたいとなったときに、Djangoを最初に学ぶには良いTutorialではないかと思います。

Django Girls Tutorial:ExtensionsでNoReverseMatchが出た時の対処法

Django Girls TutorialでDjango Girls Tutorail:ExtensionsのHomework: add more to your website!をやっていた時のこと。

Delete postという項目でpost_remove()という関数を作ってブログを削除するボタンを作りました。

でも、記事の削除はできるのですが、次のようなエラーになりブログのトップに戻りません。

NoReverseMatch at /post/24/remove/
Reverse for 'post_list' not found. 'post_list' is not a valid view function or pattern name.

実は、Django Girls Tutorial:ExtensionsはTutorial本体とはバージョンが違っていて、urls.pyの指定が間違っていました。blog/urls.pyのurlの指定のところで下のようにname='post_list'を付け加えないといけませんでした。

blog/urls.pyの変更前

urlpatterns = [
    url(r'^$', views.post_list),
]

blog/urls.pyの変更後

urlpatterns = [
    url(r'^$', views.post_list, name='post_list'),
]

views.pyファイルの中のredirect('post_list')で指定する値は、urlのnameの値になります。

nameに指定してあるから、redirectを呼んだ時urlがブログのトップページ'/'だとわかり、views.post_list関数が呼ばれます。

日本語版のTutorialをやったあとExtensionsをやっていて原因を見つけるのに時間がかかったので報告しておきます。

英語版をやっている人は問題ないです。

HerokuでGoogle Fontsを使うときはHTTPSが必要

HerokuでDjango Girls Tutorialを作ったときにGoogle Fontsを使ってみました。

ローカルではうまく表示されるのですが、Herokuへデプロイするとなぜかフォントが使われていません。

CSSでstyleを設定する前にGoogle Fontsを読み込まなければならないという情報もあり、stylesheetの読み込み順序を変えてみても、表示は変わりませんでした。なにより、ローカルで動いているのでソースコードが間違っているとは思いにくいです。結局、Herokuで使うときはHTTPSを使わないといけませんでした。

<link href="https://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">

このように、httpsで始まるようにします。

Chromeの開発者ツールで見てみると、一番下のコンソールのところにhttpはHerokuで使えませんと出ていました。見落としていました。

Djangoで静的ファイルが見つからないときの探し方

Djangoを使っていて、CSSなどの静的ファイル(staticファイル)が見つからないときは次のようにするといいです。

css/blog.cssを探す場合、コンソールで次のように打ちます。

python manage.py findstatic --verbosity 2 css/blog.css

すると、次のように表示されます。

Found 'css/blog.css' here:
  /home/hoge/djangogirls/static/css/blog.css
Looking in the following locations:
  /home/hoge/djangogirls/static
  /home/hoge/djangogirls/myvenv/lib/python3.4/site-packages/django/contrib/admin/static

見つかるとFoundで表示してくれますし、見つからなくても探している場所を表示してくれますので確認しやすいと思います。

アプリケーションの場所のstaticディレクトリは、自動で探しにいくようです。

settings.pyのSTATICFILES_DIRでstaticファイルの場所を指定している場合など、場所の確認ができます。

Django Girls Tutorialでmigrateできない

Django Girls TutorialでHerokuへのデプロイをやったときのこと。

heroku run python manage.py migrate

は成功するのですが、

heroku run python manage.py createsuperuserがエラーになりました。

auth_nameが無いといわれます。no such tableだそうです。このようなエラーが出ます。

You have 14 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, blog, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

Traceback (most recent call last):
  File "/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/app/.heroku/python/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such table: auth_user

原因は、.gitignoreのlocal_settings.pyをsetingとミススペルしていたことでした。

Django Girls Tutorialでは、local_settings.pyがあればローカルのSqlite3を使い、herokuにはこのファイルをpushしないことでPostgreSQLを使うことにしています。

ところが、.gitignoreで指定できなかったため、herokuの方にlocal_settings.pyが転送されて、データベースとしてSqlite3が使われることになってしまいました。migrate時にエラーにならないのですが、データベースファイルができないらしく、tableがないというエラーになっていました。

リモートのファイルのみを消すには、

git rm --cached mysite/local_settings.py

git commit -m "Deleted remote local_settings.py."

git push heroku master

で消すことができました。

デプロイするだけでもいろいろトラブルになるんですね。

HerokuがWindowsで使えないときの対処法

PythonのDjangoに興味があり、Django Girls Tutorialというサイトを見てTutorialをやってみました。

Tutorialでは、Djangoの使い方の紹介とともに、Herokuでアプリを公開することもレッスンに含まれています。

そこで、はまったことを紹介します。

SSHキーの保存場所

heroku keys:add で作成される公開キーの保存場所は、C:/Users/(your name)/.ssh/id_rsa.pubです。MSYS2のMinGW 64-bitを使っていたのですが、MSYS2のホームディレクトリにある~/.ssh/のキーが使われませんでした。

Gitでheroku CLIのものを使う場合

heroku CLIというherokuコマンドを含むtoolがあるのですが、一緒にGitもインストールされます。最初MSYS2のgitをつかってgit push heroku masterしても、usernameとpasswordを聞かれてしまいすんなりとpushできません。

heroku loginでEmailとPasswordを聞かれてログインしているはずですが、認識していません。

結局heroku CLIでインストールされたGitを使うとusernameが聞かれなくなりました。

MSYS2のGitを使う場合は_netrcを.netrcにコピーする

heroku loginで認証したときのユーザー名やパスワードの情報は、ホームディレクトリの~/_netrcというファイルに保存されているようです。

MSYS2のGitを使えないか試してみて、ホームディレクトリの~/_netrc を~/.netrcにコピーすると使えることがわかりました。Heroku CLIのGitも使いたいときは_netをそのままにしておいた方がいいようです。

Pythonのバージョンとpsycopg2のバージョン

MSYS2のPythonは、3.4.5です。Django Girls Tutorialでは3.5.2を指定するよう書かれているので、runtime.txtに書いてgit pushしてみましたが、エラーで動きません。

エラーはpsycopg2をインストールするときに出て、ImportError: No module named 'six'となっています。

remote:            Traceback (most recent call last):
remote:              File "<string>", line 1, in <module>
remote:              File "/tmp/pip-build-799m2cq_/psycopg2/setup.py", line 583, in <module>
remote:                ext_modules=ext)
remote:              File "/app/.heroku/python/lib/python3.5/distutils/core.py", line 148, in setup
remote:                dist.run_commands()
remote:              File "/app/.heroku/python/lib/python3.5/distutils/dist.py", line 955, in run_commands
remote:                self.run_command(cmd)
remote:              File "/app/.heroku/python/lib/python3.5/distutils/dist.py", line 974, in run_command
remote:                cmd_obj.run()
remote:              File "/app/.heroku/python/lib/python3.5/site-packages/setuptools/command/install.py", line 61, in run
remote:                return orig.install.run(self)
remote:              File "/app/.heroku/python/lib/python3.5/distutils/command/install.py", line 551, in run
remote:                self.run_command(cmd_name)
remote:              File "/app/.heroku/python/lib/python3.5/distutils/cmd.py", line 313, in run_command
remote:                self.distribution.run_command(command)
remote:              File "/app/.heroku/python/lib/python3.5/distutils/dist.py", line 974, in run_command
remote:                cmd_obj.run()
remote:              File "/app/.heroku/python/lib/python3.5/site-packages/setuptools/command/install_scripts.py", line 17, in run
remote:                import setuptools.command.easy_install as ei
remote:              File "/app/.heroku/python/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 49, in <module>
remote:                from setuptools.py27compat import rmtree_safe
remote:              File "/app/.heroku/python/lib/python3.5/site-packages/setuptools/py27compat.py", line 7, in <module>
remote:                import six
remote:            ImportError: No module named 'six'
remote:
remote:            ----------------------------------------
remote:          Rolling back uninstall of psycopg2
remote:        Command "/app/.heroku/python/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-799m2cq_/psycopg2/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-dpg0rw8e-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-799m2cq_/psycopg2/
remote:  !     Push rejected, failed to compile Python app.
remote:
remote:  !     Push failed

仕方がないので、sixをrequirements.txtに加えましたがエラーのままです。

runtime.txtの設定でpython-3.4.5をにしてみると、pipのインストールでエラーになります。No such file or directoryだそうです。
pythonのバージョンを下げるのは得策ではないようです。

remote: -----> Installing requirements with pip
remote:        /app/tmp/buildpacks/779a8bbfbbe7e1b715476c0b23fc63a2103b3e4131eda558669aba8fb5e6e05682419376144189b29beb5dee6d7626b4d3385edb0954bffea6c67d8cf622fd51/bin/steps/pip-install: line 7: /app/.heroku/python/bin/pip: No such file or directory
remote:  !     Push rejected, failed to compile Python app.
remote:
remote:  !     Push failed

pythonを3.6.1にしてもpsycopg2のエラーは変わりませんでした。

Django Girls Tutorialではpsycopg2のバージョンは、2.5.4を指定するようになっています。これを2.6や2.6.1にしてもエラーは変わりませんでした。

いろいろ試してみて結局psycopg2のバージョンを2.7.1にあげることでデプロイが成功しました。pythonのバージョンは、3.5.2と3.6.1のどちらでもよかったです。

requirements.txt

dj-database-url==0.4.2
Django==1.11
gunicorn==19.7.1
pytz==2017.2
whitenoise==3.3.0
psycopg2==2.7.1

Pythonを始めると、virutalenvやvenvといった仮想環境を使ってモジュールのバージョン管理をすることが推奨されていますが、バージョンが合わないとアプリケーションが動かなくなることが納得できました。

Herokuがうまく動かないときの情報が検索してもあまり出てこないので本当に困りました。

MSYS2でansibleを使うときの訂正とpythonのvirtualenvとvenv

MSYS2でansibleを使うときは32bit版ではなくて、インストールするパッケージがmsysのpythonであることが必要でした。
以前の記事を訂正しました。

pythonのバージョンを管理する、python3のvenvやpython2のvirutalenvも、msys用のpythonだと動きますがMinGW用のpythonだと動きません。

スタートメニューのMSYS2 MinGW 32-bitや、MSYS2 MinGW 64-bitのコンソールでは、MinGW用のpythonがインストールしてあるとそちらが優先的に実行されてしまうので注意してください。

msys用のpythonはpipが用意されていませんので、get-pip.pyをcurlでインストールします。

python2の場合、pipでvirtualenvをインストールします。そのうえで-m virtualenvでモジュールを指定して実行します。適当な名前myvenvを指定すると、myvenv/bin/以下にpythonやpipがコピーされます。activateをbashに読み込ませると開発環境が変わります。

カッコつきで(myvenv)のように表示されるとOKです。

deactivateで元に戻ります。

$ pacman -S python2

$ curl -kL https://bootstrap.pypa.io/get-pip.py | python2
$ pip install virtualenv

$ mkdir test
$ cd test
$ python2 -m virtualenv myvenv
$ source myvenv/bin/activate

(myvenv)

$ deactivate

python3をpython2と同居させる場合、pipコマンドをpython2のようにインストールすると、/usr/bin/pipが上書きされてしまいます。
そのため、venvというモジュールを使ってローカルのフォルダにpip関係のモジュールを入れて隔離したほうがいいです。

python2は、virtualenvをpipでインストールしないといけないので、グローバルにインストールするしかないです。

適当な名前myvenvを指定してpython3 -m venvを実行するとpython3の実行ファイルとpipがコピーされて使えるようになります。

$ pacman -S python

$ mkdir python3test
$ cd python3test
$ python3 -m venv myvenv
$ source myvenv/bin/activate

(myvenv)

$ deactivate

python2とpython3でpipをインストールすると、pipは後にインストールしたほうになります。先にインストールした方は、pip2もしくはpip3で指定しないといけないです。

混在するのはよくないので、pipはpython2のみでインストールし、python3は-m venvで仮想環境を作ったときに自動でインストールされるpipを使うのがよいです。

最近開発されたハイパーバイザー

PhoronixというニュースサイトでBareflankというハイパーバイザーが開発されていることを知りました。

調べていくと、最近いろいろなハイパーバイザーが開発されているようです。今回はそれを紹介します。

ハイパーバイザー

Bareflank

セキュリティーなどに応用するためのプロトタイプを目的とする。C++、STLで書かれている。ユニットテストが完備されていて、Coveralls、Travis CI、Astyleが使われていて、Coverity、Clang Tidy、Google's Sanitizersといったところでコードを分析している。

サポートするのは、SandyBrdge以降のCPU。
ホストOSは、
Ubuntu 16.10
Debian Stretch
Fedora 25, 24
OpenSUSE Leap 42.2
Windows 10
Windows 8.1

少しソースコードを見ると、WindowsホストではCygwinでカーネルドライバーを作るようになっていたり、self signをできるようにしていたりと本格的です。

シンプルなハイパーバイザーを目指しているようです。機能を拡張する方法があるようで、次の2つが挙げられています。

Extended APIs

BareflankにVPIDとかMSR bitmapにアクセスするためのAPIなどを提供するもの。

Hyperkernel

他の人が自分のハイパーバイザーを開発できるように、Bareflankのサポートソフトとして開発されている。

MoRE

Windows 7 32-bit で、CPUコアは1、メモリ2GBで動作。WinDDKを使っている。3年前に開発が止まっているようです。

SimpleVisor

Intel x64/EM64T VT-xで動く、シンプルなハイパーバイザー。アセンブリコードは10行、ホストのハイパージャックとアンハイパージャックをサポート。ホストの状態を仮想化できるそうです。EPTとVPIDをサポート。WindowsとUEFI環境で動くそうです。Cのコードは500行、総コード数1700行だとか。

VisualStudio 2015 Update 3で作られる。ミニマルなハイパーバイザーを目指しているそうです。

HyperPlatform

Intel VT-x上でのハイパーバイザー。rootkitや、侵入検知システム、Windowsカーネルのリバースエンジニアリングを目的とする。

Visual Studio Community 2015 Update 3、Windows SDK、Windows Driver Kitで作られる。

ksm

Cで書かれた軽量なx64ハイパーバイザー。WindowsとLinuxホストサポート。WindowsではMinGWを使っています。

まとめ

どれもゲストOSを動かすというより、セキュリティ分野での応用を目指しているようです。CPUのVT-x機能を使う方法など、勉強したい方にはコードが簡単でいいのではないかと思います。VirtualBox、Xen、KVMといったプログラムのコードは複雑ですので。