Welcome to kuma35's memo

Contents:

はじめに

2016年03月16日

公開できるメモを置いていきます。備忘です。

Ubuntu Linux を CUI ログインに

2018年04月09日

そもそも正常にログインできてない時

GRUBでlinux...の行のroの後ろ辺りに systemd.unit=multi-user.target を追加して起動。

参考

Ubuntu 15.04 を GRUBメニューから CUI で起動する方法(防備録)

http://qiita.com/ikwzm/items/5514b0fe9a8728e8aecb

正常にログインできているとき

$ systemclt get-default
$ sudo systemctl set-default multi-user.target

GUIログインに戻す

$ systemclt get-default
$ sudo systemctl set-default graphical.target

コンソールで日本語表示

2016年03月16日

videoグループに属してないと使えないので,まずadduserして、 一旦ログオフ、ログオン(一旦ロフオフしないとadduserは反映されない)

$ sudo adduser <<username>> video

インストール。

$ apt-get install fbterm unifont
$ LANG=C
$ fbterm -s 16
$ LANG=ja_JP.UTF-8

LANG=Cしてからfbterm立ち上げると文字が欠けない…なんで?

$ sudo chown <<username>>:<<group>> ~/.fbtermrc

参考

fbterm を使う(Ubuntu 13.10)

http://pulpdust.org/item/1702

fbtermのインストール・設定及びその他まとめ

https://banken07.wordpress.com/2013/02/19/fbterm%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%BB%E8%A8%AD%E5%AE%9A%E5%8F%8A%E3%81%B3%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%BE%E3%81%A8%E3%82%81/

コンソールでCaps LockキーをCtrlにする

/etc/default/keyborad の

XKBOPTIONS=""

XKBOPTIONS="ctrl:nocaps" にして、
$ sudo dpkg-reconfigure -phigh console-setup

でOK。

参考

CapsLockをCtrlにするまとめ

http://lambdalisue.hatenablog.com/entry/2013/09/27/212118

の、「console-setupを利用した方法」参照。

SSHサーバを建てる

2018年08月19日

サーバにOpenSSHをインストール。

$ sudo apt-get install openssh-server

クライアントで共通鍵、秘密鍵生成。ここではclientのマシン名をmeviusとする。 既に作成済のものがあればそのまま使う。

$ ssh-keygen -t rsa -f ~/.ssh/id_rsa.mevius

.ssh に id_rsa.mevius と id_rsa.mevius.pub が出来る。

公開鍵をサーバのauthorized_keyに追加。

$ mkdir ~/.ssh
$ cd .ssh
$ cat id_rsa.mevius.pub >> authorized_keys

クライアントでは秘密鍵を指定してsshにアクセス。 .ssh/configに書いておくと便利。

Host 192.168.1.1
IdentityFile    ~/.ssh/id_rsa.mevius
User            hideo
$ ssh 192.168.1.1

とすると秘密鍵~/.ssh/id_rsa.meviusを自動的に使う。

以後はアクセスするサーバが増える度に手元のid_rsa.mevius.pubをサーバに転送し、authorized_keyへ追加する。

lighttpdインストール

2016年03月16日

on Ubuntu Linux 15.10 i386

$ sudo apt-get install lighttpd

サービス自動起動無効

2016年03月16日

$ sudo systemctl | grep cups
cups.path            loaded active running   CUPS Scheduler
cups-browsed.service loaded active running   Make remote CUPS printers available locally
cups.service         loaded active running   CUPS Scheduler
cups.socket          loaded active running   CUPS Scheduler

$ sudo systemctl disable cups.path cups-browsed.service cups.service cups.socket

ユーザに/ttyUSB0の書き込み権限を付与

2016年03月16日

(ubuntu 15.10 i386)ユーザhideoをdialoutグループに追加する。

$ sudo adduser hideo dialout

ログインしなおす。 ログインしなおさないと反映されないので注意!!

Python3用pip

2016年03月16日

$ sudo apt-get install python3-pip
$ pip3 install pyserial

デフォルトのエディタを変更

2016年03月16日

(Ubuntu 15.10 i386)

$ sudo update-alternatives --config editor

ちなみに、update-alternativesで設定されているグループがどれだけ あるか知りたいときは

$ update-alternatives --get-selections

pyenv on Ubuntu 16.10 amd64

2017年02月04日

sudo apt install python3-venv
pyenv install 3.5.2

pyenv on Ubuntu 15.10 i386

2017年02月04日

sudo apt install libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
pyenv install 3.5.1

CAPSキーをCTRLキーにする(Ubuntu 15.10)

2016年03月16日

CAPSキーをCTRLキーにする(Ubuntu 15.10)(on X Window)

キー追加

dconf reset /org/gnome/settings-daemon/plugins/keyboard/active

Caps Lockキーの設定は/org/gnome/desktop/input-sources/xkb-optionsで設定するのでまず現在の値を見る。

dconf read /org/gnome/desktop/input-sources/xkb-options

デフォルトは未設定で、この場合だとCaps LockキーはCaps Lockとして、CtrlキーはCtrlとしてそれぞれ動作する。 この値を目的に応じて設定する。

Caps LockキーをCtrlキーに割り当てる(元々のCtrlキーはそのままCtrlとして動作する)

dconf write /org/gnome/desktop/input-sources/xkb-options "['ctrl:nocaps']"

CAPSキーをCTRLキーにする(Ubuntu 15.10)(console)

/etc/default/keyboard

# XKBOPTIONS=""
XKBOPTIONS="ctrl:nocaps"            # CapsLock --> Ctrl
# XKBOPTIONS="ctrl:swapcaps"        # CapsLock <-> Ctrl

変更を適用

$ sudo dpkg-reconfigure -phigh console-setup

電源管理

2016年03月16日

ノートPCの蓋を閉じてもサスペンドしない

/etc/systemd/logind.conf

HandleLidSwitch=ignore

サスペンドキーとハイバネーションキーを無効にする

/etc/systemd/logind.conf

HandleSuspendKey
サスペンドキーが押された時に行う動作を定めます。
HandleHibernateKey
ハイバネートキーが押された時に行う動作を定めます。

サスペンドキーとハイバネーションキーを無効にします。

HandleSuspendKey=ignore
HandleHibernateKey=ignore

Read the Docsを使う手順

2016年03月16日

  1. githubとかにリポジトリを作る
  2. Read the Docsでプロジェクト作成
  3. Read the Docsでgithbuのurlを登録
  4. githubの設定のwebhookでreadthedocsを選択
  5. 以後、githubにpushするたびにRead the Docsも更新

デバイス名を固定

2021年09月27日更新

2016年03月24日

高性能USB-TTL/485コンバータ(FT-UBF-TTL485)

高性能USB-TTL/485コンバータ(FT-UBF-TTL485) [1] は、 なにもしないと Arudino NANOと同様 /dev/ttyUSB%n で認識されるため、 どちらの認識が早いかで /dev/ttyUSB0 と /dev/ttyUSB1 が入れ替わることがあるので固定しておく。 更にFT232を使ったドングルを2種類繋ぐことがあるのでATTR{serial}で区別。

