ローカルマシンで開発したPython3 on pyenv with pipenvな常駐プログラムのGitリポジトリを、Bitbucketのプライベートリポジトリにリモートマスターを作成してプッシュして、ConoHaのサーバーにgit clone して動かすまで


長ったらしいタイトルだけど、何の記事か後から振り返った時に思い出せるようにw

ということで、2か月くらいローカルのMacbookでビットコインのトレードを自動化するボットを開発していて、そろそろ24時間365日動かし続けてみようということで、あまり活用していないConoHaサーバーにデプロイして動かそうとしている最中のメモ

(今、環境設定の作業自体は7割くらい終わっちゃっているけど、忘れないうちに作業内容を書き出しておく)

Bitbucketのセットアップとローカルリポジトリとの連携

https://bitbucket.org/ にアクセスして、プライベートなリポジトリを新規作成

ローカルのリポジトリからプッシュできるように自分のプロフィールにsshの公開鍵を登録しておく

リポジトリを作成するとローカルにクローンするか、既存のリポジトリのリモートリポジトリとして登録するかどうかの案内のメッセージが表示されるので、それに従い、すでに作成済みのローカルリポジトリで以下のコマンドを実行する

cd /path/to/repository/
git remote add origin [email protected]:user_account/new_repository.git

で、すでにソースコードがあり、上記ディレクトリ内でバージョン管理されているのでBitbucketに作成したリモート オリジンのリポジトリに push しちゃう

git push -u origin master

途中、ssh鍵のパスフレーズ聞かれるけど、それは、前段でBitbucketの新規リポジトリにプッシュできるように公開鍵を登録しておいたので、そのパスフレーズを入力する感じ

以下のようなメッセージが表示されれば、無事、Bitbucketのリモートリポジトリにプッシュできたことになる

To bitbucket.org:user_account/new_repository.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

BitbucketのリポジトリからConoHa上にクローン

Bitbucketのリポジトリから git clone するため、適当なディレクトリを用意する

Bitbucketのリポジトリはプライベートなため、あらかじめローカルの鍵の公開鍵をBitbucketのリポジトリ側に登録しておく

そのため、ConoHa上で git clone するユーザーのSSHの鍵を作成
むろん、パスフレーズも登録しておく

ssh-keygen -t rsa -b 4096

生成した鍵は、 /home/user/.ssh/id_rsa.pub とかで出力されているので、catviewでファイルを開いて中身をコピーするか、cat ~/.ssh/id_rsa.pub | pbcopyでクリップボードに保存しておき、Bitbucketのリポジトリの設定より、アクセスキーとして登録

ここまで準備ができれば、あとは、クローンするディレクトリに移動して、git cloneするだけ

cd /path/to/git_clone_directory
git clone [email protected]:user_account/new_repository.git

Python環境のセットアップ

ConoHaで標準で入っているPythonはバージョンが2.7で、ローカルで開発したのは、3.7だったので、それで動くようにしたい

Pythonの環境は、pipenvを利用するので、pippipenv をまずはインストール

# pip install pipenv

git cloneしてきたソースには、Pipfileが含まれているので対象のディレクトリに移動して、pipenv installすれば良いかなぁ... と思い、やってみたけど、以下のようなエラーが発生

$ cd /path/to/git_clone_directory
$ pipenv install
Warning: Python 3.7 was not found on your system...
You can specify specific versions of Python with:
  $ pipenv --python path/to/python

情報収集

以下のあたりを、ザーーッと読んで理解を深める

要は、pipenvだけインストールしてあってもダメで、裏で動く pyenv もないと自動で Python のバージョンまで揃えてくれない、ということかな

前段で pip install pipenv したけれど、 pyenv を入れて、そちらの Python で pipenv するのが良さそう

pyenvのインストール

インストール先は、 ~/.pyenv にしている例が多いけど、個別のアカウントのホームディレクトリ配下に入れるのは、なんか好きじゃないので /opt/pyenv にする

