Technologies (16)


あなたのiPhoneの自動ロック時間が変えられない理由

わたしのiPhone(iPhone X)が自動ロックされるまでの時間が30秒以外に変えられない原因が長いことわからなかったのですが、ここ最近続けてきたGoogle断ちの一環でGSuiteをやめた時、ようやくわかりました。

GSuiteの端末管理のせいでした。

GSuiteを使うようなひとには自明だからなのか、これを原因として挙げている解説サイトは皆無…というわけで、ここに書いておきます。

それにしても、GSuiteをやめるのは骨折りだった…。




SVN: server certificate verification failed

I faced such message when I typed “svn update” telling an SSL certification error occurred. Full message is

Server certificate verification failed: certificate has expired, certificate issued for a different hostname, issuer is not trusted

Explaining from the result, I added an option with these comma-separated keywords below;

–trust-server-cert-failures=unknown-ca,cn-mismatch,expired,not-yet-valid,other

I found this solution in the help of “svn update”. Type the command below and read the document carefully because I finally failed to find any advice of someone else.

% svn help update

–trust-server-cert-failures ARG : with –non-interactive, accept SSL server certificates with failures; ARG is comma-separated list of ‘unknown-ca’ (Unknown Authority), ‘cn-mismatch’ (Hostname mismatch), ‘expired’ (Expired certificate), ‘not-yet-valid’ (Not yet valid certificate) and ‘other’ (all other not separately classified certificate errors).

I guess that this problem is common even with “checkout” and other options.
I recommend you check which keyword you need.

I hope this helps you.

コマンドは見たらわかると思うので、日本語では要約にとどめます。

% svn up

でSSLのエラーが出たので、調べました。けっこうな時間を割きましたが、同じ解決策に至った方はおられないようでしたので、書き残します。同様の問題に苦しまれている方はご参照ください。

エラーメッセージは「SSLの証明書の期限が切れており、ホスト名も食い違っているため、発行元が信頼できない」といったところ。

コマンドのオプションのまとめが公式サイトを探しても見つけられなかったのですが、手元のコマンドのヘルプをよく見たらそれっぽいオプションがあったので、書いてみました。その結果、いけました。

たぶん not-yet-valid と other は今回の場合だと要らないと思いますが、試しませんでした。気になる方は調整してください。




イントラネットのProxyを越えよう!

職場や学校など、ウェブブラウザを立ち上げたときに「ユーザー名とパスワードを入力してください」などと表示される環境では、認証したウェブブラウザを経由しない通信はすべて遮断されてしまうことが少なくありません。

そのような現場では、ウェブブラウザを介さずに所属ドメインの外部と通信するプログラムが使えないため、mpmやgit、IDE(SublimetextやEclipseなど)のプラグインのインストールなど、開発環境の構築に不自由します。

とは言え、よく調べてみたところ、まるで何もできない、というわけでもありませんでした。

レジストリ

ウェブブラウザがログイン画面を出す仕組みに、レジストリが関係しています。外部にアクセスする際に、まずレジストリで指定されたURIからプロキシの設定ファイルを読み込みます。

レジストリのエントリは以下です。OSはWindows10です。

\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\AutoConfigURL

プロキシサーバー設定ファイル

このエントリには、おそらく以下のように、プロキシサーバーの設定ファイルへのURLが書かれています。

http://proxy.yourdomain/parh/to/proxy.pac

中身は、要するに、プログラムです。WEB系プログラミング言語を学んだことがあれば、何のプログラムかは検討がつくはず。

わたしが身を置いた環境では、アクセス先のドメイン(URL)によってどのプロキシサーバーに認証を受けに行くかが書いてありました。

プロキシサーバー

設定ファイルに、以下のように書かれた箇所がないか探します。

return “PROXY proxy.yourdomain:8800”;

何箇所かある場合は、ファイル最下部に書かれた「else」の下のものでいいと思います。

このURLのプロキシサーバーから「自動的に認証を受けられる」ように手元のパソコンを設定すれば、外部通信の幅が広がり、何もしないよりは遥かに快適な環境を構築できます。

認証用URLの作成

