NVR510に切り替えてみた。

9月3日に、ルーターをこれまで使っていた NEC Aterm WR8700N から YAMAHA NVR510 に置き換えました。この際だから ONU も NVR510 にセットできる小型 ONU に変更しようかと思いつつ、今のところはそのまま。

IPv6のPPPoEとIPv4のPPPoEをそれぞれセッションとして登録し、これ自体はちゃんと動いたのですが、どうもスタティックルーティングの Flets サービス情報サイトへの接続がうまくいかないのでどうしたもんかと思いつつ。

ZOOT NATIVE IPv4固定IP1個サービスが2ヶ月無料、月額基本料金2,200円(税込)ということだったので、どうせ IPv6 IPoE に切り替えるつもりだったこともあり、9月4日に申し込みしました。

IPoEを申し込むには、自分が使用している回線のお客様ID(CAFxxxxみたいな番号)とアクセスキーが必要になります。IPoEでは、ユーザ認証は網側にこの情報を登録するので、PPPoE とは異なりルータの設定にIDとパスワードは不要になります。

実はこの ID はNTT回線開通時に送られてくる契約書に書かれているのですが、保管してるのは確かなんだけど見つからなかったので116に電話して契約書の再発行をしてもらいました。そのため ZOOT NATIVE 自体の申込みが9月にずれこんだのでした。

それはともかく、ZOOT NATIVE IPv4固定IP1個サービスに申し込むと1時間ほどで登録完了メールが送られてきます。そこには、ルーターの設定に必要な契約サービス情報の

  • 固定IPトンネル終端装置IPv6アドレス
  • インタフェースID
  • グローバル固定IPv4アドレス
  • アップデートサーバーユーザー名
  • アップデートサーバーパスワード
  • アップデートサーバーURL

が記載されていて、これを NVR510 の簡単設定で登録してやればすぐに繋がりました。IPフィルタ設定やDNSサーバなどもそのままで、サービス情報サイト(v6)にもそのまま繋がりました。

また、ZOOTのサーバー構築支援ツールのページから自分のIPアドレスにpingを飛ばすと、ちゃんと応答があります。

固定IPが確認できたので、gonbeiのDNSサーバーに新しいIPを登録し直してとりあえずの作業は完了。一通り設定が終わったので、1週間くらい様子を見て、ZOOT NEXTを解約しようと思います。

自分メモ: ManjaroLinux を pacman -Syu したらいろいろ変わってた点。

 たぶん数カ月ぶりくらいになると思いますが、NVR510 を導入して ZOOT NEXT から ZOOT native に切り替えたのを機に、またサーバ環境を構築しようかと ManjaroLinux を pacman -Syu してみましたが、いろいろ変わってそうなので備忘録。

locale.conf, locale.gen:
locale.conf.pacsaveとして保存されました、とメッセージが出たけど見当たらないので気にしない。locale.genはいくつか新しいlocaleが追加されてました。

/etc/security/limits.d/10-gcr.conf:
10-gcr.conf.pacsaveとして保存されました、と出ていたので、新しいと思われる方を残しておきました。

gnome-keyring:
Symlinkを作ってました。
Created symlink /etc/systemd/user/sockets.target.wants/gnome-keyring-daemon.socket → /usr/lib/systemd/user/gnome-keyring-daemon.socket.

kea:
だいぶ前から出ているメッセージなのでメモだけ。以前のバージョンは2.0、今回のバージョンは2.0.3なので非該当ということで。
## WARNING!##
Upgrading from Kea version <1.6 to version >= 1.6 requires special attention
Please refer to the following web page for details:
[Upgrading to Kea 1.6](https://kb.isc.org/docs/en/upgrading-to-kea-16)
Notable changes include:
 - Files in /var/kea have moved to (/var)/run/kea
 - State Info: now in /usr/lib/kea
 - Hooks: /usr/lib/hooks has moved to /usr/lib/kea/hooks
 - Admin commands lease-{init,version,upgrade} have been renamed
   to db-{init,version,upgrade}
 - Logger configuration changed scope thus a manual configuration
   file intervention is needed)

lightdm.conf:
/etc/lightdm/lightdm.conf.pacnetとしてインストールされました、というメッセージが出たので、内容を確認してマージ。

mkinitcpio.conf:
/etc/mkinitcpio.conf.pacnew としてインストールされました、というメッセージが出たので、内容を確認してマージ。

mariadb:
dbをアップグレードしてね、と出ていたのでアップグレード。
"systemctl restart mariadb.service && mariadb-upgrade -u root -p"

sudo:
/etc/sudoers.pacnew としてインストールされました、と出ていたので内容を確認してマージ。

unbound:
/etc/unbound/unbound.conf.pacnew としてインストールされました、と出ていたので内容を確認。IPv6関係を見直し。