# git clone https://github.com/pyenv/pyenv.git /opt/pyenv

環境変数周りをイジって pyenv コマンドが適切に機能するように設定する

$ echo 'export PYENV_ROOT="/opt/pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l
mkdir: ディレクトリ `/opt/pyenv/shims' を作成できません: 許可がありません
mkdir: ディレクトリ `/opt/pyenv/versions' を作成できません: 許可がありません

exec $SHELL -l でエラーが出てしまった、どうやら /opt/pyenv/配下を操作するようなので... 他の例のように ~/.pyenv に配置する方が良さそう

ということで、やり直し

$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv

環境変数も周りをイジって pyenv コマンドが適切に機能するように設定する

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

話は変わるが... 設定ファイルが .bash_profile.bashrc どっち?という話もあるみたいだけど...

以下でバージョンが適切に表示されればOK

$ pyenv -v
pyenv 1.2.13

pyenvでPython3.7をインストール

リビジョン番号を指定せずに、マイナーまでの 3.7 でインストールしてみる

$ pyenv install 3.7
pyenv: no such command `install'
$ pyenv global 3.7

installコマンドが見つからないので... 検索して、同様のトラブルが発生している人を発見

要は、完全な一般ユーザーで pipenv w/ pyenv な環境構築って難しいのかもと思いつつ

$ .pyenv/plugins/python-build/install.sh
mkdir: ディレクトリ `/usr/local/share/python-build' を作成できません: 許可がありません

と、やはりエラーになったので、公式ページも見つつ

https://github.com/pyenv/pyenv/tree/master/plugins/python-build
This will install python-build into /usr/local. If you do not have write permission to /usr/local, you will need to run sudo ./install.sh instead. You can install to a different prefix by setting the PREFIX environment variable.

公式も sudo でやれということなので、やってみる

$ sudo ~/.pyenv/plugins/python-build/install.sh

あなたはシステム管理者から通常の講習を受けたはずです。
これは通常、以下の3点に要約されます:

    #1) 他人のプライバシーを尊重すること。
    #2) タイプする前に考えること。
    #3) 大いなる力には大いなる責任が伴うこと。

[sudo] user_name のパスワード:

って、そりゃそうだw sudo できるようにセットアップしてねーしw

公式サイトの以下が気になったので...

You can install to a different prefix by setting the PREFIX environment variable.

.pyenv/plugins/python-build/install.sh を覗いて見た

# Usage: PREFIX=/usr/local ./install.sh
#
# Installs python-build under $PREFIX.

あぁー、なるほど、ということで

$ PREFIX=~/.local ~/.pyenv/plugins/python-build/install.sh

上手くいったっぽいので、再度、pyenv install 3.7を実行したが...

$ pyenv install 3.7
python-build: definition not found: 3.7

The following versions contain `3.7' in the name:
  2.3.7
  3.3.7
  3.7.0
  3.7-dev
  3.7.1
  3.7.2
  3.7.3
  3.7.4
  miniconda-3.7.0
  miniconda3-3.7.0
  stackless-3.3.7

See all available versions with `pyenv install --list'.

If the version you need is missing, try upgrading pyenv.

$ pyenv install 3.7.4
Downloading Python-3.7.4.tar.xz...
-> https://www.python.org/ftp/python/3.7.4/Python-3.7.4.tar.xz
Installing Python-3.7.4...
WARNING: The Python bz2 extension was not compiled. Missing the bzip2 lib?
WARNING: The Python readline extension was not compiled. Missing the GNU readline lib?
WARNING: The Python sqlite3 extension was not compiled. Missing the SQLite3 lib?
Installed Python-3.7.4 to /home/user/.local/bin/~/.pyenv/versions/3.7.4

3.7.4 とリビジョン番号まで指定して、インストールが完了はしたけれど...
依存系で足りないものがったようなので、以下を実行して

