未分類

最初に書いたとおりVALUE-SERVER契約終了に付き、サイトは一旦休止します。

次は共有サーバーではなく月額固定のVPSにする予定です。可能であれば当サイトも再開しますが、再開時期は未定です。

未分類

はじめに

前回はなんとかvscodeを使って、djangoをUbuntu上で動かしてみました。

今回はHello,Worldでないアプリを作ろうと考え、pythonらしく物体検出でもやってみることにしました。と、言っても検出ロジックは丸パクリです。

PythonでOpenCV DNNを利用して物体検知(Object Detection)する方法 | HaneCa

DNNはおろか、OpenCVすらよく分かってません。

仕様

  1. ユーザーがサイトに来る
  2. アプリがトップページを返す
  3. ユーザーが画像を指定してアップロードする
  4. アプリが画像から物体検出する
  5. アプリが検出済み画像をファイルに出力する
  6. アプリがファイルに出力した画像を挿し込んだトップページを返して3に戻る

リクエストが複数同時に来たときの仕様がありませんが、今回は固定ファイルに上書きします。結果は神のみぞ知るスタイルです。

設計

  • 画像あり/なしで表示を分けられるテンプレートトップページ
  • モデル空
  • 物体検出は固有のモデルでもビューでもフォームでもないものに実装
  • ビューで画像を受け取り、物体検出を呼び出し、結果を受けてテンプレートを呼び出す

実装

環境調整

djangoのような大きなモジュールをpipでインストールすると、vscodeのファイル監視が許容量オーバーしてしまいます。

Running Visual Studio Code on Linux

にあるように、システムの最大監視数を増やします(8,192→524,288)。

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

これでvscodeを起動し直して、警告が出なければ大丈夫です。

でもって、新しくアプリケーション作るため、vscodeのターミナルから以下を実行します。

python manage.py startapp detect_app

フェーズ1

まずは物体検出を行わず、受け取った画像そのものを返して実装。つまり物体検出はハリボテ(モック)。

ビューはこんな感じ。コントローラがないので、全てビューで記述してます。受け取ったファイルの検証はしてません(公開は出来ない)。

from django.http import HttpResponseRedirect
from django.shortcuts import render
from .apps import DetectAppConfig
from .forms import UploadFileForm
from .upload import handle_uploaded_file
from .detect import detect


def upload_file(request):
    result = None
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            input_path = DetectAppConfig.image_filebase + DetectAppConfig.image_file_input
            output_path = DetectAppConfig.image_filebase + DetectAppConfig.image_file_output
            output_url = DetectAppConfig.image_urlbase + DetectAppConfig.image_file_output

            handle_uploaded_file(request.FILES['file'], input_path)
            detect(input_path, output_path)
            result = output_url
    else:
        form = UploadFileForm()
    return render(request, 'detect_app/upload.html', {'form': form, 'result': result})

中で使用されているフォームがこんな感じ。見事にファイルだけです。

from django import forms

class UploadFileForm(forms.Form):
    file = forms.FileField()

HTMLのテンプレートがこんな感じ。Bootstrap4を使ってますが、見た目はやはりアレです?。また画像ファイルのチェックをしていません(公開不可)。フォームデータと抽出結果のURLを渡されてビューから呼ばれます。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>物体検出</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<body class="bg-light">
    <div class="container">
        <div class="py-5 text-center">
            <h1>物体検出</h1>
        </div>
        <div class="row justify-content-center">
            <form method="post" enctype="multipart/form-data">
                {% csrf_token %}
                <div>
                    <label>画像ファイル</label>
                </div>
                <div>
                    {{form.file}}
                </div>
                {% if result %}
                <div>
                    <img src="{{ result }}" class="img-responsive">
                </div>
                {% endif %}
                <hr>
                {% for error in form.file.errors %}
                {{error}}
                {% endfor %}
                <button class="btn btn-primary btn-lg btn-block" type="submit">送信</button>
            </form>
        </div>
    </div>
</body>

</html>

そしてこれがハリボテ本体。

import shutil

def detect(input, output):
    shutil.copy2(input, output)

他にも設定ファイルなどはいじってますが、最後にgitを張るので省略します。フェーズ1はこんな感じです。

入力画像は下のサイトのをお借りしました(超綺麗な写真なので縮小したけど)。ありがとうございます。

Group of People Having Fun Together Under the Sun · Free Stock Photo

フェーズ2

いよいよ物体検出です。まずはpythonにパッケージの追加から。

pip install opencv-python
pip freeze > requirements.txt

このまま実装するとpylintがopencvを認めてくれないので、設定でpython.linting.pylintArgsを検索して、[項目追加]

「–extension-pkg-whitelist=cv2」を追加する。

でもdnnはこれでもダメなようです。うまく回避する方法は見つかりませんでした。ドキュメントコメントがないと怒られてるワーニングも大量にあるので、これ以上は諦めます。

では、気を取り直して実装します。中身を入れたdetect.pyです。

import cv2

def detect(input, output):
    classes = {0: 'background',
                1: 'person', 2: 'bicycle', 3: 'car', 4: 'motorcycle', 5: 'airplane', 6: 'bus',
                7: 'train', 8: 'truck', 9: 'boat', 10: 'traffic light', 11: 'fire hydrant',
                13: 'stop sign', 14: 'parking meter', 15: 'bench', 16: 'bird', 17: 'cat',
                18: 'dog', 19: 'horse', 20: 'sheep', 21: 'cow', 22: 'elephant', 23: 'bear',
                24: 'zebra', 25: 'giraffe', 27: 'backpack', 28: 'umbrella', 31: 'handbag',
                32: 'tie', 33: 'suitcase', 34: 'frisbee', 35: 'skis', 36: 'snowboard',
                37: 'sports ball', 38: 'kite', 39: 'baseball bat', 40: 'baseball glove',
                41: 'skateboard', 42: 'surfboard', 43: 'tennis racket', 44: 'bottle',
                46: 'wine glass', 47: 'cup', 48: 'fork', 49: 'knife', 50: 'spoon',
                51: 'bowl', 52: 'banana', 53: 'apple', 54: 'sandwich', 55: 'orange',
                56: 'broccoli', 57: 'carrot', 58: 'hot dog', 59: 'pizza', 60: 'donut',
                61: 'cake', 62: 'chair', 63: 'couch', 64: 'potted plant', 65: 'bed',
                67: 'dining table', 70: 'toilet', 72: 'tv', 73: 'laptop', 74: 'mouse',
                75: 'remote', 76: 'keyboard', 77: 'cell phone', 78: 'microwave', 79: 'oven',
                80: 'toaster', 81: 'sink', 82: 'refrigerator', 84: 'book', 85: 'clock',
                86: 'vase', 87: 'scissors', 88: 'teddy bear', 89: 'hair drier', 90: 'toothbrush'}

    # Load a model imported from Tensorflow
    tensorflowNet = cv2.dnn.readNetFromTensorflow('./model/frozen_inference_graph.pb', './model/graph.pbtxt')

    # Input image
    img = cv2.imread(input)
    rows, cols, channels = img.shape

    # Use the given image as input, which needs to be blob(s).
    tensorflowNet.setInput(cv2.dnn.blobFromImage(img, size=(300, 300), swapRB=True, crop=False))

    # Runs a forward pass to compute the net output
    networkOutput = tensorflowNet.forward()

    # Loop on the outputs
    for detection in networkOutput[0,0]:
        score = float(detection[2])
        if score > 0.2:
            left = detection[3] * cols
            top = detection[4] * rows
            right = detection[5] * cols
            bottom = detection[6] * rows
    
            #draw a red rectangle around detected objects
            cv2.rectangle(img, (int(left), int(top)), (int(right), int(bottom)), (0, 0, 255), thickness=2)
            #draw category name in top left of rectangle
            cv2.putText(img, classes[int(detection[1])], (int(left), int(top-4)), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2, 8)

    cv2.imwrite(output, img)