Windowsの情報のみで恐縮ですが……。

Windowsの環境変数にエントリを追加します。以下のサイトがわかりやすいです。別のサービスの解説サイトですが、環境変数設定は同じです。

WindowsでVargentを使う場合のプロキシ設定

ウェブブラウザで下記の情報で認証すると仮定します。

ユーザー名:user
パスワード:password

次に、認証情報を含むURLを作成します。
以下のようになります。

http://user:password@proxy.yourdomain:8800/

以下のような、URLに認証情報を埋め込む方法を説明しているウェブサイトを見つけて、同じようにやってみてください。

ベーシック認証をURLに直接書く

Windowsの環境変数の設定

以下のエントリを、Windowsの環境変数に追加します。

変数名 http_proxy

整数値 user:password@proxy.yourdomain:8800

同じ整数値で「https_proxy」も作成しておきましょう。

これでmpmは使えるはず!

Sublimetext3

下記の記事のまま、作業してください。

認証付きプロキシの環境でPackage Controlを導入する方法

記事が消えたら困るので簡単に転記します。

Sublime Textの”View” -> “Show Console”でコンソールを表示した後、↓のコマンドを入力

import urllib.request,os,hashlib; h = ‘7183a2d3e96f11eeadd761d777e62404e330c659d4bb41d3bdf022e94cab3cd0’; pf = ‘Package Control.sublime-package’; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler({“http”: “http://[username]:[password]@[proxy_server]:[port]”, “https”: “https://[username]:[password]@[proxy_address]:[port]”})) ); by = urllib.request.urlopen( ‘http://sublime.wbond.net/’ + pf.replace(‘ ‘, ‘%20’)).read(); dh = hashlib.sha256(by).hexdigest(); print(‘Error validating download (got %s instead of %s), please try manual install’ % (dh, h)) if dh != h else open(os.path.join( ipp, pf), ‘wb’ ).write(by)

“Preferences” -> “Package Settings” -> “Package Control” -> “Settings – User”で、プロキシサーバー等の情報を入力

{
“http_proxy”: “http://[proxy_server]:[port]”,
“https_proxy”: “https://[proxy_server]:[port]”,
“proxy_username”: “username”,
“proxy_password”: “password”
}

これでわたしはいけました。

この他のIDEも「○○ proxy」などと検索すれば見つかると思います。

以上です。




iMac5,1にFreeBSDをインストールする話Vol.1

iMac5,1(12年ほど前の機種)にFreeBSD 11.2(最新バージョン)の「i386 DVD」(CDだと止まる)を入れて起動してみたら、なんとインストーラが起動! さっそくそのまま成功例の多いzfsでbsdinstallまかせでバッと入れて再起動したら、iMacのブートローダに出現! やった!
でも、テキトーにブートコードを入れたらダメでした。

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

Snow LeopardのインストールCDを入れてblessしてもダメ。

# bless –device /dev/ada0

ブートローダから消えて焦ったけど、DVDのシェルから以下を打ち込んでリブートしたら復活。

# gpart bootcode -b /boot/pmbr -p /boot/boot1.efifat -i 1 ada0

でもなぜかブートオプションを表示させて(opt押しながら起動)からでないと起動しない…。何とかしたいなーと思いつつ起動させたら、デーモンが表示された。超嬉しかったけど糠喜びで、kernelを読み込んだ直後にフリーズ…なんでや…。

loader promptでなんとかしてみようとしたけど、知識がボロカスになくて不可。ああ…また調べなきゃ…。

だれかタスケテー。

I write my issue in English with effort.

I tried to install with the i386 DVD of the newest FreeBSD 11.2 and it booted! (The installer stopped displaying “CD press any key” when I inserted i386 CD.)
Then I proceeded installing with the easy bsdinstall and installed zfs which many people succeeded with. After completeing install and entered below from the console of temporary Snow Leopard CD:

# bless –device /dev/disk0s1

I made it reboot, then the boot process appeared with the daemon head! Yatta!
But it freezed displaying “Booting…” so I rebooted with DVD and entered a line below:

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0

After rebooting, iMac failed recognizing HDD UFS! Sad!
Quickly I rebooted and entered this line from FreeBSD console of DVD:

# gpart bootcode -b /boot/pmbr -p /boot/boot1.efifat -i 1 ada0

Then the daemon appeared again! and… freezed. Why!

Help me anyone…




WSGIDaemonProcessの謎

mod_wsgiを設定してみた。
環境は FreeBSD11 + Apache24。

ハマったのは、venv のパス。

/usr/local/lib/python3.6/venv

とかに設定してもダメ。encodings というモジュールがないです、と言われてしまう。

どうも大事なのは以下のコマンド。バーチャルホストのホームディレクトリ(あるいはApacheのドキュメントルートのひとつ上あたりのディレクトリ。要するにPythonアプリケーションをインストールしたあたり)で以下を実行する。

$ python -m venv ./venv

したらば、Apacheの設定ファイルに以下のような設定を書く。

<VirtualHost 127.0.0.1:80>
    ServerName www.example.com
    DocumentRoot /path/to/www.example.com/htdocs
    WSGIDaemonProcess www.example.com python-home=/path/to/www.example.com/venv threads=5
    WSGIProcessGroup www.example.com
    WSGIScriptAlias /myapp/ /path/to/www.example.com/myapp/myapp/wsgi.py process-group=www.example.com
    WSGIScriptReloading On
    <Directory /path/to/www.example.com/pyapp/pyapp>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>

python-home=/path/to/www.example.com/venv は、さっき作った venv ディレクトリの絶対パス。

これでなんとか動きました。
が…。
今度は、djangoが認識されない。アプリをウェブから叩いて動かそうとすると、「djangoモジュールが見つからないです」(意訳)とapacheのエラーログに吐き出される。

どうして!? Django公式ドキュメント通りにやってるのに!
と悩むことしばし。

ふと基本に立ち返って「rootじゃダメだよなぁ」と、バーチャルホストのユーザーに切り替えて、バーチャルホストのユーザーディレクトリであれこれコマンドを打ち込んだら、なんとかなった。

わたしがハマった最大の要因は、すべての作業を root で行ったこと。
本来はバーチャルホストのユーザーで行わなくてはいけない。
(わたしはバーチャルホストごとにユーザーを分けています)

そして、バーチャルホストのユーザーディレクトリで完結するように「環境」を整えないといけない。
さすがはPython! PHPとは違う。

$ cd www.example.com
$ python -m venv ./venv
$ ./venv/bin/pip install django
$ ./venv/bin/django-admin startproject myapp
$ ... (以下python公式ドキュメントと同じ。)

こんな感じで、バーチャルホストのディレクトリで作業を完結させる。
すると、「モジュールないですエラー」は出なくなる。

次の問題は…「myappモジュールないですエラー」
わけがわからない…。




Nginx+Apache×2+SSL(+WordPress)

獲得目標は以下の通りです。
●SSLの設定をしたNginxでリバースプロキシをさせて、バックエンドのApacheに渡す。
●Wordpressも動くようにする。

ではさっそく。

Nginx(エンジンエックスと読むそうですね!):

http {
    upstream MidgenasiaServers {
        # バックエンドサーバーの設定をします。
        server 10.0.0.80:8080; # 8080番ポートでhttp通信をListenしているIP 10.0.0.80上のApache 
        server 10.0.0.81:8080; # 8080番ポートでhttp通信をListenしているIP 10.0.0.81上のApache
    }
    upstream OtherServers {
        # こちらもバックエンドサーバーの設定です。上と同じサーバーに格納されている想定です。
        server 10.0.0.80:8081;
        server 10.0.0.81:8081;
    }
    server {
        # http通信はすべてhttpsに301リダイレクトします。
        listen 80;
        return 301 https://$host$request_uri;
    }
    server {
        listen 443 ssl;
        server_name  www.midgen.asia;
        charset utf-8;

        # SSL
        ssl_certificate      path/to/server.crt;
        ssl_certificate_key  path/to/server.key;
        ssl_session_cache  builtin:1000  shared:SSL:10m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers  on;
        # server.keyにパスフレーズを指定してある場合はたぶん必要。パスフレーズだけ書いておけばOK。
        ssl_password_file path/to/server-password;

        location / {
            # upstreamの場所で指定した名称をここに書きます。
            proxy_pass          http://MidgenasiaServers;
            proxy_redirect      off;
            proxy_set_header    Host    $host;
            proxy_set_header    X-Real-IP    $remote_addr;
            proxy_set_header    X-Forwarded-Proto     https;
            proxy_set_header    X-Forwarded-Host      $host;
            proxy_set_header    X-Forwarded-Server    $host;
            proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        }
    }

    # 2つ目のドメインの設定も続けて書きます。
    server {
        server_name  www.another.domain.com;
        charset utf-8;

        ssl_certificate      path/to/another.domain.com.crt;
        ssl_certificate_key  path/to/another.domain.com.key;
        ssl_session_cache  builtin:1000  shared:SSL:10m;
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
        ssl_prefer_server_ciphers  on;
        ssl_password_file path/to/another.domain.com-password;

        location / {
            # 上記と同様に、upstreamの場所で指定した名称をここに書きます。
            proxy_pass    http://OtherServers;
            proxy_redirect      off;
            proxy_set_header    Host    $host;
            proxy_set_header    X-Real-IP    $remote_addr;
            proxy_set_header    X-Forwarded-Proto     https;
            proxy_set_header    X-Forwarded-Host      $host;
            proxy_set_header    X-Forwarded-Server    $host;
            proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
        }
    }
}

※要旨に関係がないコメントや設定は削除してあります。

Apache:

Listen 8080
Listen 8081

>VirtualHost 10.0.0.80:8080<
    ServerName www.midgen.asia
    DocumentRoot "/path/to/midgen.asia.htdocs"
>/VirtualHost<

>VirtualHost 10.0.0.80:8081<
    ServerName www.gowest-comewest.net
    DocumentRoot "/path/to/another.domain.com.htdocs"
>/VirtualHost<

ここまででNginx+SSLとラウンドロビンなApacheは完成。
あとは…Wordpress。リバースプロキシ+SSLという環境下では、特殊な記述をwp-config.phpに加える必要があるようです。

WordPress(wp-config.phpの上のほうに書きます):

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
    && $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
  $_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

参考: WordPressをhttps化してnginx reverse proxy配下で使うには

これでWordpressのCSSやJavaScriptが読み込まれないという状況も打破できます。

できてよかった!




samba4.8でファイル共有

いつものことながら詰まりまくったのでまとめておく。

smb4.confについては、毎度の通り調べて書くわけですが、その際に忘れてはいけないのが、以下。セクションはマウントポイントの名前で大丈夫。

security = user
ntlm auth = yes

次はマウント。最低限必要なのは以下。文字コード等は適当に合わせる。

mount_smbfs -I smb.example.com //user@smb.example.com/mnt /mnt

smb.example.com はIPアドレスでもかまわない。

/mnt はマウントポイント。

/サーバー /クライアント

とする。

そして自動マウント。/etc/fstab に書く。noauto である理由はよくわからないのだけど、ネットワーク越しのマウントだから、完全自動ではなく接続が安定しているときにマウントすべし、ということであろう。もし気になるのであれば調べてください。

//user@smb.example.com/mnt /mnt smbfs rw,-I smb.example.com,-N,noauto

仕上げに、 snmb.conf に自動ログインの記述をする。ファイルの末尾に、

[SMB.EXAMPLE.COM:USER]
user=user
password=yourpassword

などと書く。パスワードはできれば暗号化して、ファイルのパーミッションを600などにするのが望ましい。

マウントは以下のようにコマンドを打てばOK。

mount /mnt

以上!




MySQLが立ち上がらなくて

RaspberryPi3(この、今ご覧になっているサイトのサーバー)のMySQL80-serverが立ち上がらなくなった。
原因は、急に電源を落としたこと。

/var/db/mysql/****.err の中に見つかったエラーメッセージは、こんな感じ。

2018-04-12T13:21:02.033081Z 0 [ERROR] I/O error reading the header from the bina
ry log, errno=175, io cache code=0
2018-04-12T13:21:02.033284Z 0 [ERROR] I/O error reading the header from the bina
ry log
2018-04-12T13:21:02.033352Z 0 [ERROR] Can't init tc log
2018-04-12T13:21:02.033446Z 0 [ERROR] Aborting

ログファイルがおかしいようである。というわけで調べてみた。
見つかったのは以下のブログ。
http://raafat.tawasol.net/mysql-crashes-io-error/

要約すると「怪しいログファイルを削除せよ」

そう言われてもわたしにはよくわからなかったので、

find /var/db/mysql/mysql-bin\* | xargs tar zcvf /tmp/mysql-bin.tgz

などとして退避し、さらにそれらのログをすべて削除したのち、

server mysql-server start

無事起動しました!




MeCab+python+JavaScriptでサイトにルビを振る

標題の通り。意外と簡単にできたので共有します。


※正規表現で先読みと後読みのアサーションを使っているため、最新のEcmaScriptでないと動作しません…PC版Chromeでしか動作しません…なんとかしたい…。


ではさっそく。

python:


#coding: utf-8

from mod_python import apache, util
import re
import json
import MeCab

def handler(req):
    # テキスト取得
    fs  = util.FieldStorage(req, True)
    q   = fs.getfirst("q", "")

    if q:
        tagger  = MeCab.Tagger("-Oyomi")
        node    = tagger.parseToNode(q)

        wordTable   = []
        a2n_regexp  = re.compile("^[あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをんがぎぐげござじずぜぞだぢづでどばびぶべぼぱぴぷぺぽぁぃぅぇぉっゃゅょアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヰヱヲンガギグゲゴザジズゼゾダヂズデドバビブベボパピプペポァィゥェォッャュョヴ]+$")
        while node:
            wordTypes   = node.feature.split(',')
            if node.surface != "" and \
                len(wordTypes) >= 8 and \
                not a2n_regexp.match(node.surface) and \
                wordTypes[7] != node.surface:
                wordTable.append({
                    "y": wordTypes[7] or "*",
                    "k": node.surface or ""
                })
            node    = node.next
        sendJson(req, True, wordTable)

    else:
        sendJson(req, False)
    
    return apache.OK

# JSON形式で返答を返す。
def sendJson(req, result = False, returnValue = []):
    req.content_type    = "application/json; charset=utf-8"
    req.write(json.dumps({"result": result, "words": returnValue}, False, False))



JavaScript:

"use esversion:6";

(function($, d, w, undef) {
    "use strict";

    $(d).on("click", ".furigana-toggler", function(e) {
        if (!$(this).hasClass("on")) {
            $(this).remove();
            furiganaOn();
        }
        e.preventDefault()
    })

    function furiganaOn() {
        $("body").find("*:not([nodeType=1])").each(function() {
            let node = $(this);
            if (node.text() !== "") {
                $.post(
                    "/py/mecab.py/getFurigana",
                    {
                        q : node.text()
                    },
                    function(json) {
                        if (json.result === true && json.words !== undef) {
                            let text  = node.html();
                            let max   = json.words.length;
                            for (let i = 0; i < max; i++) {
                                let regex = new RegExp("(?<!<ruby>[^<>]*)" + json.words[i].k + "(?![^<]*<rt>" + json.words[i].y + "</rt></ruby>)");
                                text = text.replace(
                                    regex,
                                    "<ruby>" + json.words[i].k + "<rp>[</rp><rt>" + json.words[i].y + "</rt><rp>]</rp></ruby>"
                                );
                            }
                            node.html(text);
                        }
                    },
                    "json"
                );
            }
        });
    }
    
    function furiganaOff() {
        $("ruby.furigana, rp.furigana, rt.furigana").unwrap();
    }
})(jQuery, document, window);

pythonの方には何らかの認証機構をつけなければいけませんが、ひとまずこんな感じです。




FreeBSDのコンソールに日本語を表示できるようにする設定

以下の記事を参考にしました。

確かにできました! うれしい!!!

日本語表示できた