# yum install gcc zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel

pyenv install 3.7.4 でインストールし直したところ、WARNING なしでインストール完了したので、以下も実行

$ pyenv global 3.7.4

問題なさそうなので、次に pipenv のインストールし直し(し直しというか、pyenv の環境下でインストール)

pyenv環境にpipenvをインストール

pip だけで、pyenv global 3.7.4 の Python の pip を使うことになるのかな? pyenv global 3.7.4したから、3.7.4pip が認識されるのだろう

$ pip install pipenv

上記を実行したいわけだけど、ユーザー環境で完結させるためには、実行コマンドの例として、pip install --user pipenv とユーザーディレクトリ配下にインストールする方法を取るのが良さそう

--user のオプションの有る無しの違いについては、以下のページが詳しく分かり易かった

$ pip install --user pipenv
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Requirement already satisfied: pipenv in /usr/lib/python2.7/site-packages (2018.11.26)
Requirement already satisfied: setuptools>=36.2.1 in /usr/lib/python2.7/site-packages (from pipenv) (41.0.1)
Requirement already satisfied: virtualenv in /usr/lib/python2.7/site-packages (from pipenv) (15.1.0)
Requirement already satisfied: enum34; python_version < "3" in /usr/lib/python2.7/site-packages (from pipenv) (1.1.6)
Requirement already satisfied: pip>=9.0.1 in /usr/lib/python2.7/site-packages (from pipenv) (19.2.1)
Requirement already satisfied: typing; python_version < "3.5" in /usr/lib/python2.7/site-packages (from pipenv) (3.7.4)
Requirement already satisfied: certifi in /usr/lib/python2.7/site-packages (from pipenv) (2019.6.16)
Requirement already satisfied: virtualenv-clone>=0.2.5 in /usr/lib/python2.7/site-packages (from pipenv) (0.5.3)
WARNING: You are using pip version 19.2.1, however version 19.2.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

ん? Python 2.7 って、想定と違う...

$ pyenv global 3.7.4
$ python --version
Python 2.7.5
$ pip --version
pip 19.2.1 from /usr/lib/python2.7/site-packages/pip (python 2.7)

pyenv global が機能していない... orz

原因は、.bash_profile の設定だったので編集して再設定して、読み込み直した上で、pyenvgit clone からやり直し

改めて、pyenvなpipenvでセットアップ

前項までの内容が上手くいっていれば、以下のコマンドも上手くいくはず!

$ cd /path/to/git_clone_directory
$ pipenv install
Creating a virtualenv for this project...
Pipfile: /opt/user/Pipfile
Using /home/user/.pyenv/versions/3.7.4/bin/python3.7m (3.7.4) to create virtualenv...
⠦ Creating virtual environment...Using base prefix '/home/user/.pyenv/versions/3.7.4'
New python executable in /home/user/.local/share/virtualenvs/script-UDmdRvaW/bin/python3.7m
Also creating executable in /home/user/.local/share/virtualenvs/script-UDmdRvaW/bin/python
Installing setuptools, pip, wheel...done.
Running virtualenv with interpreter /home/user/.pyenv/versions/3.7.4/bin/python3.7m

