aoishiの備忘録

備忘録

DDNSサービスのMyDNSを使って無料で自宅サーバとVPSのDNS登録してみた

はじめに

固定IPでない自宅サーバへ固定のDNS名でアクセスしたいと思い、DDNS(ダイナミックDNS)サービスであるMyDNSを使ったときの備忘録です。

また、何度も作り直すことが多いVPSサーバも固定のDNS名でアクセスできるようにしてみました。

MyDNSとは

DDNS(ダイナミックDNS)とは

IPアドレス情報を通知することで、動的にDNSサーバの設定を変更して固定のDNS名でアクセスできるようにする仕組みです。

MyDSNでは、POP3, IMAP4, FTP, HTTPを使った通知方法が提供されています。

MyDNS使い方

MyDNS.JPのページに詳細な使い方が記載されています。

Free Dynamic DNS (DDNS) for Home Server and VPS etc | MyDNS.JP

ユーザ登録(MasterIDの発行)

まず、JOIN USにアクセスしてユーザ登録しましょう。

ユーザ登録が完了すると、メールにてID(MasterID)とパスワードが発行されます。 この情報は、MyDSN.JPにログインしたりIPアドレスを通知する際に必要になりますので大事に保管しましょう。

また、後にドメイン登録について説明しますが、1つのMasterIDに対して1つのドメインが利用できるようになります。

ChildIDの発行

次に、MasterIDにぶら下がるChildIDというものを発行します。

このChildIDは、MasterIDで設定したドメイン配下で、追加のIPをDNS設定するために使います。

たとえば、自宅のIPは "myhome.ドメイン名" に設定し、VPSのIPは "www.ドメイン名" のようにDNS設定する際に必要になります。

ではMasterIDでMyDNS.JPにログインして、USER INFOにアクセスします。

子ID関連という箇所があるので、必要な子ID(通知するIP)の数を設定します。デフォルトでは 0 になっています。

設定が完了すると、メールにてChildIDとそのパスワードが送られてきます。

ドメイン登録

それでは、引き続きログインした状態でDOMAIN INFOにアクセスします。

先にも記載しましたが、1つのMasterIDに対して1つのドメインが利用できます。

今回はすべて無料で実現したいので、MyDNSが提供しているドメインから、空いているサブドメインを利用してドメイン登録します。

各入力フォームに対して下記を参考に設定していきます。

  • Domain* : (FQDN)

    希望のドメイン名を入力する。例 {{ 希望のサブドメイン名 }}.mydns.jp など

  • MX : (Hostname, Priority. FQDN)

    未入力の場合は Domain に入力したドメイン名が設定される

  • Hostname, Type, Content, Delegateid or your id. (Hostname is not FQDN)

    • MasterIDと同じIPをDNS設定する場合は、ホスト名, A、MasterIDを選択する。
    • MasterIDと異なるIPをDNS設定する場合は、ホスト名, DELEGATE, 対象のChildIDを選択する。

設定できたら、再度 USER INFO にアクセスしてみましょう。

ページ下部にChildID一覧が表示されており、先ほどドメイン登録で設定したChildIDについて、DNS名が表示されているはずです。

IPアドレスの通知

MyDNS側の設定が完了したので、あとはIPアドレスを通知してDNS設定しましょう。

ここでは、HTTPのベーシック認証を利用した方法でやってみます。 この方法では、MyDNSにHTTPでアクセスした際の接続元IPが通知され、BASIC認証時に利用したIDに登録されているDNS名に設定されます。

下記に curl を使った方法を記載します。

$ curl -s -u {{ MasterID or ChildID }}:{{ IDに対するパスワード }} https://ipv4.mydns.jp/login.html

下記のようなレスポンスが帰ればDNS登録完了です。

<html>
<head>
<title>Free Dynamic DNS (DDNS) for Home Server and VPS etc  | MyDNS.JP</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<LINK href="./site.css" rel=stylesheet type=text/css>

</head>
<BODY BGCOLOR="#FFFFFF"
      TEXT="#304040"
      leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"