perl:
5.34のmoduleはシステムでは使ってないけど依存関係があったので削除されてないから、
pacman -Qqo '/usr/lib/perl5/5.34'
で調べて対応してちょうだい、と言われたので調べてみたら、x2goserverが呼び出している様子。x2goserverは2021/5/24にビルドされた4.1.0.3-10が最新のようで、perlモジュールをいくつか使用していて、たぶんperlモジュールのバージョンを上げても大丈夫だろうとは思うけど、念のためそのまま残すことに。

ざっと以上です。

NVR510を買ってみた。

 どうも会社PC(VPN)の通信速度が遅いので、プロバイダが悪いのかルータが悪いのかそれともIPv6にすれば速くなるのか(IPv4 over IPv6)、とりあえず参考までにPCをONUに直結して東日本のフレッツサービス情報サイトに繋いでみました。

これはフレッツ網内の速度なので、プロバイダを通した速度とは異なるとは思いますが、まずは倍以上速くなりそうという感触は得られます。


うちはプロバイダはインターリンクで、ZOOT native 固定IP1個というタイプになります。

実はこれまでAterm WR8700nといういささか古いモデルをルータとして使っていましたが、これだとIPoEとかIPIPとかはできないんですよね。なので、ZOOTがIPv6を通してくれるようになったのに恩恵にれていませんでした。

ということで一念発起、YAMAHA NVR510を注文してしまいました。

ちょっと光回線(フレッツNEXTギガファミリー)の契約情報が、これまでサービス情報サイトにちゃんと接続できていなかったのでクラブ登録もできず、NTTにお願いして開通書類の再発行をしてもらっているので、本格的に繋げられるのはもう少し先になりそうです。

スタートアップに登録されているものを削除する。

 CTRL+Shift+ESC でタスクマネージャーを起動してスタートアップのタブを開くと、結構たくさん登録されていて、ここで有効/無効を切り替えてあげればスタートアップ時に実行されることはなくなります。

なくなりますが、この項目をこのタブから削除することはできません。


たとえばターミナルとターミナルプレビューは、現在プレビューを使っていて、以前のターミナルは使っていません。同じような項目が並んでいるのは気持ち悪い。

その他にもシュナイダーのStartup Notification Moduleが2つあったり、ScanSnap Homeが2つあったり。

この項目の実体は複数の方法で登録されていて、一箇所から管理できません。なので個別に見ていく必要があります。

ショートカットのもの

  • C:\Users\%USERNAME%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
  • C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
レジストリのもの

  • コンピューター\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
  • コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

  • コンピューター\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Run
ここらへんから削除してしまえば、スタートアップタブから項目が削除できます。

tkinterでボタンとメニューに同じ関数を割り当てる。

 tkinterでGUIアプリを作っていて、Menubarがあるのでそこにメニューを追加、画面上にボタンも付けて、ボタンを押してもメニューから選んでも同じ処理をしたい、となったんだけれど、ボタンの方は動くのに、メニューの方からは「引数が足りません!」と怒られました。

怒られたコードはざっくりこんな感じ。

    # メニューバー
    menubar = tk.Menu(root, tearoff=False)
    root["menu"] = menubar
    filemenu = tk.Menu(menubar, tearoff=False)
    menubar.add_cascade(label="File", menu=filemenu, accelerator="F")
    filemenu.add_command(label="開く", command=self.open_pyfile)
    
    # ボタン
    self.btn1_text = tk.StringVar()
    self.btn1_text.set(gui_text["button1"])
    button1 = ttk.Button(frame1, textvariable=self.btn1_text, style="TButton")
    button1.bind("<ButtonPress>", self.open_pyfile)

def open_pyfile(self, event):
    """ファイルを開く

    Args:
        event (_type_): _description_

    Returns:
        Path: 選択されたファイル
    """
    ofile = filedialog.askopenfilename(
        initialdir=Path.cwd(),
        title="ファイルを開く",
        filetypes=(
            ("Python files", "*.py;*.pyw"),
            ("JSON files", "*.json"),
            ("All files", "*.*"),
        ),
    )

    self.file1.set(ofile)
    return Path(ofile)
ボタンの方はちゃんと動くけれど、メニューから「開く」を選んだ瞬間に引数が足りないと言われます。 ググってみても検索語の選び方がうまくないのか、lambda: するといいよ、とかいろいろ引っかかるんですが、こうすれば解決できました。
def open_pyfile(self, event=None):
要は、eventが引き数にあればそれでいいし、ない場合にはNoneにしちゃえ、ということです。実際にevent変数を使用した処理をしているなら、event==Noneならメニューから呼ばれたものとして扱えばいいわけですし。

自分的には目からウロコでした。

Path.glob()でExplorer風にソートしてみる。

 Path.globでファイル名に[]を含む場合のエスケープ。で、ワイルドカードに[]が入っていると動作がおかしくなるのでそれをエスケープするというのをやりましたが、同じく glob ネタ。