Bus 001 Device 010: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

ATTRS{serial}は以下のコマンドで調べた。

$ udevadm info -q all -n /dev/ttyUSB0

/etc/udev/rules.d/ に 62-ft485r.rules を作成。

# for USB-TTL/485 convertor FT-UBF-TTL485
ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",ATTRS{serial}=="A7039N11",KERNEL=="ttyUSB*",SYMLINK+="ttyFT485R"

24ピンDIP-ICサイズ FT232RL USB-シリアル変換モジュール

USB-シリアル変換モジュール FT232RL [2]

/etc/udev/rules.d/ に 62-ft232r.rules を作成。

# for USB-TTL/232 convertor FT232RL
ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",ATTRS{serial}=="AH01JKEI",KERNEL=="ttyUSB*",SYMLINK+="ttyFT232R"

ミニマイコンモジュール [N328P] [3]

Arduino nano互換

Bus 001 Device 019: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter

/etc/udev/rules.d/ に 62-arduino-nano.rules を作成

# for Arduino nano compatible N328P
ATTRS{idVendor}=="1a86",ATTRS{idProduct}=="7523",KERNEL=="ttyUSB*",SYMLINK+="ttyN328P"

マイクロソフト ウェブカメラ LifeCam HD-5000

mjpg-streamerではシンボリックリンクを認識しないので、識別用のみに使用し、realpathコマンドで得たパスを与える。

Bus 002 Device 003: ID 045e:076d Microsoft Corp. LifeCam HD-5000

/etc/udev/rules.d/ に 63-ms-hd5000.rules を作成。

# for MS LifeCam HD-5000
ATTRS{idVendor}=="045e",ATTRS{idProduct}=="076d",KERNEL=="video*",SYMLINK+="webcam1"

マイクロソフト フルHD Webカメラ LifeCam Studio Q2F-00020

mjpg-streamerではシンボリックリンクを認識しないので、識別用のみに使用し、realpathコマンドで得たパスを与える。

Bus 001 Device 008: ID 045e:0772 Microsoft Corp. LifeCam Studio

/etc/udev/rules.d/ に 63-mslifecam.rules を作成。

# for MS LifeCam Studio Q2F-00020
ATTRS{idVendor}=="045e",ATTRS{idProduct}=="0772",KERNEL=="video*",SYMLINK+="webcam2"

USBロケットランチャー

40-rocketlauncher.rules

SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1941", ATTR{idProduct}=="8021", GROUP="plugdev", MODE="0660"
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="0a81", ATTR{idProduct}=="0701", GROUP="plugdev", MODE="0660"
SUBSYSTEM=="usb", ACTION=="add", ATTR{idVendor}=="1130", ATTR{idProduct}=="0202", GROUP="plugdev", MODE="0660"

Footnotes