動かすにはトレーニング済みモデルデータと設定ファイルがいるのですが、これをダウンロードするスクリプトが↓です。

#!/bin/sh
mkdir -p model
wget -O - 'http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v2_coco_2018_03_29.tar.gz' | tar xvfzO - ssd_mobilenet_v2_coco_2018_03_29/frozen_inference_graph.pb > model/frozen_inference_graph.pb
wget -O - 'https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/ssd_mobilenet_v2_coco_2018_03_29.pbtxt' > model/graph.pbtxt

サーバー起動して、POSTしてみると…

一人多いですね。

前回と同じですが、このサーバーのGitList Giteaです。

デバッグ

djangoのデバッグも特別なことはありません。デバッグメニューからデバッグの開始を選びます。

Pythonを選びます。

Djangoを選びます。

ブレークポイントを張ります。

アップロードしてみます。

こんな感じで止まりました。変数も普通に見えてます。他と変わりません。

まとめ

今回はdjangoで物体検出するアプリを作って、デバッグまでしてみました。

次回はこのアプリを進化させ、モデルも使って、PostgreSQLにデータを入れてみたいと思います。

未分類

はじめに

前回はvscodeのメニュー表示バグの回避+αを記事にしました。

今回はようやくdjangoです。

git導入

まずは開発の基本gitです。バージョン管理すると失敗してもいつでも元に戻せます。というわけでgitをインストールします。

sudo apt install git

vscode上で環境構築

フォルダ作成

まずはvscodeを起動します。[フォルダを開く]から、~/python/を開き、右上のボタンからdjango_appsフォルダを作成して開きます。

gitリポジトリの作成

フォルダが開いたら次はメニューからターミナルを開きます。

開いたターミナルでgitリポジトリをその場に作ります。

git init

Python環境の作成とgit無視ファイルの設定

出来たら次にpythonの環境をその場に作ります。

python3 -m venv env

すると何やら左側に怪しい数字が出てきます。数字の出てるボタンをクリックします。

見てみると、さっきのpython環境を作成したときに出来たファイルのようです。つまり環境作成したときに346個のファイルが変更(追加)されたよと言っています。これはvscodeがデフォルトで持っているgitの機能で、さきほど作ったリポジトリを認識していて、その変更を検出したために変更ファイル数を教えてくれてたのです。ただ、自動生成されるファイルや外部から取得するファイルはgit管理対象にしないのがお約束なので、ここでは無視ファイルに指定します。いきなり346個も指定するのは辛いので、右上の階段状のボタンを押します。

これでフォルダ階層表示になるので、変更部分が分かりやすくなります。envを右クリックして、

[.gitignoreに追加]を選択します。これは、選択したフォルダ以下全てをgit管理対象にしない=無視するという意味です。

無視にすると、変更として検出されなくなり、無視設定ファイルである.gitignoreが作成されました。このファイルを開くと

346個のファイルが全て一覧されてしまっているので、

最上位フォルダのみに修正しておきます。 (以降このフォルダに追加された場合も自動で無視したいので)

これで心置きなくpython環境を設定できます。

vscode用python環境選択

次はvscodeにpython環境を認識させます。F1キーを押して、python: Select Interpreterと打ち込んでEnterしてください。

さっき作成したpython環境が./env/bin/pythonにあるので、それを選びます。

これでvscodeがこのフォルダで使用するpython環境が設定されました。

pipを使ったインストール

後はvscodeのメニューのターミナルから新しいターミナルを開きます。env環境で立ち上がるので、ここでpipでパッケージを更新しておきます。

pip install -U pip
pip list -o
pip install -U setuptools

これで更新が必要なpythonモジュールがなくなるので、djangoをインストールします。

pip install django

djangoのプロジェクト作成と確認

まずはsample_siteプロジェクトをカレントディレクトリに作成します。

django-admin startproject sample_site .

これでサービスが稼働可能な状態になるので、djangoの開発サーバーを起動してみます。

python manage.py runserver

プロンプトが戻らずに出力が止まり、http://127.0.0.1:8000/などと出てきていたら起動成功です。firefoxを立ち上げて、http://127.0.0.1:8000/を開いてみましょう。

まだ何もプログラミングもしてないのに、画面が出ましたね。これがフレームワークの力です。骨組みはすでにあるので肉付けしてくれという状態なのです。でもこれは確認用の画面なので、この画面を編集することはありません。

アプリケーション作成

まずはCtrl+Cで開発用サーバーを止めて、sample_appを作成します。

python manage.py startapp sample_app

ここまでで骨組みが出来ています。

pipのrequirements.txt作成

今、pythonの環境は全てgitからは無視ファイルとして扱っているため、保存されません。そのため、pythonの環境はいつでも復元できるようにインストールしたパッケージのリストをバージョン付きで保存します。それがrequirements.txtです。以下のコマンドで作成します。

pip freeze > requirements.txt

sqlite3データの無視ファイル追加

データベースのデータはgitには入れないので、このファイルも無視します。db.sqlite3を右クリックして[.gitignoreに追加]してください。あとは、pythonバイトコードのキャッシュ(.pyc)も無視ファイルに追加します。最終的に.gitignoreは↓な感じになります。

env/
db.sqlite3
*.pyc

gitリポジトリにコミット

切りが良いので、リポジトリにコミットしておきます。まずは数字の出ているところアイコンを押して、変更と書いてあるバーの右側の+を押します。

すると、[変更]の上に[ステージング済みの変更]という項目が出来上がり、元々検出されていた変更ファイル群が[ステージング済みの変更]に移動しました。後はコミットするだけなのですが、初回はその前にやることがあります。確認の意味でメッセージに「初回コミット」と入れて、一度チェックボタンを押して見ると…

こんな感じで怒られます。gitは原則コミットした人の名前とメールアドレスをちゃんと記述する慣習で、その設定がされていないとエラーになります。

初回だけなので、vscode内のターミナルからサクっと登録しておきます。

git config --global user.email "you@example.com"
git config --global user.name "Your Name"

※メールアドレスと名前は自分の物に変えてください

これでコミットできるようになったので、チェックボタンを押してコミットしてみてください。成功すれば何も出ずに16個の変更ファイルがなくなります。ターミナルからgit logとすると、履歴を見ることが出来ます。

(env) user@ubuntu1804:~/python/django_apps$ git log
commit de2a5a426e41514b9281ee3250d19560f92e632a (HEAD -> master)
Author: first_user <first_user@elephantcat.work>
Date:   Sat Feb 8 01:28:39 2020 +0900

    初回コミット
(env) user@ubuntu1804:~/python/django_apps$ 

Hello,Worldの作成

まずはViewから作成します。見たまんまなHello,Worldを返すビューです。

from django.http import HttpResponse

def index(request):
    return HttpResponse("<html><body>こんにちは!世界</body></html>")

このアプリのURLとビューの対応表です。

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

このサイトのURLとアプリの対応表です。