>
Login and IP address notify OK.<BR>
login_status = 1.<BR>
<BR>
<DT>MASTERID :</DT><DD>XXXXXXXXXX</DD>
<DT>REMOTE ADDRESS:</DT><DD>xxx.xxx.xxx.xxx</DD>
<DT>ACCESS DAYTIME:</DT><DD>2017/10/31 16:57</DD>
<DT>SERVER ADDRESS:</DT><DD>163.44.151.204</DD>
<BR>

</body>
</html>

あとは、cronなどに仕掛けて定期的に通知させるようにしましょう。

まとめ

MyDNSのサービスを利用して、動的にIPが変わりやすい自宅サーバVPSサーバを固定ドメイン名でアクセスできるようにしてみました。

VPSサーバで作り直すたびにIPが変わっても、構築時にcron登録してワンショット実行すれば、常に同じDNS名で新しいVPSサーバにアクセスできるようになります。

Djangoで文字コードutf8mb4でMySQLに接続する方法

はじめに

Django文字コードがutf8mb4のMySQLデータベースを利用するためのメモです。

絵文字を含むデータを使うために文字コードがutf8mb4のデータベースを作成したのですが、クライアント側の文字コード設定を忘れてしまい、レコード追加時に下記のエラーが発生してしまったので設定方法をまとめました。

django.db.utils.InternalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x8C\\xBF\\x0Ai...' for column 'message' at row 1")

環境

方法

MySQL接続に必要なパッケージのインストール

Python実装のMySQLクライアントライブラリである PyMySQL をインストールします。

$ pip install PyMySQL

文字コードがutf8mb4のデータベースを作成

文字コードがutf8mb4のデータベースを作成します。

mysql> CREATE DATABASE {{ db_name }} CHARACTER SET utf8mb4;

コレーションを明示的に指定する場合は下記のように作成します。

mysql> CREATE DATABASE {{ db_name }} CHARACTER SET utf8mb4 COLLATE {{ collation_name }};
文字コード一覧確認方法

参考までに、MySQLで扱える文字コード一覧とデフォルトのコレーション確認方法です。

mysql> SHOW CHARACTER SET;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
~~~
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
~~~
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
~~~
41 rows in set (0.00 sec)

utf8mb4のコレーション一覧確認方法

utf8mb4で利用可能なコレーション一覧の確認方法です。

mysql> SHOW COLLATION WHERE CHARSET = "utf8mb4";                             
+------------------------+---------+-----+---------+----------+---------+
| Collation              | Charset | Id  | Default | Compiled | Sortlen |
+------------------------+---------+-----+---------+----------+---------+
| utf8mb4_general_ci     | utf8mb4 |  45 | Yes     | Yes      |       1 |
| utf8mb4_bin            | utf8mb4 |  46 |         | Yes      |       1 |
| utf8mb4_unicode_ci     | utf8mb4 | 224 |         | Yes      |       8 |
~~~
26 rows in set (0.00 sec)

settings.pyでutf8mb4の文字コードを設定

settings.pyのDATABASESの設定を修正し、OPTIONSに'charset': 'utf8mb4'を追加します。

charsetを明示的に指定しない場合、Djangoはutf8でデータベースに接続します。

import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '{{ db_name }}',
        'USER': '{{ user_name }}',
        'PASSWORD': '{{ user_password }}',
        'HOST': '{{ db_host }}',
        'PORT': {{ db_port }},
        'OPTIONS': {
            'charset': 'utf8mb4',
        },
    }
}

まとめ

DjangoMySQL文字コードutf8mb4で絵文字を含む文字列を扱うための設定方法をまとめました。

データベース側とクライアント側で文字コードを合わせることでエラーは無事解消しました。

参考資料

https://github.com/PyMySQL/PyMySQL:html

MySQL :: MySQL 5.7 Reference Manual :: 13.1.11 CREATE DATABASE Syntax

Databases | Django documentation | Django

Pythonでloggingモジュール使ってライブラリ内でログ出力する時のまとめ