Explorerではひらがな・カタカナを区別せずにソートしているっぽいですが、Path.glob()とかバッチファイルだとワイルドカードが文字コード順にソートされるので、処理順序がExplorerでの表示順と異なります。ちょっと気持ち悪いので、それっぽくできないかと考えてみました。ちなみに、Explorerでの並び順と正確に同じかどうかは検証してません。それっぽければ問題ないので。

sortedglob.py

#!python3
# -*- coding: utf-8 -*-
# vim:fenc=utf-8 ff=unix ft=python ts=4 sw=4 sts=4 si et fdm fdl=99:
# vim:cinw=if,elif,else,for,while,try,except,finally,def,class:
"""
sortedglob.py:
与えられたパターンに一致するファイル名を取得して、
Explorer風のソートを行い、リストを返す

created : Jun 26, 2022
"""
from pathlib import Path
from jaconv import z2h, kata2hira


def sortedglob(pattern: str):
    """Explorer風にソートするglob.

    patternで渡されたワイルドカードパターンを展開して、
    Explorer風にソートした順番で返す。

    Args:
        pattern (str): globに渡すパターン

    Yields:
        Path: ソートされたPathオブジェクト
    """
    dir = Path(pattern).absolute().parent
    p = Path(pattern).name
    pathlist = {}
    for f in dir.glob(p):
        key = kata2hira(z2h(str(f.absolute()), kana=False, ascii=True, digit=True))
        pathlist[key] = f
    result = sorted(pathlist.items(), key=lambda x: x[0])
    for f in result:
        yield f[1]


if __name__ == "__main__":
    for s in sortedglob("M:/Files/Documents/*"):
        print(s)
jaconvで全角英数を半角にして、カタカナは全部ひらがなに揃えて、それをキーにしてソートします。
さらに漢数字対応とかしてもいいかも。

マルチスレッドとgenerator。

 通常の線形の処理なら問題ないのですが、処理を効率化しようとマルチスレッドにすると、処理をする対象をどうやってスレッドに渡そうかと思うことがあります。

たとえば、たこ焼きを焼いています。

たこ焼き器の凹みをなんて呼ぶのかは知らないのですが、タコツボとでも呼びましょう。

タコツボにはかならず1つのタコを入れます。2つ入れてはいけないし、1つも入ってないのもだめです。

たこ焼き職人が1人なら問題ありません。順序よくタコツボにタコを落としていきます。

職人が2人になると、問題が起こります。タコツボに入れたタコは沈んでしまうので、もうひとりの職人が間違ってもう1個のタコを入れてしまうかもしれません。

それを防ぐためにはタコツボを管理する人が必要です。タコツボを差し出しておいて、どちらかの職人がタコを入れたらすっと引っ込めて次のタコツボを差し出します。そうすればどちらの職人がタコを入れようが、タコツボには1つのタコだけが入ります。


なんて、よくわからない喩え話ですが、要は処理したいシーケンスがあり、そのシーケンスのアイテムは一度だけ処理されればよい、なのでスレッド外で誰かが管理しないといけない、ということです。

リストですと、シングルスレッドならば

for item in itemlist:

で片付きます。ところがマルチスレッドにするといきなりずっこけます。というか、どう言うコードを書いたらいいものかと考えてしまいます。

1つは明らかにitemlistのインデックスを管理するカウント変数を用意して、各スレッドは自分がitemを受け取ったらそのカウント変数を+1する方法です。当然ならそのカウント変数はグローバルになるでしょうから、スレッドセーフではありません。なので、itemを受け取ってカウント変数を+1するまでは、ロックしておかないといけません。

ところがこれがインデックスで管理できるものならよいのですが、たとえばディレクトリツリーを探索する、みたいな感じだとそうも言っていられません。ツリーが巨大になると、そのツリーをリスト化するだけでも結構な時間がかかります。

そこでgeneratorです。アイテムを返すジェネレータを1つだけ用意し、各スレッドから排他的にデータを受け取れれば、二重に処理されるということもありません。

ということで、こんな風にしてみました。


import threading
from random import random
from time import sleep



def get_word():
	l = """
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
"""
	s = l.split(" ")
    for t in s:
        yield t

def tthread(name=""):
    waittime = random()
    while True:
        with lock:
            try:
                t = gen.__next__()
            except StopIteration as e:
                break
        print(f"{t}", end=" ")
        sleep(waittime)


def main():
    t1 = threading.Thread(target=tthread)
    t2 = threading.Thread(target=tthread)
    t1.start()
    t2.start()

gen= get_word()
lock = threading.Lock()
main()
もとの文は PEP 20です。
lockを取得できたら1単語もらって表示する、というだけですが、__next__()がいい仕事してくれます。

SWDなら3線でいいとはいうものの。

 安価で優秀なデバッグプローブはないかしら、と探したら、 Raspberry Pi Debug Probe というのがあったんですが、これは3線がにゅるんと出てるだけです。 もちろんSWDなら3線を繋げばいいのではありますが、汎用的に考えるなら5x2のリボンケーブルコネクタが欲し...