"""sample_site URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('sample_app/', include('sample_app.urls')),
    path('admin/', admin.site.urls),
]

では、開発サーバー起動

python manage.py runserver

firefoxで確認

OK!なので、ステージングしてコミットします。

一応GitList Giteaに置いておきました。

まとめ

djangoでHello,Worldまでをgitにコミットしながらローカルvscode環境で実行させるところまでできた。

次回(↓)はアプリケーションとしての何かの機能を実装して、デバッグまでしてみたい。

未分類

はじめに

前回は、Ubuntuにvscodeをインストールして、pythonの開発環境を立ち上げてみました。

今回は、その環境でdjangoというpython用のWebフレームワークを使って、Webアプリを作ってみたいと思っていましたが、閑話休題。一旦少しUbuntuのデスクトップ環境を少し整えます。今まで説明した設定だけではあまりに使いにくいので…

デスクトップテーマの変更

見た目なんてどうでもいいのですが、Ubuntu18.04でvscodeを使うと、メニューが表示されないバグがあるので、その回避策でテーマを変更します。

gnome-tweaksのインストール

デスクトップ版なのにデフォルトではテーマすら変更できないのが最近のUbuntuです。まずはgnome-tweaksをインストールします。

sudo apt install gnome-tweaks

インストールが終わったら、Windowsキー→tweaks[Enter]でtweaksを起動します。

この画面でテーマの変更が可能です。

Yaruのインストール

vscodeの問題回避に有効と言われているのは、18.10で配布されたテーマ(Yaru)なのですが、これは18.04でもパッケージが追加されています。ただし、追加されたパッケージはsnap用なので、snapでインストールします。(aptにもppaという私用のパッケージ配布リポジトリがありましたが、もううまく動かないとのことなので今はsnapしかありません)。

sudo snap install communitheme

インストールが終わったら再起動します(ログアウトでもいいかもしれませんが念の為) 。再起動したらログイン前に、下図のようにセッションを「Ubuntu」から「Ubuntu with communitheme snap」に変更してから、ログインします。

一度変更すれば、次回は同じものがデフォルト選択されます。ログイン完了したら、Tweaksを起動して、 テーマのうちアプリケーション、カーソル、アイコンの3つをCommunithemeに変更すれば完了です。

メニューが白背景になるので、vscodeで現象が発生しなくなります(ごめんなさい。しばらく効果あったのですが、最終的には発生しました。一度発生したら結構頻度上がりました)。アイコンなどの形もやや変わり、少し新しい感じになります。

スクリーンロックの設定

Ubuntuのスクリーンロックがとにかく時間が短いです。VirtualBox内などの環境でスクリーンロックが必要なケースは稀だと思うので、これはOFFにしてしまいます。右上のメニューから設定ボタンを押すと…

こんな画面が出るので、ココの画面ロックを押します。すると…

またダイアログが出てくるので、自動画面ロックをOFFにします。

ついでに電源管理の省電力ブランクスクリーンもOFFにしておきます。

リソースモニタの常時表示

GUIで使う場合は特に時間よりも何よりも、固まってるのか動いてるのか分からない場合があるので、システム負荷が知りたいことが多いです。そのため、上部バーなどに常駐するリソースモニタを入れておきます。

sudo apt install gnome-shell-extension-system-monitor

入れ終わったら一旦ログアウトして再ログインした後、tweaksを起動します。とりあえず曜日よりも日付が欲しい派なので、日付をONします。

拡張機能にあるシステムモニタをONにして、設定ボタンを押します。

CPU~Diskまで全てDisplayします。GPUも必要なら出来ますが、あんまり信用できないかもしれないので、私は使ってません(Windows側で見てる)。

設定完了すると、トップバーはこんな感じになります。

まとめ

これで大体Ubuntu GUIで何をするにも最低限必要な環境にはなったかと思います。GUIなので、リソース消費が激しいですけども。。。
次回(↓)こそUbuntu+vscode+djangoが出来ればいいと思います。

未分類

はじめに

前回は、WindowsのDBeaverからVirtualBoxのUbuntuに入れたPostgreSQLにアクセスして簡単な表を見てみました。

今回は、一旦DBから離れてUbuntu 18.04上にVisual Studio codeをインストールして、Pythonの開発環境を整えてみます。

Visual Studio codeのインストール

最初に断っておくと、私はLinux上のVisual Studio code(以下vscode)を常用していません。理由はWindowsのvscodeからremote-sshで使っているからです。ただ最初はローカルにvscodeをインストールして使います。参考資料は以下になります。

Running Visual Studio Code on Linux

snap/apt?

Ubuntuにvscodeをインストールする方法はsnapを使う方法とaptを使う方法の2種類あります。snapはUbuntuでしか利用されない特殊なパッケージで、コンテナを前提としたアプリのインストールをするため、従来のパッケージ管理と大きく違います。アプリに余計なオーバーヘッドは要らないので、今回はaptで行きます。

aptリポジトリの追加

wget -O - https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -o root -g root -m 644 packages.microsoft.gpg /usr/share/keyrings/
sudo sh -c 'echo "deb [arch=amd64 signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list'
rm packages.microsoft.gpg

インストール

sudo apt-get install apt-transport-https
sudo apt-get update
sudo apt-get install code

これでコマンドラインからcodeと打つとvscodeが起動するようになりました。もちろんWindowsキーからcodeでも、アプリケーション表示からvscodeアイコンを選択しても起動します。

起動直後の画面はこんな感じかと思います。

VisualStudio codeのプラグイン追加

vscodeは豊富なプラグインが売りになっています。まずはプラグインの追加方法説明も兼ねて…

日本語化

してみます。vscodeの左側についているバーの一番下のアイコンが拡張機能です。ここを押すと…

各種拡張機能(プラグイン)の一覧が出てきます。一番上に検索ボックスがあるので、そこに Japanese と打ち込むと…

日本語に関連した拡張機能が一覧されます。では一番上にJapanese Language Pock fo…というのがあるのでこれのInstallボタンを押します。しばらくすると右下にポップアップが出てくるので、そこにある[Restart Now]ボタンを押すと…

日本語で起動してくれます。

vscodeには各種のプラグインがありますが、ここではこれだけにして、必要なときに入れていく方式を採ります。

Python開発環境の構築

vscodeで環境構築する前にpython自体の環境構築方法について説明を入れておきます。

python2とpython3

まずはpythonのバージョンについて…

pythonにはバージョン2系とバージョン3系があります。2系のスクリプトは3系で動かないことが多いです(文字列周りがかなり違う)。なのでpythonというとまずはバージョンを確認することが多いわけです。今回は18.04.3をクリーンインストールしたので2系は入っておらず、3系だけです。環境を構築する上で2系のことは考えないことにします。また3系でもバージョンはいくつかありますが、複数のバージョンを切り替えて使用することも考えないことにします。

pythonのパッケージ管理

最近のスクリプト言語は、使用するライブラリ(モジュール)などをパッケージ管理が出来るようになっています。インターネットから自由にダウンロードして、簡単に利用でき、また更新なども一発で出来るようになっています。pythonでもそのような機能がありますが、スクリプト言語のパッケージでよく問題になるのは、「インストールする場所」です。例えば複数のユーザーで共通で使いたいライブラリがあるとか、このアプリだけで使うライブラリなどがあった場合、同じ場所に突っ込むと、必要なバージョンが違うなどの不都合が発生したりします。

なので、この手のパッケージ管理はアプリケーションならアプリケーションの環境ごとに分けることが多いです。その環境を切り替えるコマンドがvenvです。

venvのインストール

このvenvはpython標準の機能なのですが、ubuntuは改悪してvenvを外しているので、最初にこれをインストールします。

sudo apt install python3-venv

venv環境の作成とactivate

次に環境をtestという名前で作成します。

python3 -m venv ~/.venv/test

最後に指定してる引数が環境を保存するディレクトリになります。そしてこのディレクトリの名前が環境の名前です。では早速作成した環境に切り替えてみます。

user@ubuntu1804:~$ . ~/.venv/test/bin/activate
(test) user@ubuntu1804:~$ 

環境を切り替えるとプロンプトが変わり、カッコ付きで環境の名前が入るようになります。この状態であれば、いくらパッケージをインストールしても他の環境に影響を与えることはありません。

パッケージの更新・追加

試しにpip自体のアップデートをしてみます。

(test) user@ubuntu1804:~$ pip install -U pip
Collecting pip
  Downloading https://files.pythonhosted.org/packages/54/0c/d01aa759fdc501a58f431eb594a17495f15b88da142ce14b5845662c13f3/pip-20.0.2-py2.py3-none-any.whl (1.4MB)
    100% |████████████████████████████████| 1.4MB 958kB/s 
Installing collected packages: pip
  Found existing installation: pip 9.0.1
    Uninstalling pip-9.0.1:
      Successfully uninstalled pip-9.0.1
Successfully installed pip-20.0.2
(test) user@ubuntu1804:~$

めちゃくちゃバージョンアップしました。他にアップデートできるものがないかどうか見てみます。

(test) user@ubuntu1804:~$ pip list -o
Package    Version Latest Type 
---------- ------- ------ -----
setuptools 39.0.1  45.1.0 wheel
(test) user@ubuntu1804:~$

setuptoolsもアップデートできるようなのでやっておきます。

(test) user@ubuntu1804:~$ pip install -U setuptools
Collecting setuptools
  Downloading setuptools-45.1.0-py3-none-any.whl (583 kB)
     |████████████████████████████████| 583 kB 6.5 MB/s 
Installing collected packages: setuptools
  Attempting uninstall: setuptools
    Found existing installation: setuptools 39.0.1
    Uninstalling setuptools-39.0.1:
      Successfully uninstalled setuptools-39.0.1
Successfully installed setuptools-45.1.0
(test) user@ubuntu1804:~$

では適当にbottleでもインストールしてみます。

(test) user@ubuntu1804:~$ pip install bottle
Collecting bottle
  Downloading bottle-0.12.18-py3-none-any.whl (89 kB)
     |████████████████████████████████| 89 kB 2.1 MB/s 
Installing collected packages: bottle
Successfully installed bottle-0.12.18
(test) user@ubuntu1804:~$

インストール済みのパッケージを一覧します。

(test) user@ubuntu1804:~$ pip list
Package       Version
------------- -------
bottle        0.12.18
pip           20.0.2 
pkg-resources 0.0.0  
setuptools    45.1.0 
(test) user@ubuntu1804:~$ 

これだけ分かればパッケージ管理は何とか出来ると思います。削除など必要であればググって調べてください。

venv環境のdeactivateと削除

次は今の環境を抜けて元の環境に戻します。

(test) user@ubuntu1804:~$ deactivate 
user@ubuntu1804:~$

環境自体の削除は最初に作ったディレクトリを消すだけです。

rm -rf ~/.venv/test

今回環境は~/.venvディレクトリの下に作りましたが、ココは私が好みで使ってるというだけなので、どこでも大丈夫です。ここまででvenvの使い方や雰囲気が分かったと思います。

vscodeで作業する

まずはターミナルからフォルダを作成します。

mkdir -p ~/python/sample

ようやくvscodeを使います。 vscodeの[フォルダを開く]ボタンを押して作ったフォルダを開きます。すると…

左側のペインにSAMPLEと書かれてる部分が現れました。同じ行の右側に並んでいるアイコン群の一番左に[新しいファイル]ボタンがあるので押して、sample.pyと入れます。

作成したファイルが開かれて、右下にPython用の拡張機能が推奨されてます。渡りに船なので[Install]です。

次はpylintのインストールを促されますが、まだpipが使えないので、ここでターミナルから環境を作っておきます。

python3 -m venv ~/python/sample/venv

すると…

賢いことにvscodeが環境を検出してコレ使うか?って聞いてくれています。当然[Yes]です。
環境も選択できたので、ついでにさっき聞かれていたpylintも[Install]しちゃいます。すると、画面下側にターミナルが出てきて、venv環境がactivateされた状態でbashが立ち上がり、自動でpylintがインストールされてます。到れり尽くせりですね。

では、このターミナルからrequestsパッケージをインストールしちゃいます。

(venv) user@ubuntu1804:~/python/sample$ pip install requests
Collecting requests
  Downloading https://files.pythonhosted.org/packages/51/bd/23c926cd341ea6b7dd0b2a00aba99ae0f828be89d72b2190f27c11d4b7fb/requests-2.22.0-py2.py3-none-any.whl (57kB)
    100% |████████████████████████████████| 61kB 5.2MB/s 
Collecting chardet<3.1.0,>=3.0.2 (from requests)
  Downloading https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl (133kB)
    100% |████████████████████████████████| 143kB 3.8MB/s 
Collecting urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 (from requests)
  Downloading https://files.pythonhosted.org/packages/e8/74/6e4f91745020f967d09332bb2b8b9b10090957334692eb88ea4afe91b77f/urllib3-1.25.8-py2.py3-none-any.whl (125kB)
    100% |████████████████████████████████| 133kB 3.3MB/s 
Collecting idna<2.9,>=2.5 (from requests)
  Downloading https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl (58kB)
    100% |████████████████████████████████| 61kB 5.5MB/s 
Collecting certifi>=2017.4.17 (from requests)
  Downloading https://files.pythonhosted.org/packages/b9/63/df50cac98ea0d5b006c55a399c3bf1db9da7b5a24de7890bc9cfd5dd9e99/certifi-2019.11.28-py2.py3-none-any.whl (156kB)
    100% |████████████████████████████████| 163kB 4.2MB/s 
Installing collected packages: chardet, urllib3, idna, certifi, requests
Successfully installed certifi-2019.11.28 chardet-3.0.4 idna-2.8 requests-2.22.0 urllib3-1.25.8
(venv) user@ubuntu1804:~/python/sample$ 

画面的には↓な感じです。

さて、これで必要な環境が整ったので、コードを書いてみます。

import requests
print(requests.get('https://www.google.co.jp/').text)

Google日本のトップページを取得して、標準出力に書き出すスクリプトです。では、右上の実行ボタンを押して実行しちゃいます。

サクっと実行出来ました。次はデバッグしてみます。左側のアイコンの上から4つ目の虫っぽいのをクリックします。

ソースコード2行目の左側で左クリックし、2行目にブレークポイントを張っておきます。

2行目に赤丸を確認してから、[Pythonでデバッグする]を押します。

すると…

プログラムが動いてから2行目実行直前で止まりました。左側には変数も表示されており、デバッグが出来ることが分かります。
上にある右向き三角ボタンを押して、実行を再開します。

プログラムが終了し、元の状態に戻りました。

まとめ

Ubuntu18.04上にvscodeをインストールし、venvで用意したpythonの実行環境を使い、vscode上でGoogleのトップ画面を取得するプログラム(sample.py)を作成し、実行・デバッグしてみました。

次回(↓)は、この環境でdjangoに挑戦します(?)。

未分類

概要

マニュアル解説シリーズです。今回のお題はこちら。

PostgreSQL: Documentation: 12: 20.1. The pg_hba.conf File

認証について

はじめに

PostgreSQLサービスを使うには、まず

  • サーバーにアクセスできること(ネットワーク的に到達できること)
  • サーバーに接続できること(サービスが稼働していて、ポートなどが開いていること)
  • サービスがクライアントを認証し、PostgreSQLのユーザーとマッピングできること

が必要です。3つ目の項目がココで説明する内容です。最初の2つに問題がある場合は、ここで説明する以前の話になります。

※細かく言うと、他にOSが何らかのセキュリティ(SELinux/AppArmorなど)で弾くケースがありますが、今回は考慮しません。

クライアント認証とはサーバー側から見て、接続してきたモノがどこの誰かを識別することです。この人に違いないと思ったらユーザーとマッピングされますが、そうでない場合はエラーで弾かれるということです。

PostgreSQLの認証の種類

認証方法説明
trust認証接続できただけで特定のユーザーとして認証する
パスワード認証指定されたユーザーであることをパスワードで確認して認証する
GSSAPI認証ActiveDirectoryなどで使用されるKerberos認証で認証されたユーザーとして認証する。
GSSAPIはそこで使用されるAPIで、所謂シングルサインオン。
SSPI認証Windows認証で認証されたユーザーとして認証する(Kerberos含む)。
サーバー/クライアントともにWindowsのときだけ使用できる、所謂シングルサインオン。
IDENT認証identサーバーでクライアントが実行中のユーザーを取得して認証する。
大昔に利用されてたサーバーで現在は使われない
Peer認証ローカル接続のときだけ、クライアントの実行ユーザーを取得して認証する。Windowsでは使用できない。
OSのユーザー名とPostgreSQLのユーザー名が一致する必要がある
LDAP認証LDAPのデータを使って指定されたユーザーであることを確認して認証する。中身はパスワード認証と同じ。
RADIUS認証RADIUSのデータを使って指定されたユーザーであることを確認して認証する。中身はパスワード認証と同じ。
平文ではないものの通信が暗号化されない
証明書認証SSLで受け取ったクライアント証明書のCommon Nameで認証する。
PAM認証LinuxのPAMのデータを使って指定されたユーザーであることを確認して認証する。中身はパスワード認証と同じ。
BSD認証OpenBSDで使える認証方式。よく知らない。

かなり方式が多いので注意です。ただ、よく使用されるのは太字の3つ。他はセキュリティに難があったり、ユーザーの管理がPostgreSQL内のユーザーとのマッピング維持が大変だったりして、あまり使用されません。証明書認証は通信経路そのものが暗号化されており、今後利用の増加が見込まれるという意味での太字です。

Ubuntu18.04のデフォルト設定

Ubuntu18.04のpg_hba.confのデフォルト設定はこんな感じ。

# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5

# で始まる行はコメントです。それ以外の行は、どんなIPから、どういう接続で誰がどのデータベースに接続しようとしていた場合、どういう認証方式を使用するかを表しています。あとは1行ずつ見ていきます。

local   all             postgres                                peer

これは

  • local=ローカル接続=Unixドメインソケットの接続
  • all=対象データベースは何でもいい
  • postgres=ユーザーがpostgres(管理者)

という条件を全て満たす場合、peer=Peer認証するという設定です。そういえば最初にpostgresユーザーでpsqlで繋いだときパスワード聞かれませんでしたよね。そのときはココの設定が効いていたということです。

local   all             all                                     peer

次の行は先程のユーザー設定列がall、誰でもいいになっただけです。つまり、ローカル接続ならどのデータベースでも誰でもPeer認証にする、という設定です。一般ユーザーを作った後、そのユーザーでpsqlを実行したときにパスワード聞かれませんでしたよね。そのときに使われた設定です。

host    all             all             127.0.0.1/32            md5

次の行はhostなので、ローカル接続ではないTCP/IPの接続であることを意味しています。データベースとユーザーはallなので何でもOKです。次のIPアドレスっぽいのが、クライアントのIPです。127.0.0.1はローカルホストを意味する特別なIPで、つまりTCP/IPで同じホストから繋いできたときは、誰でもどんなデータベースでも、md5=パスワード認証を行う、という意味になります。ただし、同じホストならローカル接続でPeer認証できるので、普通はこの設定を使うことはありません。

ただし、Peer認証はLinux上のユーザー名と一致しないと使えないので、Linuxのユーザー名と異なるユーザー名をPostgreSQL側に作成した場合には使用されます。

host    all             all             ::1/128                 md5

次の行はさっきの設定のIPv6版です。説明は省略します。

残りの行はレプリケーション用の接続設定なので、1つしかない今回は割愛します。

つまりどういう設定か…

ローカルホストからしか使えない設定になっています。
なので別のマシンから接続する場合は、認証設定を追加する必要があります。

ローカルホスト以外からのパスワード認証の追加

特定のIPv4ホストからの接続でパスワード認証を追加する

host    all             all             10.0.2.2/32            md5

こんな感じで、10.0.2.2(VirtualBoxのNATの仮想ルーターのIP)からTCP/IPで接続された場合、パスワード認証をかけることが出来ます。

特定のIPv4 LAN内の複数ホストからの接続でパスワード認証を追加する

host    all             all             192.168.0.0/24            md5

こんな感じで、192.168.0.1~192.168.0.254までのIPからTCP/IPで接続された場合、パスワード認証をかけることが出来ます。

設定ファイルを編集したら…

OSに用意された方法でサービスの再起動をしてください。

ローカルホスト以外からのSSLクライアント認証の追加

hostssl all all all cert map=cnmap

こんな感じで追加出来ます。SSLで接続する場合は、他のTCP/IP接続手段は消した方がいいでしょう。
cnmapというのは、Common Nameとユーザーをどうマッピングするかという設定を他のファイルに記述するのですが、そこで使用されるマッピングの名前です。

具体例を↓に書いたので、良かったら参考にしてください。あまり丁寧には書いてないですけど…。

まとめ

PostgreSQLの認証設定は種類が多く、デフォルトではローカルからの認証設定しか存在しない。
今回はそこにリモート接続からの認証設定を追加する方法を解説した。

未分類

概要

VirtualBoxのネットワークについて、簡単に解説します。
内容的にはマニュアルの↓の部分です。原文をChrome翻訳などで読める方はそちらの方が正確です。

Chapter 6. Virtual Networking

仮想ネットワックのモードについて

VirtualBoxで構成可能な仮想ネットワークにはいくつかのモードがあり、それぞれ構成や可能なことが異なります。

この画面で割り当ててるやつのことです。アダプターは4つあるので組みあせて使用することも可能です。

モード説明
NAT(デフォルト)いつもお世話になっているモードです。
VM→ホスト/インターネットが可能で、ホスト→VMはポートフォワードしないと出来ません。VM間の通信は出来ません。
NATネットワークVM間の通信も可能なNATです。
ブリッジホストと同じネットワークに参加します。
内部ネットワークVM間だけで通信できます。
ホストオンリーVMとホストが双方向に通信できるモードです。ただしVMはインターネットにはアクセス出来ません。
汎用ドライバ使ったことがないので、説明しません。拡張パックのドライバを使用して、トンネルを作るのに使うようです。

NAT(デフォルト)

デフォルトで簡単そうに見え、Oracleも簡単と言ってますが、ソフト的には実は一番ややこしいモードです。

解説

模式的に書くと以下な感じ。

各VMごとにNATを構成する仮想ルーターがあり、ホストのWindowsはどのIPも10.0.2.2で、ゲスト(VM)はどのIPも10.0.2.15(DHCP)となっています。VMのOSが起動しIPを自動取得すると、仮想ルーターのDHCPで10.0.2.15が返るということです。仮想ルーターはホスト側にIPを持っておらず、従ってVM間の通信はできない、ということになります。ようするにIPが同じか振られていないかで VMの区別が付かないということです。

NATとは…

家庭用のルーターなどで使用されているネットワークの仕組みです。

ネットワークアドレス変換 – Wikipedia

正式にはNAPT、古くはIPマスカレードと呼ばれていた機能の系譜になります。ざっくり説明すると、上図のVMから来たパケットをさもホストから送られたパケットとして外部のネットワークに転送し、返事としてホスト宛に返ってきたパケットを上手いこと識別して(ココが難しい)元のVMに転送する機能です。IP通信はTCP/UDPなどのプロトコルがあり、NAPTは各プロトコルに合わせてIPやポートを上手いこと変換するので、IPマスカレードと呼ばれていました。仕組みについては、

NAPTとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

辺りを読んで分かった気になってください。ココ以上に上手い説明を私は知りません。
IPやポートを変換できないものは弾かれるため、自動的にファイヤーウォールが構築されることになります。

ポートフォワーディングについて

IPやポートを変換できないものに関して、固定の例外的ルールを作ることで、ファイヤーウォールに穴を開けることが出来ます。例えば、sshの標準ポートである22で、通信開始(SYN)のパケットが外から送られてきた場合は、弾かずにVMのIP 10.0.2.15のポート22に転送する、などのルールです。パケットを転送することをフォワードと呼ぶので、これをポートフォワードと呼びます。

ポートフォワーディングの設定がない場合、NATのファイヤーウォールを越えることは出来ません。

NATネットワーク

これを模式的に書くとこんな感じ。

ただのNATよりは幾分スッキリした構成になり、1つの仮想ルーターでVM同士が並び、DHCPで綺麗にIPが振られているのが分かります。これなら物理LAN同様VM同士が通信出来るのも分かります。VMとホストの関係はNATのときと変わらないので、同じように扱う事ができます。

ブリッジ

これを模式的に書くとこんな感じ。

VMがホストと同じネットワークに参加する形になります。VMが普通に1台のPCとしてネットワークに出現してきます。ある意味一番ユーザーには分かりやすい形です。ただしDHCPな環境であれば、1台でホスト+VMの数分IPを使うので管理者泣かせの形ですし、VMにもホストと同等のセキュリティが求められます。

内部ネットワーク

これを模式的に書くとこんな感じ。

VM同士は繋がっていますが、ホストとVMは繋がっていません。DHCPサーバなどもいないので、通常静的IPを使って独自のネットワークを構築します。VirtualBoxの機能を使ってDHCPの機能を追加することも頑張れば出来ます。物理ネットワークに出る手段がない形なので、主に外部からの影響を受けたくないときに一時的に使用するマニアックな構成だと思います。

ホストオンリー

これを模式的に書くとこんな感じ。

内部ネットワークにホストが参加しました!という構成です。ついでにホストにIPを振るための仮想ネットワークアダプタを用意し、DHCPも提供されています。 VMを外のネットワークと遮断した上でホストとは通信できますが、内部ネットワーク同様、個人的にはマニアックな設定に見えます。さすがにホストとは通信したいだろうという配慮なんでしょうかね…

なお、たまにNAT+ホストオンリーなネットワーク構成をオススメしてるサイトも見たことがありますが、ホストとVMを仮想ルーターでも繋げて仮想ブリッジでも繋げるというのは変則的なので、個人的には、素直にNATにポートフォワードの設定をオススメしたいです。

まとめ

VirtualBoxのネットワーク設定の種類について説明し、いつもデフォルトで使っているNATがどんな特性のものなのかを解説しました。
SVGのお絵描き大変ですが、面白かったです。inkscapeありがとう!

未分類

事件

今日何気なく記事を編集して、「ああ、そういや過去記事で似たような画像作ったな…作った画像どこだっけ?」って過去記事を探していたところ、どこを探しても見つかりません。

この画像には alt 属性が指定されておらず、ファイル名は image-27-1024x188.png です

あれれ?それもそのはず消えているのです。そう言えばアップロードしたときも↓な感じでメッセージが出てました。

プレビューとかでは見えていたので、「警告かなぁ…まあいいや」と気にしていなかったのですが、実際にアップロードには失敗していた模様。そしてこのファイルこそがsvgだったのです。

なぜ拒否られてたのか?

アップロードできるファイル・タイプがWordPress側で決められているからです。

Uploading Files « WordPress Codex

これはメッセージに出ていたようにセキュリティ上の理由です。

どうすればいいのか?

メッセージから調べたところ、対応方法の記事が以下に見つかりました。

大きく分けて、プラグインを使う方法とそうでない方法があるようです。遅くなりそうだからプラグインを使いたくなくて、

3. Use the Upload_Mimes Filter by Editing Your Theme’s functions.php File

の方法にしようと考えました。テーマのファイルをいじるようですが、テーマと言えばLuxeritas、誰かやってないかなぁとググって↓の記事を見つけました。

ピッタリですね。読んで見ると、今までインストールはしたものの、面倒だったので使ってこなかった「子テーマ」を使うのがいいようです。

子テーマの適用

よく分からないけどポチっと変えてみたら、、、

『設定が共通化されてない!』

直後からカスタマイズした設定の全てがデフォルトに戻っています。親テーマに戻すと戻るのですが、子テーマに変えるとまたデフォルトに…。どうやら設定が共通化されてないようなのです。ここを分ける意味はあったんでしょうか…。どこかに相互にコピーする機能があるのかもしれませんが、まあいうてそんな変えてないので、ポチポチ再設定して復元しました。凝った設定をしてる方、お気をつけください

functions.phpの編集

どうやら子テーマとは、親テーマを直接いじることなく、テーマのphpファイルを書き換えるなどヘビーな操作をWebから行えるようにした、カスタマイズの申し子のようです。どおりでアップデートの頻度が少ないわけです。↓な感じでサクっと編集できます!

でも、これ書き間違えたら二度と直せないような…要るのかな?…この画面…

ちなみに修正は↓のみ。参考文書ではいろいろ他にも処理していましたが、本家のコードにないことはしたくなかったので…

function my_custom_mime_types( $mimes ) {
	$mimes['svg'] = 'image/svg+xml';
	$mimes['svgz'] = 'image/svg+xml';
	return $mimes;
}
add_filter( 'upload_mimes', 'my_custom_mime_types' );

無事アップロード出来たので問題なし、です。ちなみに↓が投稿した記事内のsvg画像のレスポンスヘッダ。

HTTP/1.1 200 OK
Date: Tue, 04 Feb 2020 22:21:33 GMT
Server: Apache
Last-Modified: Tue, 04 Feb 2020 22:16:33 GMT
ETag: "a3c0204-10b0b-59dc7647855c6"
Accept-Ranges: bytes
Content-Length: 68363
Vary: User-Agent
Connection: close
Content-Type: image/svg+xml

普通に返されてるので、少なくとも私のアップロード操作で、別のファイルタイプと勘違いしているような問題は起きてないように見えます。

未分類

前書き

前回はWindows上のVirtualBoxで入れたUbuntuにPostgreSQLをインストールし、簡単なテーブルを作成・表示させてみました。

今回はそのテーブルをWindowsから見てみようという記事です。

Ubuntu側の設定

PostgreSQLの設定

前回はUbuntu上のpsqlコマンドから同じマシン上のPostgreSQLサーバーに接続してSQLを叩いていました。現在のPostgreSQLの設定はこのタイプの接続しか許可していません。別のマシン上のアクセスを許可する設定をしていきます。

この設定は設定ファイルに書かれているので、ターミナル/sshで接続したコマンドプロンプトから、viコマンドを使ってファイルを編集する必要があります。ただ、viはとても癖のあるエディタで機能も少ないので、それを改良したvimを先にインストールします。操作感は同じですが、ハイライトされるなどの機能が違います。

$ sudo apt install -y vim

インストールが終わると、同じviコマンドでも、動きが変わってきます。ではまず、/etc/postgresql/10/main/pg_hba.confを編集して、別のマシンからの接続設定を追加します。

$ sudo vi /etc/postgresql/10/main/pg_hba.conf

viの操作方法(最小限)

キー操作意味
上に移動
下に移動
左に移動
右に移動
i入力モードに入り、以降[ESC]で戻るまで打ち込んだ文字を挿入します。
xカーソル位置の文字を削除します。
dd1行削除します。
[ESC]入力モードから戻ります。
ZZファイルを保存して終了します。
:q!ファイルを保存しないで終了します。

上を参考にどうにかして、ファイル末尾付近に移動して「ココ追加」の1行を追加してみてください。vimでググるとよりいろいろな操作方法を知る事ができますが、覚えることが多いので今は最小限でいいです。

# database superuser can access the database using some other method.
# Noninteractive access to all databases is required during automatic
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# Database administrative login by Unix domain socket
local   all             postgres                                peer

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# ↓ココ追加
host    all             all             10.0.2.2/32             md5
# ↑ココ追加
# IPv6 local connections:
host    all             all             ::1/128                 md5
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            md5
host    replication     all             ::1/128                 md5
"/etc/postgresql/10/main/pg_hba.conf" 102L, 4790C             90,10        末尾

追加したのは、「(ホストから転送されてきた)ホスト自身からの接続の場合、パスワードで認証する」という設定です。10.0.2.2はVirtualBoxがホストに割り当てている仮想ネットワーク上のアドレスです。編集しているpg_hba.confファイルのフォーマットについての詳細は、

20.1. pg_hba.confファイル (PostgreSQLのマニュアル)

を御覧ください。よく分からないと思いますが、丁寧に説明しているとそれぞれ1つの記事になってしまうので、今回は割愛します。

参考: VirtualBoxのネットワークについて

参考: pg_hba.confファイルの認証設定

次にpostgresql.confを編集し、TCP/IPで待ち受ける(listenする)IPアドレスを追加します(デフォルトではTCP/IPで待ち受けていない=IPアドレスでの接続を待ち受けていない)。

$ sudo vi /etc/postgresql/10/main/postgresql.conf

ここでも「ココ追加」と書かれている1行を、どうにかして追加してください。

# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

# - Connection Settings -

#listen_addresses = 'localhost'         # what IP address(es) to listen on;
                                        # comma-separated list of addresses;
                                        # defaults to 'localhost'; use '*' for all
# ↓ここ追加
listen_addresses = '*'                  # what IP address(es) to listen on;
# ↑ここ追加
                                        # (change requires restart)
port = 5432                             # (change requires restart)
max_connections = 100                   # (change requires restart)
#superuser_reserved_connections = 3     # (change requires restart)
unix_socket_directories = '/var/run/postgresql' # comma-separated list of directories
                                        # (change requires restart)
#unix_socket_group = ''                 # (change requires restart)
#unix_socket_permissions = 0777         # begin with 0 to use octal notation
                                        # (change requires restart)
#bonjour = off                          # advertise server via Bonjour
<c/postgresql/10/main/postgresql.conf" 664L, 23154C           64,15-10       8%

完了すると、Ubuntuが持っているネットワークI/F全てで、ポート5432の接続待ちをする設定が追加されます。後はPostgreSQLサービスを再起動して新しい設定を読み込ませるだけです。

$ sudo service postgresql restart

VirtualBoxの設定

sshのときと同様にポートフォワードの設定が必要です。Ubuntuを動かしているVirtualBox上のメニューから、[デバイス]>[ネットワーク]>[ネットワーク設定]を開きます。

[高度]>[ポートフォワーディング]を押します。

上記のようにゲストIPを10.0.2.15でホスト/ゲストポートを5432に設定し、名前を適当につけて[OK]を押します。

すると、ホスト側の5432ポートに来た接続は、ゲスト側のIP10.0.2.15のポート5432に転送されます。この設定がない場合、ファイヤーウォール(NAT)に弾かれて、ホストからゲストにPostgreSQLの標準通信ができません。

Windows側の設定

PostgreSQLクライアントを導入

PostgreSQLクライアントの選定

PostgreSQLの無料クライアントはいくつか種類があります。

最も軽いのはUbuntuで使用したpsql(サーバー同梱)です。これはバッチ実行などをする際にはよく使いますが、コマンドから直に何かしたいとき以外はあまり使いません。

PostgreSQL専用のGUIクライアント兼管理ツールpgadminがあります。これも管理をする際には使いやすいツールです。

今回は、他のDBでも汎用に使用できるGUIのSQLエディタである、DBeaverをご紹介します。これは元々主にJava開発のIDEとして使用されるeclipseのプラグインとして実装されたものです。日本ではこのような種類ではA-5が有名ですが、世界的には現在このDBeaverが無料汎用SQLエディタでNo.1です。

DBeaverのインストール方法

DBeaverのインストールにはいくつか方法があります。

  1. インストーラを使用する
  2. zipを展開してjdkの設定を自分でする
  3. chocolateyを使用してインストールする

今回はchocolateyを使用して、インストールしますが、いずれの方法でも構いません。

Chocolateyとは

以下のリンク先のソフトです。

Chocolatey Software | Chocolatey – The package manager for Windows

Windows用のコマンドラインベースのパッケージ管理ツールに該当します。Ubuntuのaptのような使い勝手のツールです。便利なので、私も可能なときはchocolateyでアプリをインストールしています。便利な点はいくつかありますが、

  • まとめてソフトのアップデートを出来ること
  • インストールしたアプリの一覧をエクスポートし、他のPCにもまとめてインストールすることが出来ること
  • 共通の依存パッケージを複数入れなくて良くなったりすること

くらいでしょうか…

逆にイケてない点は

  • アプリ独自で更新機能を持っているソフトはどっちでアップデートする迷う(DBeaverもそうですが)
  • ユーザーの少ないパッケージは作りが適当で、うまくインストール/アンインストールできない場合がある

辺りです。

Chocolateyのインストール

インストール方法はあらゆるケースを網羅した資料が英語だけど↓にあります。

Chocolatey Software | Installation

私は以下の手順でインストールしています。

  1. Windowsキーを押す
  2. cmdと打ち込んでCtrl+Shift+[Enter]
  3. ユーザーアカウント制御(UAC)の問い合わせに[OK]
  4. 立ち上がった管理者権限のコマンドプロンプトで以下を実行
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command " [System.Net.ServicePointManager]::SecurityProtocol = 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

終わるとchocolateyが使えるようになります。コマンドラインが不得意な人は、続けてchoco install chocolateyguiでGUI版もインストールできます。

DBeaverのインストール

管理者権限のコマンドプロンプトから

cinst dbeaver -y

するだけでインストールは終了します。

Windowsから接続

DBeaverの起動

初回起動時に出てくるポップアップは全部キャンセルします。一度しか見れないメッセージだと間違えるかもしれないので。

左上の新しい接続ボタンを押します。

PostgreSQLのゾウさんを選択して[次へ]

DatabaseとUserとPasswordを記述して、[テスト接続]

まだドライバがないため、ダウンロードするか聞いてくれるので[ダウンロード]

ダウンロードが完了すると、正しく設定されていれば上のようなテスト接続成功画面が出てきます。
満足して[OK]→[終了]してください。

元の画面に戻ると、データベースナビゲータで選べるデータベースが追加されてます。開いてみてください。

ポチポチ押していくと、前回作成したデータベースやテーブルがグラフィカルに表示されてることが分かります。ここでexample_tableをダブルクリックすると…

何やら分かりやすく整理されてテーブルの定義が表示されています。上部中央のデータタブをクリックすると…

当然のようにExcel表のような画面が表示されています。SQLを覚えてpsqlでコマンド叩かなくてもExcelが使える人なら簡単な編集は出来てしまいます。もちろんSQLも便利に使えるソフトです。でも、これでデータベースも怖くなくなりそうじゃないですか?

まとめ

WindowsのVirtualBox上で動くUbuntuに入れたPostgreSQLサーバーを外部からTCP/IPで接続できるように設定し、WindowsからDBeaverを使ってアクセスできるようになった。

次回は、Ubuntu上でVisual Studio codeをインストールし、pythonの開発環境を整えたいと思います(↓)。

未分類

前回まではVirtualBox上のUbuntu18.04にsshサーバーをインストールして、Windowsからsshで繋げられるところまで実施しました。

今回はUbuntu18.04にHerokuでよく使用されるPostgreSQLをインストールして、SQLなDatabaseを使えるようにします。

インストールの前に

Dockerじゃダメなの?

最近の環境構築では、こういうケースで、便利なのでDockerを使うことも多いです。ただし、それはUbuntuやLinuxに慣れてれば、の話なので、今回はまずは基本のローカルインストールを実施します。

Databaseとはどんなもの?

みんなが使用する大規模データを入れておくサーバーです。ファイルサーバーよりもより細かく、大量のデータを検索したり集計したりできます。検索したり集計したりするのに、データの持ち方や、検索・集計に使用するI/Fや言語などの区別により、いろいろな種類のデータベースがあります。

今回インストールするPostgreSQLは古式ゆかしいSQLを使用するRDBMSという分類のデータベースです。Excelのお化けみたいなタイプで、OracleやMySQLなどと同様古くからある、最もオーソドックスなタイプのデータベースになります。

インストール

$ sudo apt install postgresql

いつもどおり、パスワードを入力して、容量確認して"y"でOKです。2020年2月4日現在PostgreSQLの最新バージョンは12ですが、ここでインストールされるバージョンは10になります。これはUbuntu18.04が約2年前のOSであることが原因です。最新バージョンを入れる方法もありますが、そこまで凝ったこともしないので、今回はバージョン10のまま使います。

初期設定など

素のPostgreSQLはpostgresという管理ユーザーが一人だけいるパスワード設定のない管理用のデータしか入っていないデータベースになっています。

管理ユーザーで接続

まずはsudoで PostgreSQLの管理ユーザー postgres になります。

user@ubuntu1804:~$ sudo -i -u postgres bash --login
[sudo] user のパスワード: 
postgres@ubuntu1804:~$ 

PostgreSQLに接続します。ここではPostgreSQLサーバーに同梱されているpsqlコマンドを使います。

postgres@ubuntu1804:~$ psql
psql (10.10 (Ubuntu 10.10-0ubuntu0.18.04.1))
Type "help" for help.

postgres=# 

この状態でPostgreSQLに接続しています。例えば現在操作しようとしているデータベースの状態を調べるには…

postgres-# \conninfo
You are connected to database "postgres" as user "postgres" via socket in "/var/run/postgresql" at port "5432".
postgres-# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
 template0 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(3 rows)

postgres-# 

psqlコマンドの内部コマンドである、\coninfoで、現在接続しているデータベースを調べています。"postgres"という名前のデータベースに接続しています。ややこしいのですが、PostgreSQLに限らずデーターベースサーバー内には通常複数のデータベースが格納されていて、それぞれに名前がついています。この"postgres"という名前のデータベースは、管理用のデータが入っているデータベースです。

その次に実行している\l内部コマンドが、現在接続しているPostgreSQLサーバー内のデータベース一覧です。全て管理用のデータベースなので、普通のデータは格納しませんし、これらのデータベースは基本的に直接いじりません。

管理ユーザーのパスワード設定

まずはpostgresユーザーのパスワードを設定します。 (パスワード)部分にはご自分の覚えやすいパスワードを設定してください。

postgres-# alter user postgres with password '(パスワード)'
postgres-# 

一般ユーザーとデータベース作成

このままPostgreSQL内のユーザー追加と、データベース追加を行います。
(ユーザー)(パスワード)(ユーザーデータベース名)には自分で名前を入れてください(ユーザー名はUbuntuのユーザー名と一致させてください)。ここではそれぞれuser, password, userdbで実施しています。

postgres=# create user "(ユーザー)" password '(パスワード)';
CREATE ROLE
postgres=# create database "(ユーザーデータベース名)" owner "(ユーザー)";
CREATE DATABASE
postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 postgres  | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
 template0 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 userdb    | user     | UTF8     | ja_JP.UTF-8 | ja_JP.UTF-8 | 
(4 rows)

postgres=# 

psqlの内部コマンド\lで新しいデータベースuserdbが所有者userで作成されているのが分かります。

なお、今回設定されたパスワード、実は使用しません。ローカル接続のpeer認証を使っているからなのですが、ネットワーク経由で接続する場合に初めて必要になるのですが、今回はネットワーク経由で使用しないということです(SSLクライアント認証などを使用する場合はネットワーク経由でも使いませんけども…)。

これで一旦管理ユーザーでの作業が終わるので、抜けます。psqlからは\qで、sudo bashからはexitで抜けます。

postgres=# \q
postgres@ubuntu1804:~$ exit
ログアウト
user@ubuntu1804:~$ 

一般ユーザーで接続

改めてpsqlコマンドで繋ぎ直します。(ユーザーデータベース名)(ユーザー)には先程作成したものを使用してください。ここではそれぞれuserdb, userとしています。

user@ubuntu1804:~$ psql -d (ユーザーデータベース名) -U (ユーザー)
psql (10.10 (Ubuntu 10.10-0ubuntu0.18.04.1))
Type "help" for help.

userdb=>

テーブル作成とデータ追加

何もしないのも寂しいのでサンプル程度のデータを作成します。以下を貼り付けて実行してください。create tableでExcel表のようなテーブルを作成し、insertでデータをテーブルに挿入しています。英語圏の人なら何をしているかこれだけで分かるような文法です。

create table example_table (item_id varchar(14) primary key, item_name varchar(100), kakaku numeric(10,0));
insert into example_table values('4514603365511','アサヒ 十六茶 PET500ml',124);
insert into example_table values('4514603343519','アサヒ 十六茶 (LL)紙パックスリム250ml',80);
insert into example_table values('4514603377019','アサヒ 十六茶 PET2L',350);
insert into example_table values('4514603240719','アサヒ 十六茶 PET275ml',115);
insert into example_table values('4514603377217','アサヒ 十六茶 PET630ml',140);
insert into example_table values('4514603240818','アサヒ 十六茶 ボトル缶275g',115);
insert into example_table values('4514603241112','アサヒ 十六茶 缶245g',86);
insert into example_table values('4514603386110','アサヒ 十六茶ほうじ茶 PET630ml',140);
commit;

実行するとexample_tableが作成されて、中にアサヒ飲料様の尊いお茶のデータが数件作成されます。元データは↓のホームページからお借りしました。

JANコード一覧|商品情報|アサヒ飲料

では作成したテーブルのデータをselectで見てみましょう。

userdb=> select * from example_table;
    item_id    |               item_name               | kakaku 
---------------+---------------------------------------+--------
 4514603365511 | アサヒ 十六茶 PET500ml                |    124
 4514603343519 | アサヒ 十六茶 (LL)紙パックスリム250ml |     80
 4514603377019 | アサヒ 十六茶 PET2L                   |    350
 4514603240719 | アサヒ 十六茶 PET275ml                |    115
 4514603377217 | アサヒ 十六茶 PET630ml                |    140
 4514603240818 | アサヒ 十六茶 ボトル缶275g            |    115
 4514603241112 | アサヒ 十六茶 缶245g                  |     86
 4514603386110 | アサヒ 十六茶ほうじ茶 PET630ml        |    140
(8 rows)

userdb=>

それっぽいデータが表示されました。十六茶、皆さんも大好きですよね。

まとめ

WindowsのVirtualBox上にインストールしたUbuntu18.04にPostgreSQLをインストールし、簡単なテーブルを作成、表示してみました。

次回はもう一発PostgreSQLをやります。ホスト側から、DBeaverというSQLエディタを使って操作してみます。