はじめに

Pythonでloggingモジュールを使う際の備忘録です。

下記の要求を実現することを目的としています。

  • ライブラリ化したいコードがあり、デバッグ目的などでログを出力させたい。
  • ライブラリで発生した例外のトレースも同じログに出力させたい。
  • ライブラリを利用するスクリプトがあり、ログの出力先やログレベルなどをカスタマイズしたい。

方法

ライブラリ側のロギング設定

logging.getLogger()でモジュール名(__name__)を指定して名前付きでロガーを作成します。

ロガーは階層構造になっており、ここで作成したロガーはルートロガーの子ロガーとなります。

ルートロガーはlogging.getLoggerで名前を指定しない場合に取得できますが、 ライブラリ自身はルートロガーは使用せずに、モジュール毎に名前付きで作成されたロガーでログ出力するのが良いようです。

ライブラリ側で作成したロガーにはNullHandlerという何もしない(ログ出力しない)ハンドラーを設定します。

NullHandlerを設定されたロガーは、イベントが記録(ログ出力)されても何もしませんが、 ロガーのpropagate変数がTrueの場合には、イベントが上位ロガーに伝播されるため、そこで設定されたハンドラーによりイベントが処理されます。

ライブラリ利用側ではこの仕組みを利用し、ここで作成したロガーかより上位ロガーに対してロギング設定していきます。

from logging import getLogger, DEBUG, NullHandler
logger = getLogger(__name__)
logger.addHandler(NullHandler())
logger.setLevel(DEBUG)

# ロガーで記録されたイベント(ログ出力)が上位ロガーに伝播されるかどうか。
# True(デフォルト値)の場合、親ロガーを通じルートロガーまで伝播し、上位ロガーのハンドラー設定に応じてログ出力される。
# ロガーとその上位ロガーそれぞれでハンドラーが設定されていた場合は重複してログ出力される。
logger.propagate = True

# ロガーを使用してログ出力する(NullHandlerのためこのままでは何も出力されない)
logger.debug("Hello World")

# 例外のトレースをロガーに出力する(NullHandlerのためこのままでは何も出力されない)
try:
    # ここで例外を発生させる
except Exception as e:
    logger.warning(e, exc_info=True)

ライブラリ利用側のロギング設定

例として、ファイルにログ出力して日時でローテーションするロギング設定を記述します。

先にライブラリ側のロギング設定でも説明しましたが、ライブラリ内で作成したロガーに対して記録されたイベントは上位ロガーを通じてルートロガーにまで伝播されます。

ここでは、簡単のためにlogging.getLogger()で名前を指定せずルートロガーを取得してロギング設定しています。

具体的なロギング設定については参考文献を参照してください。

from logging.handlers import TimedRotatingFileHandler
import logging

# ルートロガーを取得
logger = logging.getLogger()

# フォーマッターを作成
formatter = logging.Formatter('%(asctime)s %(name)s %(funcName)s [%(levelname)s]: %(message)s')

# ハンドラーを作成しフォーマッターを設定
handler = TimedRotatingFileHandler(
    filename="path/to/log.log",
    when="D",
    interval=1,
    backupCount=31,
)
handler.setFormatter(formatter)

# ロガーにハンドラーを設定、イベント捕捉のためのレベルを設定
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)

まとめ

  • ライブラリ側では、何もしないロガーを作成してイベントを記録する。
  • ライブラリ利用側では、ルートロガーを取得してロギング設定する。
  • ライブラリ側およびライブラリ利用側に関らず、ルートロガーにイベントを記録するのは避ける。

参考

ライブラリ側とその利用側のloggingの使い分け方

Logging HOWTO — Python 3.6.3 ドキュメント

ログ出力のための print と import logging はやめてほしい - Qiita

Python標準のloggingでログをJSON形式で出力する - Qiita

例外処理時にエラートレースを出力する方法

29.9. traceback — スタックトレースの表示または取得 — Python 3.6.3 ドキュメント

loggingモジュールで例外処理時にトレース出力する方法

