◆省電力なWOLServer(WakeOnLANサーバー)を作成◆ WOLServerの導入
いよいよこのレシピの芯になる手順です。「Nginx」のWebサーバーを導入し、フレームワークとして「uWSGI+Django」、そして「Python」で書かれたWOLServerを、Raspberry Pi のOS「Raspbian」に導入していきます。
きっちりとサーバーを構成する重厚な内容となっておりますが、途中まではPythonのWeb開発環境をRaspberryPiに構築する手順としても活用いただけると思います。
◆ 目次 ◆
◆ 1. Pythonの仮想環境構築 ◆
◆ 1-1. 標準搭載のPythonのバージョンを確認 ◆
まずは以下のコマンドで標準搭載のPythonのバージョンを確認します。
pi@raspberrypi:~ $ python3 -V[ENTER]
|
◆ 1-2. gitを使ってpyenvをインストール ◆
◆ 1-3. ビルドに必要なライブラリをインストールします ◆
ライブラリをインストール
pi@raspberrypi:~ $ sudo apt-get install -y make build-essential libssl-dev \
zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl \
llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev[ENTER]
|
◆ 1-4. pyenvを使ってPython3.7.3をインストール ◆
pyenvを使ってPython3.7.3をインストールし、pyenvでPython3.7.3をデフォルトの設定にします。
pi@raspberrypi:~ $ source ~/.bash_profile[ENTER]
pi@raspberrypi:~ $ pyenv install 3.7.3[ENTER]
pi@raspberrypi:~ $ pyenv global 3.7.3[ENTER]
|
Pythonが3.7.3になっていることを確認
pi@raspberrypi:~ $ python -V[ENTER]
|
◆ 1-5. pipenvをインストール ◆
※pipenvとはPython公式のパッケージ管理ツールです。
先にpipを最新版にアップグレードします
pi@raspberrypi:~ $ pip install --upgrade pip[ENTER]
|
pipenvをインストールします
pi@raspberrypi:~ $ pip install pipenv[ENTER]
|
◆ 1-6. 仮想環境の構築 ◆
※今回は/home/pi 上にmywebディレクトリを作成し、そこに仮想環境を構築します。
仮想環境を構築後、DjangoとuWSGIをインストールしていきます。
# 3.7.3で仮想環境構築
pi@raspberrypi:~ $ mkdir myweb[ENTER]
pi@raspberrypi:~ $ cd myweb[ENTER]
# 3.7.3で仮想環境構築
pi@raspberrypi:~/myweb $ pipenv install --python 3.7.3[ENTER]
# 仮想環境にDjangoをインストール
pi@raspberrypi:~/myweb $ pipenv install Django[ENTER]
# 仮想環境にuwsgiをインストール
pi@raspberrypi:~/myweb $ pipenv install uwsgi[ENTER]
|
◆ 1-7. 作成した仮想環境を実行 ◆
#仮想環境を実行します。
pi@raspberrypi:~/myweb $ pipenv shell[ENTER]
(myweb) pi@raspberrypi:~/myweb $
|
仮想環境実行後はターミナルの表示の先頭が(myweb)になっているはずです。これは仮想環境(myweb)を実行中である、という事を示しています。
なお、仮想環境から抜ける際は exit を入力すれば抜けられます。
以上で、Pythonの仮想環境構築は完了です。
◆ 2. Djangoプロジェクトの作成 ◆
※先程仮想環境にインストールしたDjangoを使いDjangoプロジェクトを作成します。
この手順ではプロジェクト名をmywebとします。
今回のプロジェクト用に作成したmywebディレクトリにプロジェクトを作成します。
プロジェクトが作成されると、mywebフォルダ上にプロジェクトのフォルダ(myweb)が生成されます。
◆ 2-1. プロジェクト(myweb)の作成◆
以下のコマンドでプロジェクトを作成します。
# 仮想環境になっていない場合は$ pipenv shell #で仮想環境を実行してから実施します。
(myweb) pi@raspberrypi:~/myweb $ django-admin.py startproject myweb
|
◆ 2-2. プロジェクト(myweb)の確認 ◆
◆ 3. 必要なモジュールのインストール ◆
◆ 3-1. Pythonまわりのモジュール◆
# パッケージリストの更新
(myweb) pi@raspberrypi:~/myweb $ apt-get update
# インストール
(myweb) pi@raspberrypi:~/myweb $ sudo apt-get -y install python-dev \
python-pip
|
◆ 3-2. pipを使ってuwsgiモジュールをインストール ◆
# インストール
(myweb) pi@raspberrypi:~/myweb $ sudo pip install -U pip
(myweb) pi@raspberrypi:~/myweb $ pip install django uwsgi
|
◆ 3-3. パスを通す ◆
(myweb) pi@raspberrypi:~/myweb $ vi .bashrc
|
一番下に以下追加
export PATH="$PATH:~/.local/bin"
|
設定を反映
(myweb) pi@raspberrypi:~/myweb $ source .bashrc
|
パスが通っているか確認
(myweb) pi@raspberrypi:~/myweb $ echo $PATH
|
/home/pi/.pyenv/shims:/home/pi/.pyenv/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:~/.local/bin
^^^^^^^^^^^^
|
再起動後もパスが通っているか確認
(myweb) pi@raspberrypi:~/myweb $ sudo reboot
|
pi@raspberrypi:~ $ cd myweb
pi@raspberrypi:~/myweb $ pipenv shell
(myweb) pi@raspberrypi:~/myweb $ echo $PATH
|
/home/pi/.pyenv/shims:/home/pi/.pyenv/bin:/usr/local/sbin:/usr/local/bin:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:~/.local/bin
^^^^^^^^^^^^
|
◆ 4. uWSGIの動作確認 ◆
◆ 4-1. /home/pi/myweb/myweb にtest.pyを作成◆
/home/pi/myweb/myweb にtest.pyを作成し、以下の内容を入力して保存します
(myweb) pi@raspberrypi:~/myweb $ cd ./myweb # mywebディレクトリに移動
(myweb) pi@raspberrypi:~/myweb/myweb $ vi test.py
|
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
|
◆ 4-2. uWSGIを起動◆
#uWSGIを起動
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --http :8000 --wsgi-file test.py
|
*** Starting uWSGI 2.0.18 (32bit) on [Sun May 3 19:08:42 2020] ***
compiled with version: 8.3.0 on 16 July 2019 12:06:45
os: Linux-4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019
nodename: raspberrypi
machine: armv7l
clock source: unix
pcre jit disabled
detected number of CPU cores: 4
current working directory: /home/pi/myproject/mysite
detected binary path: /home/pi/.local/share/virtualenvs/myproject-O4qzz3q6/bin/uwsgi
*** WARNING: you are running uWSGI without its master process manager ***
your processes number limit is 5909
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :8000 fd 4
spawned uWSGI http 1 (pid: 16747)
uwsgi socket 0 bound to TCP address 127.0.0.1:42361 (port auto-assigned) fd 3
Python version: 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0]
*** Python threads support is disabled. You can enable it with --enable-threads ***
Python main interpreter initialized at 0x1211b70
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 64400 bytes (62 KB) for 1 cores
*** Operational MODE: single process ***
WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x1211b70 pid: 16746 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 16746, cores: 1) |
◆ 4-3. ブラウザでアクセス確認◆
※RaspberryPiからRaspbianのブラウザChomiumで「http://127.0.0.1:8000」に接続し、「Hello World」がブラウザに表示されれば、正常に動作しています。
※確認できればプロセスはターミナルからCTRL+Cで停止してください。
◆ 5. Djangoプロジェクトでテスト ◆
◆ 5-1. Djangoテストコマンドの実行◆
# 下記コマンドをプロジェクトの(myweb)ディレクトリで実行してください。
(myweb) pi@raspberrypi:~/myweb/myweb $ python3 manage.py runserver
|
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
May 03, 2020 - 10:18:11
Django version 3.0.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
|
◆ 5-2. Djangoサイトをブラウザで確認◆
※RaspberryPiからRaspbianのブラウザChomiumで「http://127.0.0.1:8000」に接続し、以下の通りブラウザに表示されれば、正常に動作しています。
※確認できればプロセスはターミナルからCTRL+Cで停止してください。
◆ 5-3. uWSGIでDjangoサイトを実行◆
※mywebディレクトリで下記コマンドを実行してください。
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --http :8000 --module myweb.wsgi
|
◆ 5-4. uWSGI経由でDjangoサイトをブラウザで確認◆
※RaspberryPiからRaspbianのブラウザChomiumで「http://127.0.0.1:8000」に接続し、先程表示したDjangoサイトが表示できれば、uWSGI経由でDjangoプロジェクトを呼び出すことが出来たことになります。
※確認できればプロセスはターミナルからCTRL+Cで停止してください。
◆ 6. アプリケーションの作成 ◆
◆ 6-1. アプリケーション(hello)の作成◆
# プロジェクトのディレクトリ(myweb)で以下の通り入力しアプリケーション(hello)を作成します。
(myweb) pi@raspberrypi:~/myweb/myweb $ python manage.py startapp hello
|
ディレクトリ構成は以下となります。
(myweb) pi@raspberrypi:~/myweb/myweb $ tree --charset=x
|
.
|-- db.sqlite3
|-- hello
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- migrations
| | `-- __init__.py
| |-- models.py
| |-- tests.py
| `-- views.py
|-- manage.py
|-- myweb
| |-- __init__.py
| |-- asgi.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- test.py
|
◆ 6-2. アプリケーション(hello)の登録◆
アプリケーションをプロジェクトに含めるには、構成クラスへの参照を
INSTALLED_APPS設定に追加する必要があります。
INSTALLED_APPS設定は作成したプロジェクトディレクトリ(myweb)内のさらに(myweb)内(settings.py)にありますので、こちらに追記します。
ここからはカレントディレクトリをプロジェクトのディレクトリ(myweb)
※/home/pi/myweb/myweb
として、そこからの相対パスで記載します。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi myweb/settings.py
|
:
:
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hello', #<--追記
]
:
:
|
◆ 6-3. viewの編集◆
※viewではどのページを表示するかを決定する処理をしていますので、これを編集します。
※Djangoは設計思想について「MTVモデル」を採用しています。
MTVとは、
- Model(データベースに格納されているデータ)
- Template(テンプレートファイルによって定義されたページのデザイン)
- View(どのページを表示させるかを決定する処理)
を組み合わせて設計を行う考え方となります。
viewはアプリケーション(hello)ディレクトリにあります。(views.py)になりますので、これを編集します。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi hello/views.py
|
from django.shortcuts import render
# Create your views here.
|
ここでは、以下の通り編集し全体を書き換えます。
from django.http import HttpResponse
def main(request):
return HttpResponse("Hello!")
def linux_memo(request):
return HttpResponse("linux-memo.net!")
|
◆ 6-4. URLの紐付け◆
※viewができれば、views.pyとURLを紐付けます。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi hello/urls.py
# まずはviewと同じディレクトリ(hello)にurls.pyを作成します。以下の通り記入
|
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^linux-memo', views.linux_memo, name='linux_memo'),
url(r'^$', views.main, name='main'),
]
|
※/hello/で来たら「Hello!」を表示する「main」関数を
※/hello/linux-memoで来たら「linux-memo.net!」を表示する「linux_memo」関数を(関数に使えない記号'-'ハイフンではなく'_'アンダーバーとなっている点に注意)
※myweb/urls.pyも編集する必要があります。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi myweb/urls.py
|
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
|
以下の通り編集します。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')), #<--追記
]
|
※紐付けは「どっとつなぎのパス」を入れて表現します。
(hello.urls)は「hello」ディレクトリ内の「urls.py(urls)」を指し、(hello/)は「URLが(hello/)の場合」を意味します。
◆ 6-5. マイグレーションを行いDjangoへモデルの変更の保存を指示◆
以下のコマンドでマイグレーションを行いDjangoへモデルの変更を保存する指示を出します。
(myweb) pi@raspberrypi:~/myweb/myweb $ manage.py migrate
# エラーがなければ、以下の通り表示されます。
|
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying sessions.0001_initial... OK
|
◆ 6-6. アプリケーションの確認◆
アプリケーションができたので、以下の通り入力しサーバーを起動します。
(myweb) pi@raspberrypi:~/myweb/myweb $ python manage.py runserver \
0.0.0.0:8000
# 以下の通り表示されます。
|
Performing system checks...
System check identified no issues (0 silenced).
May 05, 2020 - 05:29:27
Django version 1.11.29, using settings 'myweb.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
|
下記のページをローカルRaspbianのブラウザで開いて'hello!'がでたらOK!
http://127.0.0.1:8000/hello/
下記のページをローカルのブラウザで開いて'linux-memo.net!'がでたらOK!
http://127.0.0.1:8000/hello/linux-memo
※ローカルのブラウザで開かないと、別のパソコンからの接続はALLOWED_HOSTS
に設定を入っていないためアクセスが拒否されエラーとなります。
※確認が終わればターミナルのプロセスはCONTROL+Cで抜けてください。
◆ 7. uWSGIでの動作確認 ◆
WSGIはWebサーバとWebアプリケーションを接続するためのインターフェース定義の一つで、uWSGIはWSGIコンテナの機能をもったwebサーバーになります。
◆ 7-1. [the web client] <-> uWSGI <-> Django◆
以下のコマンドでuWSGIを起動します。
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --http :8000 --module myweb.wsgi
|
下記のページをローカルRaspbianのブラウザで開いて'hello!'がでたらOK!
http://127.0.0.1:8000/hello/
下記のページをローカルのブラウザで開いて'linux-memo.net!'がでたらOK!
http://127.0.0.1:8000/hello/linux-memo
※確認が終わればターミナルのプロセスはCONTROL+Cで抜けてください。
◆ 7-2. 一旦仮想環境から抜ける◆
以下のコンソールになっていると思いますので、
(myweb) pi@raspberrypi:~/myweb/myweb $
|
以下のコマンドで一旦仮想環境から出ます
(myweb) pi@raspberrypi:~/myweb/myweb $ exit
|
すると、コンソールが以下のようになり、仮想環境から出たことになります。
◆ 8. Nginxのインストール ◆
◆ 8-1. Nginxのインストール ◆
以下のコマンドでNginxをインストールします。
pi@raspberrypi:~/myweb $ sudo apt install nginx
|
◆ 8-2. Nginxの起動 ◆
以下コマンドでNginxを起動します。
pi@raspberrypi:~/myweb $ sudo /etc/init.d/nginx start
# 起動が成功すると以下が表示されます
[ ok ] Starting nginx (via systemctl): nginx.service.
|
◆ 8-3. Nginxへの接続の確認 ◆
起動が成功したら http://127.0.0.1:80 にアクセスしてください。
正常に動いていれば下の"Welcome to nginx!"ページが表示されるはずです。
◆ 9. nginx + uWSGIでの動作確認 ◆
※今回はnginxが8000番ポートでブラウザからリクエストを受け取り、8001番ポートで待ち受けているuWSGIにsocketで受け渡す構成で確認(webサーバーがnginxで、WSGIコンテナがuWSGI)します。
the web client <-> the web server <-> the socket <-> uWSGI <-> Django
◆ 9-1. nginxのuwsgiモジュール用の設定を行う ◆
uwsgi_paramsをプロジェクトディレクトリ(myweb)に新規作成します。
pi@raspberrypi:~/myweb $ cd ~/myweb/myweb
pi@raspberrypi:~/myweb/myweb $ vi uwsgi_params
|
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
|
◆ 9-2. Nginxの設定ファイルを作成 ◆
Nginxの設定ファイルを作成します。Nginxは起動時にディレクトリ
に入っている設定ファイルを読み込みます。
今回はプロジェクトディレクトリ(myweb)にmyweb_nginx.confを作成し、
にmyweb_nginx.confへのシンボリックリンクを貼ることで構成します。
まずはmyweb_nginx.confを新規に作成します。
pi@raspberrypi:~/myweb $ cd ~/myweb/myweb
pi@raspberrypi:~/myweb/myweb $ vi myweb_nginx.conf
|
# the upstream component nginx needs to connect to
upstream django {
# server unix:///home/pi/myweb/myweb/myweb.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name example.com; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
location /static {
alias /home/pi/myweb/myweb/static; # your Django project's static files - amend as required
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /home/pi/myweb/myweb/uwsgi_params; # the uwsgi_params file you installed
}
}
|
以下でシンボリックリンクを張ります。
pi@raspberrypi:~/myweb $ sudo ln -s ~/myweb/myweb/myweb_nginx.conf \
/etc/nginx/sites-enabled/
|
◆ 9-3. staticフォルダを展開 ◆
myweb/settings.pyにSTATIC_ROOTを指定します。
pi@raspberrypi:~/myweb $ vi myweb/settings.py
|
# 以下を最終行に追記
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
|
starticフォルダ展開
# 仮想環境に入る
pi@raspberrypi:~/myweb $ pipenv shell
(myweb) pi@raspberrypi:~/myweb $ cd ~/myweb/myweb
(myweb) pi@raspberrypi:~/myweb/myweb $ python manage.py collectstatic
|
◆ 9-4. フォルダ構成の確認 ◆
※特にstartcフォルダにたくさんのファイルが展開されていることを確認
ここまででフォルダ構成は以下のようになります。
(myweb) pi@raspberrypi:~/myweb/myweb $ tree --charset=x
|
.
|-- db.sqlite3
|-- hello
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- migrations
| | `-- __init__.py
| |-- models.py
| |-- tests.py
| |-- urls.py
| `-- views.py
|-- manage.py
|-- myweb
| |-- __init__.py
| |-- asgi.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
|-- myweb_nginx.conf
|-- static
| `-- admin
| |-- css
| | |-- autocomplete.css
| | |-- base.css
| | |-- changelists.css
| | |-- dashboard.css
| | |-- fonts.css
| | |-- forms.css
| | |-- login.css
| | |-- responsive.css
| | |-- responsive_rtl.css
| | |-- rtl.css
| | |-- vendor
| | | `-- select2
| | | |-- LICENSE-SELECT2.md
| | | |-- select2.css
| | | `-- select2.min.css
| | `-- widgets.css
| |-- fonts
| | |-- LICENSE.txt
| | |-- README.txt
| | |-- Roboto-Bold-webfont.woff
| | |-- Roboto-Light-webfont.woff
| | `-- Roboto-Regular-webfont.woff
| |-- img
| | |-- LICENSE
| | |-- README.txt
| | |-- calendar-icons.svg
| | |-- gis
| | | |-- move_vertex_off.svg
| | | `-- move_vertex_on.svg
| | |-- icon-addlink.svg
| | |-- icon-alert.svg
| | |-- icon-calendar.svg
| | |-- icon-changelink.svg
| | |-- icon-clock.svg
| | |-- icon-deletelink.svg
| | |-- icon-no.svg
| | |-- icon-unknown-alt.svg
| | |-- icon-unknown.svg
| | |-- icon-viewlink.svg
| | |-- icon-yes.svg
| | |-- inline-delete.svg
| | |-- search.svg
| | |-- selector-icons.svg
| | |-- sorting-icons.svg
| | |-- tooltag-add.svg
| | `-- tooltag-arrowright.svg
| `-- js
| |-- SelectBox.js
| |-- SelectFilter2.js
| |-- actions.js
| |-- actions.min.js
| |-- admin
| | |-- DateTimeShortcuts.js
| | `-- RelatedObjectLookups.js
| |-- autocomplete.js
| |-- calendar.js
| |-- cancel.js
| |-- change_form.js
| |-- collapse.js
| |-- collapse.min.js
| |-- core.js
| |-- inlines.js
| |-- inlines.min.js
| |-- jquery.init.js
| |-- popup_response.js
| |-- prepopulate.js
| |-- prepopulate.min.js
| |-- prepopulate_init.js
| |-- urlify.js
| `-- vendor
| |-- jquery
| | |-- LICENSE.txt
| | |-- jquery.js
| | `-- jquery.min.js
| |-- select2
| | |-- LICENSE.md
| | |-- i18n
| | | |-- af.js
| | | |-- ar.js
| | | |-- az.js
| | | |-- bg.js
| | | |-- bn.js
| | | |-- bs.js
| | | |-- ca.js
| | | |-- cs.js
| | | |-- da.js
| | | |-- de.js
| | | |-- dsb.js
| | | |-- el.js
| | | |-- en.js
| | | |-- es.js
| | | |-- et.js
| | | |-- eu.js
| | | |-- fa.js
| | | |-- fi.js
| | | |-- fr.js
| | | |-- gl.js
| | | |-- he.js
| | | |-- hi.js
| | | |-- hr.js
| | | |-- hsb.js
| | | |-- hu.js
| | | |-- hy.js
| | | |-- id.js
| | | |-- is.js
| | | |-- it.js
| | | |-- ja.js
| | | |-- ka.js
| | | |-- km.js
| | | |-- ko.js
| | | |-- lt.js
| | | |-- lv.js
| | | |-- mk.js
| | | |-- ms.js
| | | |-- nb.js
| | | |-- ne.js
| | | |-- nl.js
| | | |-- pl.js
| | | |-- ps.js
| | | |-- pt-BR.js
| | | |-- pt.js
| | | |-- ro.js
| | | |-- ru.js
| | | |-- sk.js
| | | |-- sl.js
| | | |-- sq.js
| | | |-- sr-Cyrl.js
| | | |-- sr.js
| | | |-- sv.js
| | | |-- th.js
| | | |-- tk.js
| | | |-- tr.js
| | | |-- uk.js
| | | |-- vi.js
| | | |-- zh-CN.js
| | | `-- zh-TW.js
| | |-- select2.full.js
| | `-- select2.full.min.js
| `-- xregexp
| |-- LICENSE.txt
| |-- xregexp.js
| `-- xregexp.min.js
|-- test.py
`-- uwsgi_params
|
◆ 9-5. nginx起動 ◆
※nginxを起動します
(myweb) pi@raspberrypi:~/myweb/myweb $ sudo /etc/init.d/nginx restart
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --socket :8001 --module myweb.wsgi
|
下記のページをローカルRaspbianのブラウザで開いて'hello!'がでたらOK!
http://127.0.0.1:8000/hello/
下記のページをローカルのブラウザで開いて'linux-memo.net!'がでたらOK!
http://127.0.0.1:8000/hello/linux-memo
※確認が終わればターミナルのプロセスはCONTROL+Cで抜けてください。
◆ 10. nginx + uWSGI のつなぎをUnixソケットで行うよう修正 ◆
◆ 10-1. Unixソケットで通信を行う ◆
先程まではTCPポートソケットを使って通信を行ってきましたが、今度はUnixソケットを使用して通信を行います。
TCPポートソケットは通信が簡単な反面、Unixソケットと比較しオーバーヘットが多いです。
Unixソケットで通信を行う準備をしましょう。myweb_nginx.conf を編集します。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi myweb_nginx.conf
|
upstream django {
# server unix:///home/pi/myweb/myweb/myweb.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
|
以下の通り変更します。
upstream django {
server unix:///home/pi/myweb/myweb/myweb.sock; # for a file socket
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
|
mysite_nginx.conf のupstream djangoに2行コードが書いてあり、片方がコメントアウトされていると思います。
片方のコメントアウトを外して、今まで生きていた方をコメントアウトします。
編集が完了したらNginxを再起動しtest.pyを呼び出します。
(myweb) pi@raspberrypi:~/myweb/myweb $ sudo /etc/init.d/nginx restart
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --socket myweb.sock --module \
myweb.wsgi --chmod-socket=666
|
TCPポートソケットを使った際のコマンドと違い、ポート番号の指定からmysite.sockとUnixソケットの指定に変わっています。
また、先程には付いていなかった--chmod-socket=666 というオプションですが、これはNginxがUnixソケットを使用できるように権限を管理するコマンドです。
この権限がなく、--chmod-socket=666 を付けなかった場合は502 Bad Gateway が表示されてしまいます。
もう一度、ページが表示されるか確認してみましょう。
下記のページをローカルRaspbianのブラウザで開いて'hello!'がでたらOK!
http://127.0.0.1:8000/hello/
下記のページをローカルのブラウザで開いて'linux-memo.net!'がでたらOK!
http://127.0.0.1:8000/hello/linux-memo
※確認が終わればターミナルのプロセスはCONTROL+Cで抜けてください。
◆ 11. iniファイルでuWSGIを実行させる ◆
◆ 11-1. 設定をすべてiniファイルにまとめる ◆
Djangoアプリの表示はできましたが、uWSGIの実行時に--chmod-socket=666などオプションを付けたりするのでどうしてもコマンドが冗長になりがちです。
ですのでオプション含めた設定をすべてiniファイルにまとめ、実行時に読み込む様にします。こうすることで設定の管理が容易になります。
/home/pi/myproject/mywebディレクトリにmysite_uwsgi.iniを新規作成します。
(myweb) pi@raspberrypi:~/myweb/myweb $ cd ~/myweb
(myweb) pi@raspberrypi:~/myweb $ vi myweb_uwsgi.ini
|
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /home/pi/myweb/myweb
# Django's wsgi file
module = myweb.wsgi
# the virtualenv (full path)
# home = /home/pi/myweb/myweb
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /home/pi/myweb/myweb/myweb.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
# clear environment on exit
vacuum = true
|
◆ 11-2. iniファイルでの起動 ◆
iniファイルの編集が完了したら早速起動してみましょう。
以下のコマンドを/home/pi/myproject/mywebで実行してください。
(myweb) pi@raspberrypi:~/myweb $ uwsgi --ini myweb_uwsgi.ini
|
もう一度、ページが表示されるか確認してみましょう。
下記のページをローカルRaspbianのブラウザで開いて'hello!'がでたらOK!
http://127.0.0.1:8000/hello/
下記のページをローカルのブラウザで開いて'linux-memo.net!'がでたらOK!
http://127.0.0.1:8000/hello/linux-memo
※確認が終わればターミナルのプロセスはCONTROL+Cで抜けてください。
◆ 11-3. 一旦仮想環境から出ます。 ◆
以下のコマンドで一旦仮想環境から出ます
(myweb) pi@raspberrypi:~/myweb/myweb $ exit
|
すると、コンソールが以下のようになり、仮想環境から出たことになります。
◆ 12. gitでWOLプログラムコピー ◆
◆ 12-1. gitでdjango-wol-webコピー ◆
django-wol-webはuWSGI+Djangoのフレームワーク上で動作するようPythonで書かれたシンプルなWOLServerです。
gitでDockerコンテナで公開されていますが、WebサーバがApacheで構成されています(Apache+uWSGI+Django)ので、ここまでで準備したNginx+uWSGI+Djangoに合うよう配置していきます。
pi@raspberrypi:~/myweb $ cd ~
pi@raspberrypi:~ $ git clone https://github.com/SoarinFerret/django-wol-web.git
|
ダウンロードできたか確認します。
pi@raspberrypi:~ $ ls
django-wol-web <---このディレクトリがあればOK
|
◆ 12-2. WOLで必要モジュールインスト ◆
django-wol-webで使われるモジュールをインストールしていきます。
pi@raspberrypi:~ $ cd ~/myweb
# 仮想環境にrequestsをインストール
pi@raspberrypi:~/myweb $ pipenv install requests
# 仮想環境にdjango-crispy-formsをインストール
pi@raspberrypi:~/myweb $ pipenv install django-crispy-forms
# wakeonlanとinetutils-pingをインストール
pi@raspberrypi:~ $ sudo apt-get install -y wakeonlan inetutils-ping
|
◆ 12-3. 再び仮想へ ◆
以下のコマンドで再度仮想環境に入ります
pi@raspberrypi:~/myweb $ pipenv shell
(myweb) pi@raspberrypi:~/myweb $
|
◆ 13. アプリケーション(wol)の作成 ◆
◆ 13-1. アプリケーション(wol)の作成 ◆
プロジェクトのディレクトリ(myweb)で以下の通り入力しアプリケーション(wol)を作成します。
(myweb) pi@raspberrypi:~/myweb $ cd ~/myweb/myweb
(myweb) pi@raspberrypi:~/myweb/myweb $ python manage.py startapp wol
|
ディレクトリ構成は以下となります。
(myweb) pi@raspberrypi:~/myweb/myweb $ tree --charset=x
|
.
|-- crispy_forms
| |-- __init__.py
| |-- admin.py
| |-- apps.py
| |-- migrations
| | `-- __init__.py
| |-- models.py
| |-- tests.py
| `-- views.py
|-- db.sqlite3
|-- hello
| |-- __init__.py
| |-- __init__.pyc
| |-- admin.py
| |-- admin.pyc
| |-- apps.py
| |-- migrations
| | |-- __init__.py
| | `-- __init__.pyc
| |-- models.py
| |-- models.pyc
| |-- tests.py
| |-- urls.py
| |-- urls.pyc
| |-- views.py
| `-- views.pyc
|-- manage.py
|-- myweb
| |-- __init__.py
| |-- __init__.pyc
| |-- settings.py
| |-- settings.pyc
| |-- urls.py
| |-- urls.pyc
| |-- wsgi.py
| `-- wsgi.pyc
|-- myweb_nginx.conf
|-- myweb_uwsgi.ini
|-- static
| `-- admin
| |-- css
| | |-- base.css
| | |-- changelists.css
| | |-- dashboard.css
| | |-- fonts.css
| | |-- forms.css
| | |-- login.css
| | |-- rtl.css
| | `-- widgets.css
| |-- fonts
| | |-- LICENSE.txt
| | |-- README.txt
| | |-- Roboto-Bold-webfont.woff
| | |-- Roboto-Light-webfont.woff
| | `-- Roboto-Regular-webfont.woff
| |-- img
| | |-- LICENSE
| | |-- README.txt
| | |-- calendar-icons.svg
| | |-- gis
| | | |-- move_vertex_off.svg
| | | `-- move_vertex_on.svg
| | |-- icon-addlink.svg
| | |-- icon-alert.svg
| | |-- icon-calendar.svg
| | |-- icon-changelink.svg
| | |-- icon-clock.svg
| | |-- icon-deletelink.svg
| | |-- icon-no.svg
| | |-- icon-unknown-alt.svg
| | |-- icon-unknown.svg
| | |-- icon-yes.svg
| | |-- inline-delete.svg
| | |-- search.svg
| | |-- selector-icons.svg
| | |-- sorting-icons.svg
| | |-- tooltag-add.svg
| | `-- tooltag-arrowright.svg
| `-- js
| |-- SelectBox.js
| |-- SelectFilter2.js
| |-- actions.js
| |-- actions.min.js
| |-- admin
| | |-- DateTimeShortcuts.js
| | `-- RelatedObjectLookups.js
| |-- calendar.js
| |-- cancel.js
| |-- change_form.js
| |-- collapse.js
| |-- collapse.min.js
| |-- core.js
| |-- inlines.js
| |-- inlines.min.js
| |-- jquery.init.js
| |-- popup_response.js
| |-- prepopulate.js
| |-- prepopulate.min.js
| |-- prepopulate_init.js
| |-- timeparse.js
| |-- urlify.js
| `-- vendor
| |-- jquery
| | |-- LICENSE-JQUERY.txt
| | |-- jquery.js
| | `-- jquery.min.js
| `-- xregexp
| |-- LICENSE-XREGEXP.txt
| |-- xregexp.js
| `-- xregexp.min.js
|-- uwsgi_params
`-- wol
|-- __init__.py
|-- admin.py
|-- apps.py
|-- migrations
| `-- __init__.py
|-- models.py
|-- tests.py
`-- views.py
|
◆ 13-2. アプリケーション(wol,crispy_forms)の登録 ◆
アプリケーションをプロジェクトに含めるには、構成クラスへの参照を
INSTALLED_APPS 設定に追加する必要があります。
INSTALLED_APPS 設定は作成したプロジェクトディレクトリ(myweb)内の
さらに(myweb)内(settings.py)にありますので、こちらに追記します。
ここからはカレントディレクトリをプロジェクトのディレクトリ(myweb)
として、そこからの相対パスで記載します。
(myweb) pi@raspberrypi:~/myweb/myweb $ myweb/settings.py
|
ALLOWED_HOSTS = []
↓
ALLOWED_HOSTS = ['*'] #<--修正
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hello',
'wol', #<--追記
'crispy_forms', #<--追記
]
CRISPY_TEMPLATE_PACK = 'bootstrap4' #<--追記
|
◆ 13-3. URLの紐付け ◆
viewができれば、views.pyとURLを紐付けます。
まずはviewと同じディレクトリ(wol)にurls.pyを新規作成します。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi wol/urls.py
|
from django.conf.urls import url, include
from . import views
urlpatterns = [
url(r'^$', views.select_computer, name='select_computer'),
url(r'^new/$', views.add_computer, name='add_computer'),
url(r'^results/(?P\d+)/$', views.wol_results, name='wol_results'),
url(r'^ping/(?P\d+)/$', views.ping_computer, name='ping_computer'),
]
|
次にmyweb/urls.pyを編集します。
(myweb) pi@raspberrypi:~/myweb/myweb $ vi myweb/urls.py
|
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include #<--追記
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', include('hello.urls')),
url(r'', include('wol.urls')), #<--追記
]
|
◆ 13-4. プログラムのコピー ◆
Pythonで書かれたWOLSerberプログラムのコピーを行います。
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -ip \
~/django-wol-web/django-wol/wol/forms.py ./wol/
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -ip \
~/django-wol-web/django-wol/wol/models.py ./wol/
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -ip \
~/django-wol-web/django-wol/wol/views.py ./wol/views.py
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -ip \
~/django-wol-web/django-wol/wol/admin.py ./wol/admin.py
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -ip \
~/django-wol-web/django-wol/wol/wol.py ./wol/
|
◆ 13-5. テンプレートのコピー ◆
テンプレートをコピーします。
(myweb) pi@raspberrypi:~/myweb/myweb $ cp -iprv \
~/django-wol-web/django-wol/wol/templates/ ./wol/
|
◆ 13-6. wolアプリケーションのマイグレーション ◆
wolアプリケーションのマイグレーションのマイグレーションを行います。
(myweb) pi@raspberrypi:~/myweb/myweb $ python manage.py migrate
|
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, wol
Running migrations:
Applying wol.0001_initial... OK
|
◆ 13-7. wolアプリケーションの動作確認 ◆
以下のコマンドでuwsgiを起動します。
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --ini myweb_uwsgi.ini
|
下記のページをローカルのブラウザで開きます。
http://127.0.0.1:8000/new/
以下のページが表示されればOKです。
ここで、以下のエラーが出た場合はテンプレートを修正する必要があります。
-------------
TemplateSyntaxError at /xxx/
'staticfiles' is not a registered tag library. Must be one of:
admin_list
admin_modify
admin_urls
cache
i18n
l10n
log
static
tz
-------------
# Djangoの公式ドキュメントを見ると、'staticfiles' がDjango3.0で削除になっていて、このコードは「wol/templates/base.html」内にありますので、これを修正します。
(myweb) pi@raspberrypi:~/myweb/myweb $ wol/templates/base.html
|
#-------------------先頭の以下を
{% load staticfiles %}
#-------------------
#-------------------以下に変更して保存します。
{% load static %}
#-------------------
|
変更できれば、もう一度以下のコマンドでuwsgiを起動します。
(myweb) pi@raspberrypi:~/myweb/myweb $ uwsgi --ini myweb_uwsgi.ini
|
◆ 14. 自動起動設定 ◆
ここからは、RaspberryPi起動時に、サービスが自動起動するように、サーバーとしての仕込みをしていきます。
◆ 14-1. スクリプト作成 ◆
以下のコマンドで一旦仮想環境から出ます
(myweb) pi@raspberrypi:~/myweb/myweb $ exit
|
すると、コンソールが以下のようになり、仮想環境から出たことになります。
まずは、起動スクリプトから呼び出させるスクリプトを新規作成します。
pi@raspberrypi:~/myweb $ cd ~
pi@raspberrypi:~ $ vi ~/wol_server.sh
|
#!/bin/bash
source ~/.bash_profile
export HASH=ハッシュ値
cd ~/myweb/myweb
pipenv run uwsgi --ini myweb_uwsgi.ini
|
※「ハッシュ値」の部分は任意のパスワードのハッシュ値になります。
「django-wol-web」では、WOLを行うPCの登録や、そのPCをWOLで起動する場合に、パスワードの入力を求められます。
その際に入力が必要なパスワードをハッシュ値にして、環境変数HASHに入れておくことで、そのパスワードを知らないユーザが勝手に操作出来ないように、最低限のセキュリティを施す仕組みになっています。
ハッシュ値は「https://tools.keycdn.com/sha256-online-generator」などから設定したいパスワードから導きだしてそれを貼り付けてください。
次に、パーミッションを設定します。
pi@raspberrypi:~/myweb $ chmod 755 ~/wol_server.sh
|
次に、スクリプトから起動したプロセスを効率的に停止するスクリプトを用意します。
pi@raspberrypi:~ $ vi ~/killpstree.bash
|
#!/bin/bash
killpstree(){
local children=`ps --ppid $1 --no-heading | awk '{ print $1 }'`
for child in $children
do
killpstree $child #子プロセス、孫プロセス、ひ孫プロセス終了
done
echo "--->>> kill $1"
kill -2 $1 #プロセス終了
}
[ $# -ne 1 ] && echo "Usage:$0 [target process name]" && exit
kill_family_lst=`ps ax|grep $1|grep -v 'grep'|grep -v $0|awk '{ print $1 }'`
for parent_pid in $kill_family_lst
do
echo "=== start:family killing target=[$parent_pid] ==="
pstree -pha $parent_pid #終了するプロセスの構成を表示
killpstree $parent_pid
done
|
次に、パーミッションを設定します。
pi@raspberrypi:~/myweb $ chmod 755 ~/killpstree.bash
|
◆ 14-2. 起動スクリプトテンプレートをコピーして起動スクリプト作成 ◆
まずは起動スクリプトのテンプレートをコピーしてきます。
pi@raspberrypi:~ $ sudo wget -O /etc/init.d/wol_server \
https://raw.githubusercontent.com/fhd/init-script-template/master/template
|
次にテンプレートを編集します。
pi@raspberrypi:~ $ sudo vi /etc/init.d/wol_server
|
#変更する部分だけ説明します。
#-------------------
dir=""
cmd=""
user=""
#-------------------
#部分を以下に変更します。
#-------------------
dir="/home/pi"
cmd="/home/pi/wol_server.sh"
user="pi"
#-------------------
#次に
-------------------
kill `get_pid`
-------------------
部分を以下に変更します。
-------------------
/home/pi/killpstree.bash `get_pid`
-------------------
|
次に、パーミッションを設定します。
pi@raspberrypi:~ $ sudo chmod 755 /etc/init.d/wol_server
|
◆ 14-3. スクリプトをインストール ◆
起動/停止スクリプトをインストールします。
pi@raspberrypi:~ $ sudo update-rc.d wol_server defaults
|
◆ 14-4. 起動確認 ◆
起動/停止スクリプトの起動確認を行います。
pi@raspberrypi:~ $ sudo /etc/init.d/wol_server start
|
エラーなく起動できれば、以下のコマンドでプロセス数を確認し、11個(複数)あればOKです。
pi@raspberrypi:~ $ ps -ef | grep uwsgi | grep -v grep | wc -l
11
|
◆ 14-5. 停止確認 ◆
起動/停止スクリプトの停止確認を行います。
pi@raspberrypi:~ $ sudo /etc/init.d/wol_server stop
|
エラーなく停止できれば、以下のコマンドでプロセス数を確認し、0個であればOKです。
pi@raspberrypi:~ $ ps -ef | grep uwsgi | grep -v grep | wc -l
0
|
◆ 14-6. システムを再起動しても正常にWOLにアクセスできるか確認 ◆
再起動を行います。
pi@raspberrypi:~ $ sudo reboot
|
再起動後、ターミナルを起動し、以下のコマンドでプロセス数を確認し、11個(複数)あればOKです。
pi@raspberrypi:~ $ ps -ef | grep uwsgi | grep -v grep | wc -l
11
|
◆ 15. ログローテート設定 ◆
以下のWOLサーバーのログがたまらないよう仕込みをしていきます。
/var/log/wol_server.log
/var/log/wol_server.err
◆ 15-1. ログローテートの対象にwol_serverログを含める◆
以下の通り「/etc/logrotate.d/」ディレクトリにログローテート用のファイル「wol_server」を新規作成します。
pi@raspberrypi:~ $ sudo vi /etc/logrotate.d/wol_server
|
/var/log/wol_server.log {
rotate 14
daily
compress
copytruncate
missingok
notifempty
}
/var/log/wol_server.err {
rotate 14
daily
compress
copytruncate
missingok
notifempty
}
|
※「copytruncate」を入れてローテート後もローテート先のファイルに書き込んでしまう状況を回避しているのがポイントです。
◆ 15-2. ログローテートの試験 ◆
ログローテートが機能するか確認します。
pi@raspberrypi:~ $ sudo logrotate -f /etc/logrotate.d/wol_server
|
pi@raspberrypi:~ $ ls -al /var/log/wol_server.*
|
-rw-r--r-- 1 root root 2036 5月 6 23:34 /var/log/wol_server.err
-rw-r--r-- 1 root root 3678 5月 6 23:28 /var/log/wol_server.err.1.gz
-rw-r--r-- 1 root root 0 5月 6 23:34 /var/log/wol_server.log
-rw-r--r-- 1 root root 235 5月 6 19:36 /var/log/wol_server.log.1.gz
|
※圧縮ファイルができているか、ブラウザで「http://127.0.0.1:8000/new」にアクセスして、新しいログがゼロバイトのファイルに追加でできているか確認します。
以上でWOLServerの導入は完了です。
|
|