[1]aitendo。1,250円(税別)( http://www.aitendo.com/product/10245 ) 2016年3月現在。
[2]秋月電子 950円(税別)( http://akizukidenshi.com/catalog/g/gK-01977/ ) 2016年3月現在。
[3]aitendo。1,250円(税別)( http://www.aitendo.com/product/10700 ) 2016年3月現在。

mjpg-streamer (2016年)

2016年08月18日

$ sudo apt-get install subversion libjpeg-dev imagemagick

最新版をsvnリポジトリから取得。そのままcheckoutすると/usr/bin/へmjpg-stramerのバイナリを書き込もうとするので、ignore-extarnalsオプションで抑止する。

$ cd
$ svn checkout --ignore-externals http://svn.code.sf.net/p/mjpg-streamer/code/ mjpg-streamer-code
$ cd ~/mjpg-streamer-code/mjpg-streamer
$ make

注釈

このままの権限で使い続けるのでインストール(sudo make install)はしない。

利用するユーザはvideoグループに属している必要があるので追加する。

$ sudo gpasswd --add <<username>> video

ログアウト、ログインして反映する。

動作確認

$ ./mjpg_streamer -i "./input_uvc.so -d /dev/video1 -y -r 1920x1080 -f 1" -o "./output_http.so -w www"

設定例

Webカメラ用サーバからport8080で送出し、apache2のリバースプロキシで /cam2 に見せる。

Webカメラ用サーバ(192.168.1.2)

$ ./mjpg_streamer -i "./input_uvc.so -d /dev/video1 -r 1920x1080 -f 1 -y -n" -o "./output_http.so -p 8080 -w www"

Webサーバ(192.168.1.6) proxy.conf内で...

ProxyPass /cam2 http://192.168.1.2:808
ProxyPassReverse /cam2 http://192.168.1.2:8080

http://192.168.1.6/cam2 にアクセスすると mjpegで再生される。

デバイス名固定

mjpg-streamerはデバイス名へのシンボリックリンクを辿れないようなので、以下のようにrealpathコマンドを介して利用する。 なお、固定方法そのものについては デバイス名を固定 を参照してください。

$ ./mjpg_streamer -i "./input_uvc.so -d `realpath /dev/webcam2` -r 1920x1080 -f 1 -y -n" -o "./output_http.so -p 9999 -w www"

mjpg-streamer

2020年03月28日

インストール

$ sudo apt install cmake libv4l-dev libjpeg-dev imagemagick
$ cd ~/work
$ git clone https://github.com/jacksonliam/mjpg-streamer.git
$ cd mjpg-streamer/mjpg-streamer-experimental
$ make
$ sudo make install

注釈

systemd対応するので sudo make install まで実施する。

mjpg-streamer用htmlファイルの場所を旧環境に合わせる。

$ sudo cp -rp www /home/httpd/mjpg-streamer

注釈

動作確認はデバイス名固定、デバイス接続後に行います。

デバイス名固定

参考: udev - ArchWiki ( https://wiki.archlinux.jp/index.php/Udev )

調べる

$ sudo udevadm info -q path -n /dev/webcam2
/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/video4linux/video0

で、得られたデバイスパスを以下で指定する。

sudo udevadm info -a -p /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/video4linux/video0
実行結果(抜粋)
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0/video4linux/video0':
  KERNEL=="video0"
  SUBSYSTEM=="video4linux"
  DRIVER==""
  ATTR{dev_debug}=="0"
  ATTR{index}=="0"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5:1.0':
  KERNELS=="1-1.5:1.0"
  SUBSYSTEMS=="usb"
  DRIVERS=="uvcvideo"
  ATTRS{authorized}=="1"
  ATTRS{bAlternateSetting}==" 0"
  ATTRS{bInterfaceClass}=="0e"
  ATTRS{bInterfaceNumber}=="00"
  ATTRS{bInterfaceProtocol}=="00"
  ATTRS{bInterfaceSubClass}=="01"
  ATTRS{bNumEndpoints}=="01"
  ATTRS{iad_bFirstInterface}=="00"
  ATTRS{iad_bFunctionClass}=="0e"
  ATTRS{iad_bFunctionProtocol}=="00"
  ATTRS{iad_bFunctionSubClass}=="03"
  ATTRS{iad_bInterfaceCount}=="02"
  ATTRS{supports_autosuspend}=="1"

looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5':
  KERNELS=="1-1.5"
  SUBSYSTEMS=="usb"
  DRIVERS=="usb"
  ATTRS{authorized}=="1"
  ATTRS{avoid_reset_quirk}=="0"
  ATTRS{bConfigurationValue}=="1"
  ATTRS{bDeviceClass}=="ef"
  ATTRS{bDeviceProtocol}=="01"
  ATTRS{bDeviceSubClass}=="02"
  ATTRS{bMaxPacketSize0}=="64"
  ATTRS{bMaxPower}=="500mA"
  ATTRS{bNumConfigurations}=="1"
  ATTRS{bNumInterfaces}==" 5"
  ATTRS{bcdDevice}=="0113"
  ATTRS{bmAttributes}=="80"
  ATTRS{busnum}=="1"
  ATTRS{configuration}==""
  ATTRS{devnum}=="4"
  ATTRS{devpath}=="1.5"
  ATTRS{devspec}=="(null)"
  ATTRS{idProduct}=="0772"
  ATTRS{idVendor}=="045e"
  ATTRS{ltm_capable}=="no"
  ATTRS{manufacturer}=="Microsoft"
  ATTRS{maxchild}=="0"
  ATTRS{quirks}=="0x0"
  ATTRS{removable}=="removable"
  ATTRS{rx_lanes}=="1"
  ATTRS{speed}=="480"
  ATTRS{tx_lanes}=="1"
  ATTRS{urbnum}=="5183816"
  ATTRS{version}==" 2.00"

マイクロソフト ウェブカメラ LifeCam HD-5000

lsusb コマンドでも調査
Bus 002 Device 003: ID 045e:076d Microsoft Corp. LifeCam HD-5000

/etc/udev/rules.d/ に 63-ms-hd5000.rules を作成。

/etc/udev/rules.d/63-ms-hd5000.rules
# for MS LifeCam HD-5000
ATTRS{idVendor}=="045e",ATTRS{idProduct}=="076d",KERNEL=="video*",SYMLINK+="webcam1"

マイクロソフト フルHD Webカメラ LifeCam Studio Q2F-00020

lsusb コマンドでも調査
Bus 001 Device 008: ID 045e:0772 Microsoft Corp. LifeCam Studio

/etc/udev/rules.d/ に 63-mslifecam.rules を作成。

/etc/udev/rules.d/63-mslifecam.rules
# for MS LifeCam Studio Q2F-00020
ATTRS{idVendor}=="045e",ATTRS{idProduct}=="0772",KERNEL=="video*",SYMLINK+="webcam2"

動作確認

注釈

利用するユーザはvideoグループに属している必要があるので追加する。

sudo gpasswd --add <<username>> video

一旦ログアウト、ログインして反映する。

上記デバイス MS LifeCam HD-5000 の場合(ハーフHD) ※下記例ではポート9999でリッスン。

$ /usr/local/bin/mjpg_streamer -i "input_uvc.so -d /dev/webcam1 -y -r 1280x720 -f 1" -o "output_http.so -p 9999 -w /home/httpd/mjpg-streamer"

上記デバイス MS LifeCam Studio Q2F-00020 の場合(フルHD) ※下記例ではポート9998でリッスン。

$ /usr/local/bin/mjpg_streamer -i "input_uvc.so -d /dev/webcam2 -y -r 1920x1080 -f 1" -o "output_http.so -p 9998 -w /home/httpd/mjpg-streamer"

注釈

2016年時点ではデバイスのシンボリックリンクを辿れなくて 'realpath /dev/webcam1' などとする必要があったが、 2020年時点では不要になっている。

Webブラウザでひらけば拝めるはず…

CTRL+Cで終了。

systemd対応

両カメラとも上記デバイス名固定が動作しているとして、

webcam2

/home/httpd/django/webcam2.service
$ cat /home/httpd/django/webcam2.service
# MJPG-Streamer with MS LifeCam Studio Q2F-00020 on /dev/webcam2
# please add TAG+="systemd" in udev-rule for /dev/webcam2

[Unit]
Description=mjpg_streamer with MS LifeCam Studio Q2F-00020 on /dev/webcam2
After=udev.target
# After=sound.target
After=syslog.target
BindsTo=/dev/webcam2
After=/dev/webcam2

[Service]
type=simple
ExecStart=/usr/local/bin/mjpg_streamer -i 'input_uvc.so -d /dev/webcam2 -y -r 1920x1080 -f 1' -o 'output_http.so -p 9998 -www /home/httpd/mjpg-streamer'

[Install]
WantedBy=multi-user.target
WantedBy=/dev/webcam2

systemd対応(USBポート指定版)

ググると以下の例がゴロゴロ出てくる。でもこの指定だと 挿しているUSBハブやUSBポートまで指定しちゃってるんである。

当然、うっかり挿すポートを変更すると動かないのである。

これが役にたつというと、同じ商品を複数運用するなどの場合かしらん。 挿すUSBポートによって区別するとか。もちろん、そのポートが故障したら この設定ファイルも修正しなければならない。

webcam1

当該デバイスを調べる。挿すポートによって違うので必ず調べること。当然運用中もこのポートに固定すること。 下記はRaspberry Pi 3 USBポート右下(HDMIポートを左に見て)

$ sudo systemctl list-units -t device | grep "LifeCam HD-5000"
sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.5-1\x2d1.5:1.2-sound-card0.device   loaded active plugged LifeCam HD-5000

webcam2

当該デバイスを調べる。挿すポートによって違うので必ず調べること。当然運用中もこのポートに固定すること。 下記はRaspberry Pi 3 USBポート左下(HDMIポートを左に見て)

$ sudo systemctl list-units -t device | grep "LifeCam Studio"
sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device   loaded active plugged LifeCam Studio
/home/httpd/django/webcam2.service
[Unit]
Description=MJPG-Streamer with MS LifeCam Studio Q2F-00020
After=udev.target
After=sound.target
After=syslog.target

BindsTo=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device
After=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device

[Service]
type=simple
ExecStart=/usr/local/bin/mjpg_streamer -i 'input_uvc.so -d /dev/webcam2 -y -r 1920x1080 -f 1' -o 'output_http.so -p 9998 -www /home/httpd/mjpg-streamer'

[Install]
WantedBy=multi-user.target
WantedBy=sys-devices-platform-soc-3f980000.usb-usb1-1\x2d1-1\x2d1.3-1\x2d1.3:1.2-sound-card1.device

インストール

cd /etc/systemd/system
sudo ln -s /home/httpd/django/webcam2.service

動作確認

sudo systemctl start webcam2
sudo systemctl status webcam2

Webブラウザで http://192.168.999.999:9998 を拝んで動作確認する。

起動時に起動するようにする(しばしば忘れる)

sudo systemctl enable webcam2

startx

2016年03月17日

$ sudo systemctl start lightdm

最近は、こうやるそうである。

startx.sh もゴリゴリカスタマイズすれば可能…

X停止

$ sudo systemctl stop lightdm

で、できたけど、これが正式な作法なのかどうかは不明。

コマンドラインもろもろ

2016年03月24日

カレントディレクトリ以下のファイルの大きい順に50個

$ du -ch | sort -rh | head -n 50

特定のディレクトリ以下を除外したファイルリスト作成

$ find $HOME \( -type d -and \( -name '.cache' -or -name '.compiz-1' \) -and -prune \) -or \( -type f -and -print \)

pip install で追加された ~/.local/bin をパスに加える

~/.profile

# for python pip install commands.
if [ -d "$HOME/.local/bin" ]; then
    PATH="$HOME/.local/bin:$PATH"
fi
$ source ~/.profile

ufw

2018年04月05日

$ sudo ufw default DENY
$ sudo ufw allow OpenSSH
$ sudo ufw enable

/etc/ufw/applications.d/openssh-outer-server

[OpenSSH outer]
title=Secure shell server, an rshd replacement
description=OpenSSH is a free implementation of the Secure Shell protocol.
ports=10000/tcp

ルールを削除する方法

その1.ルールの追加したときのコマンドラインでufwの直後にdeleteを付けて実行

追加時

$ sudo ufw allow 8080

それを削除する。

$ sudo ufw delete allow 8080

その2.行番号を指定して削除

$ sudo ufw status numbered
状態: アクティブ

     To                         Action      From
     --                         ------      ----
[ 1] 9999/tcp                   ALLOW IN    Anywhere
[ 2] 80                         ALLOW IN    Anywhere
[ 3] OpenSSH                    ALLOW IN    Anywhere
[ 4] Samba                      ALLOW IN    Anywhere
[ 5] 8080                       ALLOW IN    Anywhere
[ 6] 9999/tcp (v6)              ALLOW IN    Anywhere (v6)
[ 7] 80 (v6)                    ALLOW IN    Anywhere (v6)
[ 8] OpenSSH (v6)               ALLOW IN    Anywhere (v6)
[ 9] Samba (v6)                 ALLOW IN    Anywhere (v6)
[10] 8080 (v6)                  ALLOW IN    Anywhere (v6)
$ sudo ufw delete 5
削除:
allow 8080
操作を続けますか (y|n)? y
ルールを削除しました
$ sudo ufw delete 10

途中に追加する

insert <<number>> RULE

<<number>> の位置にRULEを挿入する。元々<<number>>の位置にあったRULEは後ろにズレる。

x11vnc

2016年03月24日

Ubuntu15.10MATE(on Raspberry Pi 2 model B)

参考のとおりに。

$ sudo apt install x11vnc
$ sudo x11vnc –storepasswd /etc/x11vnc.pass

/lib/systemd/system/x11vnc.service

[Unit]
Description=Start x11vnc at startup.
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth guess -forever -loop -noxdamage -repeat -rfbauth /etc/x11vnc.pass -rfbport 5900 -shared

[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable x11vnc.service

ポート5900を開放する。

$ sudo ufw allow 5900

マシンをリブート

$ sudo reboot

クライアントマシンからアクセス。

$ sudo gvncviewer 192.168.1.2:0

Nexus7では「アンドロイドvnc」で接続できた。Vnc Viewerでは繋がらなかったが原因は未調査。

mailをgmailにリレーするだけ

2016年08月07日

ubuntu 15.10(i386)

メールを全部gmailに放り投げるだけなので、 軽そうなssmtpを使ってみる。

$ sudo apt install ssmtp

/etc/ssmtp/ssmtp.confをいじる。

メールアドレス
hogehoge@gmail.com
パスワード
fuga1234

とする。

mailhub=smtp.gmail.com:587
rewriteDomain=gmail.com
hostname=gmail.com
AuthPass=fuga1234
AuthMethod=LOGIN
UseSTARTTLS=YES
FromLineOverride=YES

再起動等は不要。

テスト

test-mail.txt

To:hogehoge@gmail.com
From:hogehoge@gmail.com
Subject:test-mail

test-mail
$ sudo /usr/sbin/sendmail -t < test-mail.txt

メーラーなりWebメールなりでメールが届いていれば成功。

mailで送る

mailを使うにはUbuntu 16.04LTSではaptする必要があった。

sudo apt install mailutils

ffmpeg

2016年03月19日

$ ffmpeg -f video4linux2 -list_formats all -i /dev/video1

ffmpeg version 2.7.6-0ubuntu0.15.10.1 Copyright (c) 2000-2016 the FFmpeg developers

built with gcc 5.2.1 (Ubuntu 5.2.1-22ubuntu2) 20151010

configuration: --prefix=/usr --extra-version=0ubuntu0.15.10.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/i386-linux-gnu --incdir=/usr/include/i386-linux-gnu --enable-gpl --enable-shared --disable-stripping --enable-avresample --enable-avisynth --enable-frei0r --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-openal --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libxvid --enable-libzvbi --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-libssh --enable-libsoxr --enable-libx264 --enable-libopencv --enable-libx265 --disable-i686

libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
libpostproc 53. 3.100 / 53. 3.100

[video4linux2,v4l2 @ 0xa011d00] Raw : yuyv422 : YUYV 4:2:2 : 640x480 1280x720 960x544 800x448 640x360 424x240 352x288 320x240 800x600 176x144 160x120 1920x1080

[video4linux2,v4l2 @ 0xa011d00] Compressed: mjpeg : Motion-JPEG : 640x480 1920x1080 1280x720 960x544 800x448 640x360 800x600 432x240 352x288 176x144 320x240 160x120

[video4linux2,v4l2 @ 0xa011d00] Raw : Unsupported : YUV 4:2:0 (M420) : 640x480 1280x720 960x544 800x448 640x360 424x240 352x288 320x240 800x600 176x144 160x120 1920x1080

bootstrap tips

2016年07月19日

モーダルダイアログへのデータ渡し

modalでdata-*を渡すときはon('click')...$(#modal).modal()では渡らなかった。 こちらでイベント定義せずにdata-toggle,data-targetを定義しbootstrap側で予め定義されたイベントに任せると上手く渡った。

beaker tips

2016年07月19日

セッションID

session = request.environ.get('beaker.session')
logger.debug(request.get_cookie(session_opts['session.key'])))
logger.debug(pformat(session.id))

session.id でクッキーに設定する予定のと同じid文字列が得られる。 get_cookieは初回、まだクッキーを設定していない時は'None'を返す。

virtualenvからvenvへ移行

2016年09月25日

Ubuntu 16.04LTS(Python 3.5.2)

準備

Ubuntu 16.04LTS(i386)ではpyvenvをインストールする必要があった。

sudo apt install python3-venv

移行作業

元の場所は ${HOME}/.virturalenvs/py3bottle として、移行先フォルダを ${HOME}/work/pyvenv/py3bottle とする。

まず、1階層上までフォルダを作る。

mkdir -p ${HOME}/work/pyvenv

元々のremoteのurlを確認

cd ${HOME}/.virturalenvs/py3bottle
git remote -v

として表示されたoriginのURLを控えておく。

cd ${HOME}/work/pyvenv
git clone ${HOME}/.virtualenv/py3bottle

元のフォルダで git remote -v した結果をcloneしたリポジトリにも反映させる。

git remote set-url origin <<url>>

当該フォルダのvenv環境作成

pyvenv py3bottle

有効化

source ${HOME}/work/pyvenv/py3bottle/bin/activate

とすると有効化できる。

以下のようにしてaliasを組んでおくと便利。

alias py3bottle source ${HOME}/work/pyvenv/py3bottle/bin/activate;cd ${VIRTUAL_ENV}

py3bottleと打つと環境を有効化し、当該ディレクトリに移る。

cd $VIRTUAL_ENV

当該ディレクトリに移動したい時。

venv無効化

有効化している状態で deactivate と入力。

環境の削除

virturalenvと異なりvenvの設定ファイルは当該フォルダ下にしかないので、 当該フォルダを削除するだけでよい。

Python unittestの中でloggingを使う

2016年09月25日

環境

Python 3.5.2(Ubuntu 16.04LTS(i386))

in setUp()

setUp()の中では通常通りloggerを開く。streamHandlerだと何も出ないので FileHandlerなどで他所へ出力してください。この例ではlog_fileで指定した ファイルへ出力しています。

    def setUp(self):
        """Open serial port."""
        self.ser = serial.Serial(com_port,
                                 com_boud,
                                 timeout=com_timeout)
        self.logger = getLogger(__name__)
        formatter = Formatter('%(asctime)s - '
                              '%(levelname)s - '
                              '%(filename)s:%(lineno)d - '
                              '%(funcName)s - '
                              '%(message)s')
        self.sh = FileHandler(log_file, delay=True)
        self.sh.setLevel(DEBUG)
        self.sh.setFormatter(formatter)
        self.logger.setLevel(DEBUG)
        self.logger.addHandler(self.sh)

tearDown()で扱えるよう、shとloggerをself.sh、self.loggerとします。

in tearDown()

sh.close()して、loggerからshをremoveHandler()します。

sh.close()しないと2つ目以降のtestを実行する時にResouce warnng unclose fileと怒られます(実行はできるが、tail -f で追えない)。

Handlerをremoveしないと、当該suite内でテストを実行するたびに Handlerが追加されてログ出力がダブります。

    def tearDown(self):
        """Cosing serial port."""
        self.ser.close()
        self.sh.close();
        self.logger.removeHandler(self.sh)

注意

setUp()とtearDown()なので、当然ながら 各テストごとにログのセットとクローズが走ります。

arduino-mk with Arduino IDE 1.6.12

2019年02月10日

環境

Python 3.5.2(Ubuntu 16.04LTS(i386))

pyserial==3.1.1

Install arduino-mk

とってくる。

git clone https://github.com/sudar/Arduino-Makefile.git

ここでは ${HOME}/work/Arduino-Makefile に置いたとする。

Get Arduino IDE 1.6.12

ArduinoのページからLinux32用を取得し展開。

ここでは ${HOME}/.arduino/arduino-1.6.12 とする。

Makefile

# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
ARDUINO_DIR = $(HOME)/.arduino/arduino-1.6.12
AVR_TOOLS_DIR = $(ARDUINO_DIR)/hardware/tools/avr
ARDMK_DIR = $(HOME)/work/Arduino-Makefile
BOARD_TAG = uno
MONTOR_PORT = /dev/ttyACM0
AVRDUDE_CONF = $(ARDUINO_DIR)/hardware/tools/avr/etc/avrdude.conf
include $(HOME)/work/Arduino-Makefile/Arduino.mk

Arduinoのライブラリ指定する場合は$(HOME)/sketchbook/librariesに追加の上、 ARDUINO_LIBSに列記してください。

# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
ARDUINO_DIR = $(HOME)/.arduino/arduino-1.6.12
AVR_TOOLS_DIR = $(ARDUINO_DIR)/hardware/tools/avr
ARDMK_DIR = $(HOME)/work/Arduino-Makefile
BOARD_TAG = uno
MONTOR_PORT = /dev/ttyACM0
AVRDUDE_CONF = $(ARDUINO_DIR)/hardware/tools/avr/etc/avrdude.conf
ARDUINO_LIBS += Wire Adafruit_MotorShield
include $(HOME)/work/Arduino-Makefile/Arduino.mk

make

compileのみ。

make

compileとアップロード。

make upload

その他

シリアルコンソールはino serialの方が 使いやすかったのでそっちを使っています。

ポリプロピレン(1mm厚)に38mm穴を穿孔

2016年12月04日

木工用ホールソーを使いました。

_images/hole-saw-image1.jpg _images/hole-saw-image2.jpg

今回は下穴3mmを木工用ドリルで穿孔後ホールソーを使いました。

ポリプロピレンは食いつきが悪いので根気よく低速で数十秒回転させる。その後も時々確認しながら低速で根気よく。速度コントロールが重要なのでボール盤ではなく電動ドライバードリル使いました。

なお、写真の商品(amazon https://www.amazon.co.jp/gp/product/B003NVBNW2 )に関してはレビューにある通り、センタードリルを固定するネジのネジ穴にタッピングが必要でしたトホホ(ネジ径M5、ピッチ0.8mm中タップ)。

_images/hole-saw-image3.jpg

byobuのlsのdircolorsを変更

2018年11月22日

Ubuntu 16.04LTS(32bit)

byobu(backend screen)の中でlsしたときの色を変更する。

byoubの中でlsでディレクトリ表示するとダークブラウンの背景に灰色表示とか非常に見難いので、Ubuntuのデフォルトのdircolorsにする。

/usr/share/byobu/profiles/bashrc の中で、 /usr/share/byobu/profiles/dircolorsを読み込んでる。

全ユーザで共有する場合

byobuを起動していない状態で

dircolors -p > /tmp/dircolors.ubuntu
cd /usr/share/byobu/profiles
sudo cp /tmp/dircolors.ubuntu .
sudo mv dircolors dircolors.byobu
sudo ln -s dircolors.ubuntu dircolors

として無理やり変更。

自分の環境のみ

byobuを起動していない状態で

dircolors -p > ${HOME}/.byobu/.dircolors

.byobu/promptファイル

[ -r /usr/share/byobu/profiles/bashrc ] && . /usr/share/byobu/profiles/bashrc  #byobu-prompt#

行を追加する。

[ -r /usr/share/byobu/profiles/bashrc ] && . /usr/share/byobu/profiles/bashrc  #byobu-prompt#
if [ -x /usr/bin/dircolors ]; then
  test -r ${HOME}/.byobu/.dircolors && eval "$(dircolors -b ${HOME}~/.byobu/.dircolors)" || eval "$(dircolors -b)"
  alias ls='ls --color=auto'
  #alias dir='dir --color=auto'
  #alias vdir='vdir --color=auto'

  alias grep='grep --color=auto'
  alias fgrep='fgrep --color=auto'
  alias egrep='egrep --color=auto'
fi

noip2 client daemon for sytemd

2018年01月19日

noip2 client インストール

$ wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz
$ tar xf noip-duc-linux.tar.gz
$ cd noip-2.1.9-1/
$ sudo make install

sign upのユーザ名とパスワードを聞いてくるので入力。配置場所はデフォルトでは バイナリは /usr/local/bin/noip2 で、 conf は /usr/local/etc/noip2.conf

systemd対応

を参考に /lib/systemd/system に noip2.service を作る。

[Unit]
Description=No-IP Dynamic DNS Update Client
After=network-online.target

[Service]
Type=forking
ExecStart=/usr/bin/noip2

[Install]
WantedBy=multi-user.target

有効化する。

$ sudo chmod 644 /usr/local/bin/noip2
$ sudo systemctl enable noip2.service
Created symlink from /etc/systemd/system/multi-user.target.wants/noip2.service to /lib/systemd/system/noip2.service.
$ sudo systemctl status noip2.service
● noip2.service - No-IP Dynamic DNS Update Client
             Loaded: loaded (/lib/systemd/system/noip2.service; enabled; vendor preset: enabled)
             Active: inactive (dead)
$ sudo systemctl start noip2.service
$ sudo systemctl status noip2
● noip2.service - No-IP Dynamic DNS Update Client
             Loaded: loaded (/lib/systemd/system/noip2.service; enabled; vendor preset: enabled)
             Active: active (running) since  2017-01-27 04:55:15 JST; 21s ago
             Process: 1881 ExecStart=/usr/local/bin/noip2 (code=exited, status=0/SUCCESS)
Main PID: 1883 (noip2)
CGroup: /system.slice/noip2.service
        └─1883 /usr/local/bin/noip2

1月 27 04:55:15 merit systemd[1]: Starting No-IP Dynamic DNS Update Client...
1月 27 04:55:15 merit systemd[1]: Started No-IP Dynamic DNS Update Client.
1月 27 04:55:15 merit noip2[1883]: v2.1.9 daemon started with NAT enabled
1月 27 04:55:16 merit noip2[1883]: hogehoge.ddns.net was already set to XXX.XXX.XXX.XXX

ピュアボディ腰部接合部修理

2017年07月02日

  • ファンタスティックブランド(オリエント工業製)
  • ピュアボディ(立像タイプ)
  • 2004年9月お迎え

修理前の状態

腰の接合部が剥がれて上半身下半身に分離。 専用スタンドが脇の下で支える構造のため、足が床から浮き気味となり、 下半身自身の荷重と、ソフビの経年による収縮で接合部が剥がれたものと思われる。

修理前全身 修理前上半身 修理前下半身

修正箇所

発泡材盛り上がりを是正

ソフトビニール(肌色)の接合面より発泡材が土手のように膨らんでいる。 ソフトビニールの収縮によるものと思われ、 ソフトビニールの接合部がうまく合わさらないので、この部分を ソフトビニールの接合面ツライチになるよう切削した。

カッターナイフで簡単に切削することができた。

上半身接合部発泡材盛り上り

接合面傾斜是正

下半身ソフトビニール接合部が水平でなかった。 水平に近づける為、内側の山側を中心に外側のエッヂで水平に近づけるよう 切削した。カッターナイフで切削した。

下半身接合部傾斜

内側の山側を中心に外側のエッヂで水平に近づけるよう切削した。

下半身接合部傾斜是正

接着

接着剤で接着し、接着面に圧を掛けるため倒立状態で固定。

接着

今回利用した接着剤。硬化後も無色透明で弾力があるタイプ。

接着剤

接着増し増し

圧が均等でなかったためか、結構隙間ができた。 隙間を埋めるよう更に接着剤を盛り、なるべく均等に圧が掛るよう固定。

接着2

thunderbird引越し

2018年01月21日

Ubuntu16.04LTSにて。

引越し元

${HOME}/.thunderbird 以下を丸ごとコピー。

引っ越し先

${HOME}

ROS

2018年04月09日

ROSインストール

for Ubuntu 16.04 LTS(Xenial) i386

それぞれのバージョンが、ディストリビューションの特定のバージョンでしかインストールできないことに注意。

当該ディストリビューション用ソースから作成する場合も同様に束縛される。

よってディストリビューション、バージョン、アーキテクチャに 適合するROSのバージョンをを選ぶ必要がある。

Ubuntu 16.04 LTS(Xenial) i386 なら、選べるので最新のはKinetic

2018/4/2 時点で shadow-repository 使うと

$ sudo apt update
$ sudo apt list ^ros | less
$ sudo apt list | grep ^ros | less
$ sudo apt install ros-kinetic-desktop-full

入門

.bashrc

~/.bashrc に追加。

#for ROS kinetic
source ${HOME}/catkin_ws/devel/setup.bash

rosdep

$ sudo rosdep init

initは/etc/apt/apt.source.d/へaptライン追加なのでsudoで実行。初回のみ。

$ rosdep update

updateは${HOME}/.ros/内のリストとキャッシュを更新する作業なので 当該userで実行する。

うっかりsudoすると以後updateするときやリストを利用する時に権限無くてエラーになる。その際は sudo chown -R .ros hoge:hoge で権限を修正する。

venv環境をプロンプトに表示

2020年04月11日

現在のvenv環境を知る

activateで環境変数 VIRTUAL_ENV がセットされる。 deactivateでアンセット。

$ echo $VIRTUAL_ENV
/home/hideo/work/memosphinx/venv

よってこのまま表示するなら、 プロンプトで $VIRTUAL_ENV を指定するだけでOK。

venvフォルダを含むフォルダ名だけ表示したい。

$ echo $(basename $(dirname $VIRTUAL_ENV))
memosphinx

結論

.bashrcで以下の関数を定義。

function venvname() {
    # https://qiita.com/ymdymd/items/51bf4145ec58654eaffc
    if [ "${VIRTUAL_ENV:+UNDEF}" ]; then
        echo $(basename $(dirname $VIRTUAL_ENV))
    fi
}

プロンプトの方は以下のように書き換える。

if [ "$color_prompt" = yes ]; then
    PS1='`venvname`\n${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\n\$ '
else
    PS1='`venvname`\n${debian_chroot:+($debian_chroot)}\u@\h:\w\n\$ '
fi

こうすると、venv環境内にあるときは以下のようなプロンプトとなる。

(venv) memosphinx
hideo@winston:~/work/memosphinx
$

emacs grep-find サンプル集

2020年05月31日

pythonやperl内で使うのに慣れていて、シェル内で使うgrepの正規表現 に慣れていないので。 例えばgrepの場合、繰り返しの + の前にはバックスラッシュが必要だったり。

([A-Z]+)

カレントディレクトリの *.po ファイルより 丸括弧で囲まれた英大文字2つ以上の文字列を取得。 例えば、 (AC)(CDC) など。

find . -type f -name \*.po -exec grep --color -nH -e "([[:upper:]]\{2,\})" {} +

応用 [(;][A-Z]+)

(interface association descriptor;IAD) という表記を引っ張ってくる。

find . -type f -exec grep --color -nH -e "[(;][[:upper:]]\{2,\})" {} +

.[[:lower:]]{3}W

2020年06月07日

ピリオド(.)で始まり小文字3文字で終わるのを取ってくる(拡張子等)

find . -type f -name \*.rst -exec grep --color -nH -e "\.[[:lower:]]\{3\}\W" {} +

0b[01]+

2020年06月14日

独自の2進数形式 0b0101... を探してくる。

find . -type f -name \*.rst -exec grep --color -nH -e "0b[01]\+"  {} +

-[[:upper:]]

2020年06月15日

Kindleでハイフネーションをつなげた時に、ハイフンの後が大文字だと ハイフンを残したまま繋げる事があり、それを検出するため。

find . -type f -name \*.rst -exec grep --color -nH -e"\-[[:upper:]]"  {} +

emacs po-mode Symbol’s function definition is void: po-with-temp-buffer

2021年09月18日

Ubuntu 20.04.2 LTSにアップグレードしたら GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.14) of 2020-03-26, modified by Debian でPOファイルを開いたときに

and: Symbol’s function definition is void: po-with-temp-buffer

とエラーが出てファイル読み込めなくなった。

.emacs.d/intl.el に

(require 'po)
(require 'po-mode)

追加したら動くようになった。これが正しい対処方法かどうかは不明。

(Emacs21.2以降にはpo.elって名前でpo-compat.el相当のファイルがバンドルされている)

Emacs Lisp

emacs lisp の 型はコレだけ(?)

  • シンボル
  • 整数
  • 文字列
  • ベクタ(リスト?)
  • コンスセル
  • 浮動小数点数

つまり、こうかな? - シンボル - 即値(整数、文字列、浮動小数点数) - リスト(ベクタ、コンスセル)

 enum Lisp_Type
 {
   /* Symbol.  XSYMBOL (object) points to a struct Lisp_Symbol.  */
   Lisp_Symbol = 0,

   /* Type 1 is currently unused.  */

   /* Fixnum.  XFIXNUM (obj) is the integer value.  */
   Lisp_Int0 = 2,
   Lisp_Int1 = USE_LSB_TAG ? 6 : 3,

   /* String.  XSTRING (object) points to a struct Lisp_String.
      The length of the string, and its contents, are stored therein.  */
   Lisp_String = 4,

   /* Vector of Lisp objects, or something resembling it.
      XVECTOR (object) points to a struct Lisp_Vector, which contains
      the size and contents.  The size field also contains the type
      information, if it's not a real vector object.  */
   Lisp_Vectorlike = 5,

   /* Cons.  XCONS (object) points to a struct Lisp_Cons.  */
   Lisp_Cons = USE_LSB_TAG ? 3 : 6,

   /* Must be last entry in Lisp_Type enumeration.  */
   Lisp_Float = 7
};

コンスセル

struct Lisp_Cons
{
  union
  {
    struct
    {
      /* Car of this cons cell.  */
      Lisp_Object car;

      union
      {
        /* Cdr of this cons cell.  */
        Lisp_Object cdr;

        /* Used to chain conses on a free list.  */
        struct Lisp_Cons *chain;
      } u;
    } s;
    GCALIGNED_UNION_MEMBER
  } u;
};

シンボル

struct Lisp_Symbol
{
  union
  {
    struct
    {
      bool_bf gcmarkbit : 1;

      /* Indicates where the value can be found:
         0 : it's a plain var, the value is in the `value' field.
         1 : it's a varalias, the value is really in the `alias' symbol.
         2 : it's a localized var, the value is in the `blv' object.
         3 : it's a forwarding variable, the value is in `forward'.  */
      ENUM_BF (symbol_redirect) redirect : 3;

      /* 0 : normal case, just set the value
         1 : constant, cannot set, e.g. nil, t, :keywords.
         2 : trap the write, call watcher functions.  */
      ENUM_BF (symbol_trapped_write) trapped_write : 2;

      /* Interned state of the symbol.  This is an enumerator from
         enum symbol_interned.  */
      unsigned interned : 2;

      /* True means that this variable has been explicitly declared
         special (with `defvar' etc), and shouldn't be lexically bound.  */
      bool_bf declared_special : 1;

      /* True if pointed to from purespace and hence can't be GC'd.  */
      bool_bf pinned : 1;

      /* The symbol's name, as a Lisp string.  */
      Lisp_Object name;

      /* Value of the symbol or Qunbound if unbound.  Which alternative of the
         union is used depends on the `redirect' field above.  */
      union {
        Lisp_Object value;
        struct Lisp_Symbol *alias;
        struct Lisp_Buffer_Local_Value *blv;
        lispfwd fwd;
      } val;

      /* Function value of the symbol or Qnil if not fboundp.  */
      Lisp_Object function;

      /* The symbol's property list.  */
      Lisp_Object plist;

      /* Next symbol in obarray bucket, if the symbol is interned.  */
      struct Lisp_Symbol *next;
    } s;
    GCALIGNED_UNION_MEMBER
  } u;
};

静的HTMLの翻訳

2021年07月10日

経緯

libusbの文書を翻訳することにした。libusbの文書は、

  • doxygenを使ってソースファイル(C言語)から生成する。
  • doxygen様々な形式で出力できるがlibusbはhtml出力。
  • 翻訳するとなると、ソースファイル(のコメント)または出力をいじる事になる。
  • ソースファイル改変なんかしたくないのでhtmlをいじることにする。

翻訳ツール

po4a

gettext - po なプロセスをプログラム言語以外でもやりたい!という代物。htmlもOK。今回はコレを利用した。

omegaT

GUIなツール。各種有料・無料サービスとも連携可能なようです。 以前もhtmlを翻訳したことあるけれども、致命的な問題なく扱うことができる。 内蔵エディタはキーバインドとかナニソレなのでそこの部分の作業効率はあがらない。 (sed文書翻訳に使用)

GNUN

GNUnited Nations

gnu.orgのドキュメント翻訳用。 フォルダがgnu.org専用に固定されちゃってるとか、gnu.orgへ投稿前提とか、正に専用ツールなのでそれ以外の用途には使いにくい。

google翻訳者ツールキット

(webサービス) 既にサービス終了。

sphinx-intl

sphinx文書であれば問題なく翻訳を行える。 reStructureのディレクティブ等もちゃんと認識した上で原文切り出ししてくれる (Scrapy文書、pyusb文書、Thinking Forth翻訳に使用)。

pandoc

翻訳ツールじゃなくて形式変換だけども。

LaTex → reStructure に使用したが、変換不能な部分が多く散々であった(Thinking Forth翻訳に利用)。

翻訳サイト

翻訳そのものは google翻訳 や weblio辞書 で済ませています。必要に応じて更にググります。

po4a

通常プログラムソースファイルで使われる gettext を、html等様々な形式のテキストでも使えるようにしようという試み。らしい。

po4aをそのまま使う訳ではない

私は原文1ファイルに対して翻訳作業用のファイル(po)も1つという対応で作業したいんである。 しかしpo4aは原文ファイル全てを1つのpoファイルにまとめちゃうんである。 言語毎に1つのpoファイルという発想のようである。

よってpo4a統合コマンド(とpo4a.cfg)は使わずに、個々のコマンドをリッチgettextとして呼び出すのである。

作業環境

  • sudo apt install doxygen libusbでドキュメントを生成するために必要(配布物にはドキュメントは含まれていないため手元で生成する必要有る)
  • sudo apt install libudev-dev autogen.sh実行時に必要

libusbのバイナリをコンパイルしなくても doc/Makefile の実行だけでドキュメントは生成できる。

フォルダ構成

  • ./ Makefile等
  • source/api-1.0 原文ファイル群(html,js,css)
  • po poファイル群
  • docs/ 訳文書(翻訳を適用したhtml、jsとcssはsourceからコピー)

原文を用意する

libusbはautogen.shを実行すると各フォルダにMakefileが生成される。

docディレクトリに入り、(docディレクトリの) Makefile を実行すると doc/api-1.0 に文書が出来る。

今回は api-1.0/* を libusb翻訳作業用の source/ にコピーして使用。

初回・原文ファイル追加時のみの作業

初回または原文ファイルが追加された時。

初回専用スクリプト

#!/bin/sh
find ./source/libusb.sourceforge.io/api-1.0/ -name "*.html" -printf "po4a-gettextize --format xhtml --master %p --master-charset utf-8 --copyright-holder \"libusb\" --package-name \"libusb\" --package-version \"0.0\" --po ./po/%f.po\n"

原文ファイル追加時用スクリプト

po4a-gettextize --format xhtml --master source/api-1.0/functions_vars.html --master-charset UTF-8  --copyright-holder libusb --package-name "libusb-api-doc" --package-version "1.0" --po po/functions_vars.html.po

いままで存在していなかった functions_vars.html が追加になった時のスクリプト

POヘッダ編集

生成した全てのPOファイルについて、POヘッダを設定する必要がある。 設定しないとPOファイルコンパイルやpo4a-updatepo(msgmerge)でエラーになる。

# -*- coding: utf-8 -*-
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR libusb
# This file is distributed under the same license as the libusb package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: libusb-api-doc 1.0\n"
"POT-Creation-Date: 2021-07-09 02:36+0900\n"
"PO-Revision-Date: 2021-07-09 02:54+0900\n"
"Last-Translator: kuma35\n"
"Language-Team: Japanese\n"
"Language: ja_JP\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
  • #コマンドでコメント編集にしておまじないを追加 -- coding: utf-8 --
  • Last-Translator Language-Team Language Content-Type を表記の通りとする。

翻訳

poファイルを編集する。emacs po-modeなど

訳文書生成

make html

Makefileの詳細は下記 Makefile 参照。

「80%に達していないので…破棄」

po4a-translateのkeepオプション(--keep)のデフォルトが80に設定されているため。 --keep 0 と設定すれば翻訳の進捗に関わらず訳文書を生成するようになる。

原文更新

make updatepo

Makefileの詳細は下記 Makefile 参照。

なお、原文に新しいファイルが追加された場合、make html でエラーとなるので上記 原文ファイル追加時用スクリプト を参考にpoファイルを追加する。

Makefile

訳文書生成原文更新 で使うMakefile

# SRC_DIR = source/libusb.sourceforge.io/api-1.0
SRC_DIR = source/api-1.0
PO_DIR = po
TARGET_DIR = docs

SRC_ALL = $(wildcard $(SRC_DIR)/*)

SRC_HTML = $(filter %.html,$(SRC_ALL))
SRC_OTHER = $(filter-out %.html,$(SRC_ALL))

PO_PO = $(wildcard $(PO_DIR)/*.html.po)

TARGET_HTML = $(addprefix $(TARGET_DIR)/,$(notdir $(SRC_HTML)))
TARGET_OTHER = $(addprefix $(TARGET_DIR)/,$(notdir $(SRC_OTHER)))

a_file = $(addsuffix $(3),$(addprefix $(1)/,$(notdir $(basename $(2)))))


html: $(TARGET_HTML) $(TARGET_OTHER)

updatepo: $(PO_PO)

# static pattern
$(TARGET_HTML): $(TARGET_DIR)/%.html : $(PO_DIR)/%.html.po
   po4a-translate -v --format xhtml --master $(call a_file,$(SRC_DIR),$@,.html) --master-charset UTF-8 --po $? --localized $(call a_file,$(TARGET_DIR),$@,.html) --localized-charset UTF-8 --keep 0

$(TARGET_OTHER): $(TARGET_DIR)/% : $(SRC_DIR)/%
   cp -v -u $? $@

$(PO_PO): $(PO_DIR)/%.html.po : $(SRC_DIR)/%.html
   po4a-updatepo --format xhtml --master $? --master-charset UTF-8 --previous --copyright-holder "libusb" --package-name "libusb" --package-version "1.0" --po $@

.PHONY: html updatepo

kivy.resources

2023年03月02日

kivy.resources.resouce_paths

「あらかじめ決められた一連のフォルダーを検索します。 」

っていうのがこのリストである。

初期値は

['.',
'',
'<venv_dir>/lib/python3.10/site-packages/kivy',
'<venv_dir>/lib/python3.10/site-packages/kivy/data/..']

で、ソースは

['.',
dirname(sys.argv[0]),
dirname(kivy.__file__),
join(kivy_data_dir, '..')]

iOS の場合は:

['.',
dirname(sys.argv[0]),
join(dirname(sys.argv[0]), 'YourApp'),
dirname(kivy.__file__),
join(kivy_data_dir, '..')]

である。

ただし、検索時は reversed(resource_paths) するので後ろから前への順番で 行うことに注意。

resource_add_path

resources_paths の「末尾」に追加する。よって追加した path が検索対象として 真っ先に検索される。

既に登録済のものがあった場合は何もしないので、 優先順位を上げたい場合は 一旦 resource_remove_path してから resource_add_path する必要があるだろう。

追加する path は一切加工されない。 abspath() とか一切しない。

resource_remove_path

既にリストの中に path があれば削除する。

引数で指定する path は一切加工しないので、リスト中に存在するパスと全く 同じものを指定しなければならない。

resource_find

filename に resource_paths というリストの中の パスを「逆順」に適用しながら、探します。

つまり resource_paths に /hoge/fuga というパスが あれば join('/hoge/fuga', filename) というファイルを探します。

無かったら作成とかしません。無かったら None を返します。 まずそこが大前提です。

よって filename が None だったら 単に return します。

  1. use_cache が True の場合は 60 秒以内は無条件にキャッシュされた ものが返ってきてしまいます。 一旦 use_chche を False にして使うか、 60 秒を超えて待ちましょう(?)
  2. filename の 先頭が 'atlas://' なら 何もせずに filename をそのまま返します。
  3. abspath(filename) 存在してるパスなら abspath() したものを返します。
  4. abspath(join(<resource_paths のパス>, filename)) が 存在したならそれを返します。
  5. filename.startswith("data:") filename が 'data:' で始まる場合は filenameそのものを返します
  6. use_cache が True で、 返す found_filename があるなら、 found_filename をキャッシュに登録します。
  7. とにかく何かあれば found_filename を返して 無ければ None を返します。