loggingで例外情報を出力する | Python Snippets

loggingモジュールのフォーマット文字列

16.6. logging — Python 用ロギング機能 — Python 3.6.3 ドキュメント

Chromeの拡張機能 smartUp Gestures と Go Back With Backspace で戻る&進む機能を便利に使う

はじめに

Chromeの「戻る」と「進む」機能を使いやすくしようとした備忘録です。

職場でも自宅でも主にノートPCを使っていて、マウスが手元にない場合に使い勝手が悪いと思ったので調べてみました。

環境

環境 OS バージョン
自宅 Fedora26 Chromium 60.0.3112.113(Developer Build)Fedora Project 64bit
職場 Windows10 Chrome 61 64bit

方法

5ボタン以上のマウスを携帯する

マウスが手元にない場合という前提を覆してしまう方法ですが、携帯性のあるものを選ぶというのも手だと思います。 職場では、下記が使いやすいという方がいました。

Bluetooth®ワイヤレスマウス“CAPCLIP” - M-CC1BRBU

Alt + 矢印キーを使う

Chromeの公式ヘルプにも記載がありますし、なんとなくできるかなと思って試してご存知の方も多いかと思います。

キー 機能
Alt + 左矢印 現在のタブの閲覧履歴の中で前にあるページを開く
Alt + 右矢印 現在のタブの閲覧履歴の中で次にあるページを開く

Chrome のキーボード ショートカット - Google Chrome ヘルプ

Chrome52より前のバージョンではBackspaceキーで戻ることができましたが、それ以降のバージョンではAlt+矢印キーに変わったようです。

GoogleのChrome 52では「バックスペースキーを押しても前のページに戻れなくなる」ということで賛否両論が巻き起こる - GIGAZINE

また、後で記載しますが、現在ではBackspaceキーで戻る&進むができるGoogle公式の拡張機能が提供されております。

拡張機能の「CrxMouse」を使う

追記 CrxMouseは閲覧履歴やIPをトラッキングするマルウェアのようです。ご利用は自己責任でお願いします。

マウスジェスチャー系の拡張機能です。

Chrome用マウスジェスチャー「CrxMouse」が最強すぎる! | Hep Hep!

Linuxの場合は右クリックがメニュー表示と干渉するため、デフォルト設定で機能有効にし場合は右クリック2回でメニュー表示になるようです。

高機能なようですが、私は設定で「Enable Mouse Gestures」のみ有効にしています。 「Enable Scrolling」を有効にしていると、ページの中間をスクロールしている際にズーム機能(Ctrl + 上下スクロール)が正常に機能しませんでした。 ちなみに、ページ上部の場合はズームアップ、ページ下部の場合はズームダウンできるようです。

拡張機能の「smartUp Gestures」を使う

CrxMouseがマルウェアということなので、急遽焦って調べました。 Linux環境でも動作し、デフォルト設定のまま問題なく動いています。

smartUp Gestures - Chrome ウェブストア

拡張機能の「Go Back With Backspace」を使う

個人的には Alt + 矢印キー よりも便利だなと思いました。 Shift + Backspaceキー で進むこともできます。

「[Backspace]キーで戻る」機能を復活させる、Google公式のChrome拡張機能リリース -INTERNET Watch Go Back With Backspace - Chrome Web Store

キー 機能
Backspace 現在のタブの閲覧履歴の中で前にあるページを開く
Shift + Backspace 現在のタブの閲覧履歴の中で次にあるページを開く

まとめ

現在の私の環境では、拡張機能で「smartUp Gestures」と「Go Back With Backspace」をインストールしてそれぞれ使っている状態です。 これにより、

  • 矢印キーに指を持ってくよりもBackspaceキーの方が楽に指を運べる
  • 5ボタン以上のマウスでなくても、2,3ボタンのマウスにも適用できる(Thinkpadの赤ポチ大好きなので超便利)

ことで、Chromeの戻る&進む機能が便利に利用できるようになりました!

以上、初めてのはてなブログ投稿でした。