✔ Successfully created virtual environment! 
Virtualenv location: /home/user/.local/share/virtualenvs/script-UDmdRvaW
Installing dependencies from Pipfile.lock (6aaddf)...
An error occurred while installing pubnub==4.1.4 --hash=sha256:98b02b1fb3c08f95d50b05cd4ee58bb1ba2d3b858c355256d6c232fe4d3dad7c! Will try again.
An error occurred while installing graphql-relay==2.0.0 --hash=sha256:0e94201af4089e1f81f07d7bd8f84799768e39d70fa1ea16d1df505b46cc6335 --hash=sha256:75aa0758971e252964cb94068a4decd472d2a8295229f02189e3cbca1f10dbb5 --hash=sha256:7fa74661246e826ef939ee92e768f698df167a7617361ab399901eaebf80dce6! Will try again.
An error occurred while installing apistar==0.7.2 --hash=sha256:8da0d3f15748c8ed6e68914ba5b8f6dd5dff5afbe137950d07103575df0bce73! Will try again.
An error occurred while installing jinja2==2.10.1 --hash=sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013 --hash=sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b! Will try again.
An error occurred while installing graphql-server-core==1.1.1 --hash=sha256:e5f82add4b3d5580aa1f1e7d9f00e944ad3abe1b65eb337e611d6a77cc20f231! Will try again.
An error occurred while installing responder==1.3.1 --hash=sha256:717ad3d85999007066aac62ff822913452940f9679a8ae6b77597e2e7c841ec4 --hash=sha256:a8936a250620f99aa8f88813963d433f32c82acba81f1b45ae23f3dd84a3a219! Will try again.
An error occurred while installing uvicorn==0.8.4 --hash=sha256:5320b48629564fa914fe8120542608c91f98fcd2278e8454bda9db08467519d1! Will try again.
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 41/41 — 00:00:20
An error occurred while installing requests==2.22.0 --hash=sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4 --hash=sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31! Will try again.
Installing initially failed dependencies...
  ☤  ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 8/8 — 00:00:10
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

An error occurred while installing ... Will try again. と出ているのでエラーかと思いきや... スクリプトは実行できたので問題なさそう...

環境は、コレでOK

スクリプトの実行

ローカルPCでパラメーターの調整のためファイルを編集して、コミットして、リモートのマスターにpush

$ git push -u origin master
Warning: Permanently added the RSA host key for IP address '1234:abcd:1234::abcd:123' to the list of known hosts.
Enter passphrase for key '/Users/user_name/.ssh/id_rsa': 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 354 bytes | 354.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To bitbucket.org:account/repos.git
   d7862b3..28cff50  master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

スクリプトを動かすサーバー側では、最新のデータを取得

$ git pull origin master
Warning: Permanently added the RSA host key for IP address '1234:abcd:1234::abcd:1234' to the list of known hosts.
Enter passphrase for key '/home/user_name/.ssh/id_rsa': 
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From bitbucket.org:account/repos
 * branch            master     -> FETCH_HEAD
Updating d7862b3..28cff50
Fast-forward
 v.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

スクリプトを実行したら、logsディレクトリがないと怒られたw

$ pipenv run python ./script.py
Traceback (most recent call last):
  File "./script.py", line 452, in <module>
    filename="./logs/script_debug.log",
  File "/home/user/.pyenv/versions/3.7.4/lib/python3.7/logging/__init__.py", line 1895, in basicConfig
    h = FileHandler(filename, mode)
  File "/home/user/.pyenv/versions/3.7.4/lib/python3.7/logging/__init__.py", line 1087, in __init__
    StreamHandler.__init__(self, self._open())
  File "/home/user/.pyenv/versions/3.7.4/lib/python3.7/logging/__init__.py", line 1116, in _open
    return open(self.baseFilename, self.mode, encoding=self.encoding)
FileNotFoundError: [Errno 2] No such file or directory: '/opt/user/logs/script_debug.log'

ディレクトリを作成

$ mkdir /path/to/logs/

スクリプトは、バックグラウンドで実行

$ nohup pipenv run python ./script.py &

初回 nohup をつけ忘れたので以下の手順でスクリプトを一時停止させてからバックグラウンド処理に変更

$ pipenv run python ./script.py
^Z
[1]+  停止                  pipenv run python ./script.py

$ jobs
[1]+  停止                  pipenv run python ./script.py

$ bg 1
[1]+ pipenv run python ./script.py &

$ jobs
[1]+  実行中               pipenv run python ./script.py &

$ disown %1

$ jobs
$ ps -Af

上手く動いている様子