Quantcast
Channel: mattintosh note
Viewing all 878 articles
Browse latest View live

Raspberry Pi で入退室記録的なものをやってみた

$
0
0

Felica使って遊んでみたいなと思ったので PaSoRiを買ってみた。

f:id:mattintosh4:20170625193452j:plain

とりあえず Pythonの nfcpy モジュールで IDmは取得できるようになったので、SQLiteIDmのリストやら社員名簿やらを作った。本当は Pythonオンリーで書きたかったけど、時間がなかったので Shell から Pythonを呼び出すようにした。外部サービスに投げるテストとして Tocaro を利用。

f:id:mattintosh4:20170625193507p:plain

とりあえず IDmと社員番号、社員番号と名前を紐付けられるようなテーブルを作成。時間を記録するテーブルは SQLiteCURRENT_TIMESTAMPに任せる。もうひとつ、「入」と「出」を記録するテーブルを作ってフラグを更新するようにしておくといいかもしれない。(帰るときにカード通し忘れるとずっと入室したままになるので0時リセットとかも組んで)

createtable FELICA_EMP (
    'IDM'       TEXT    NOTNULLUNIQUE
,   'EMP_ID'    TEXT    NOTNULL
,   'TYPE_ID'NUMBER
);

createtable EMPLOYEES (
    'EMP_ID'NUMBERNOTNULLUNIQUE
,   'LNAME'     TEXT    NOTNULL
,   'FNAME'     TEXT    NOTNULL
,   'E_LNAME'   TEXT    NOTNULL
,   'E_FNAME'   TEXT    NOTNULL
,   'H_LNAME'   TEXT    NOTNULL
,   'H_FNAME'   TEXT    NOTNULL
);

createtable FELICA_TYPE (
    'TYPE_ID'NUMBERNOTNULLUNIQUE
,   'NAME'      TEXT    NOTNULLUNIQUE
);

createtable TIME_CARD (
    'TIMESTAMP'DATENOTNULLDEFAULT CURRENT_TIMESTAMP
,   'IDM'       TEXT    NOTNULL
);

insertinto FELICA_EMP  values('01010XXXXXXXXXXX',00000,1);
insertinto FELICA_EMP  values('01010XXXXXXXXXXX',00000,2);
insertinto FELICA_EMP  values('01140XXXXXXXXXXX',00000,3);
insertinto FELICA_EMP  values('01120XXXXXXXXXXX',00000,4);

insertinto EMPLOYEES   values(00000,'山田','太郎','やまだ','たろう','Yamada','Taro');

insertinto FELICA_TYPE values(1,'Suica(JR)'        );
insertinto FELICA_TYPE values(2,'Suica(りんかい線)');
insertinto FELICA_TYPE values(3,'Suica(モノレール)');
insertinto FELICA_TYPE values(4,'PASMO'            );


出勤記録的なやつ #RaspberryPi #NFC #Suica

Makoto Yoshidaさん(@mattintosh4)がシェアした投稿 -


圧電スピーカーを買ったまま使ってなかったので、ファミリー○ートの入店音を PWM で作成。音楽やってたはずなのに楽譜全然よめなくなっててびっくり。MIDIデータでそのまま投げられると楽なんだけど、とりあえず八分音符で周波数ベタ書き。

#!/usr/bin/python2import RPi.GPIO as GPIO
import time

gpio_pin = 4

GPIO.setmode(GPIO.BCM)
GPIO.setup(gpio_pin, GPIO.OUT, initial = GPIO.LOW)
p = GPIO.PWM(gpio_pin, 440)

scales = [
    369.994
,   311.127
,   220.000
,   311.127
,   329.628
,   440.000,440.000,440.000
,   329.628
,   369.994
,   329.628
,   220.000
,   311.127,311.127
]

try:
    p.start(20)
    for i in scales:
        p.ChangeFrequency(i)
        time.sleep(0.3)
    p.stop()
finally:
    GPIO.cleanup()



実用するかどうかと言われれば多分しない。というのも、SQLiteとか Oracleとか使える人がいないからデータベースの管理ができないのよね。(CSVをパースしたりでもいいんだけどさ…)


Ubuntu Server 16.04 LTS に Zabbix 3.0 をインストールする

$
0
0

CentOS 7 にインストールするのは終わったので、今度は Ubuntuに入れてみる。公式のドキュメント通りにやればいいのだけど、ちょっと手順変更してやってみる。

GPG 鍵の登録。

$ curl -s https://repo.zabbix.com/zabbix-official-repo.key | sudo apt-key add -

リポジトリの登録。

$ sudo add-apt-repository 'deb https://repo.zabbix.com/https://repo.zabbix.com/zabbix/3.0/ubuntu/ xenial main'

パッケージリストの更新。

$ sudo apt-get update

Zabbix のインストール。

$ sudo apt-get install zabbix-{release,agent,server-mysql,frontend-php} --install-suggests --install-recommends

MySQLMariaDB)の設定。仮想マシンなのでとりあえず root のパスワードは放置。

$ sudo mysql -uroot
> create database zabbix character set utf8 collate utf8_bin;
> grant all privileges on zabbix.* to zabbix@localhost identified by 'zabbix';
> quit;

テンプレートを使ってテーブルのセットアップ。

$ zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -uzabbix -p zabbix

設定をバックアップして編集。

$ sudo gzip -k /etc/zabbix/zabbix_server.conf
$ sudo vim /etc/zabbix/zabbix_server.conf

DBPasswordのとこだけだった。

$ diff -u <(zcat /etc/zabbix/zabbix_server.conf.gz) /etc/zabbix/zabbix_server.conf
--- /dev/fd/63  2017-06-27 00:56:55.808000984 +0900+++ /etc/zabbix/zabbix_server.conf      2017-06-27 00:55:06.753552066 +0900@@ -112,7 +112,7 @@
 #
 # Mandatory: no
 # Default:
-# DBPassword=+DBPassword=zabbix
 
 ### Option: DBSocket
 #      Path to MySQL socket.
$ sudo systemctl start zabbix-server
$ ^start^status
sudo systemctl status zabbix-server
● zabbix-server.service - Zabbix Server
   Loaded: loaded (/lib/systemd/system/zabbix-server.service; disabled; vendor preset: enabled)
   Active: active (running) since Tue 2017-06-27 00:55:14 JST; 7s ago
  Process: 1848 ExecStart=/usr/sbin/zabbix_server -c $CONFFILE (code=exited, status=0/SUCCESS)
 Main PID: 1865 (zabbix_server)                                                                                                                     
    Tasks: 27                                                                                                                                       
   Memory: 28.7M                                                                                                                                    
      CPU: 152ms                                                                                                                                    
   CGroup: /system.slice/zabbix-server.service
           ├─1865 /usr/sbin/zabbix_server -c /etc/zabbix/zabbix_server.conf
 :
 :
 :

自動起動

$ sudo systemctl enable zabbix-server

これでブラウザから http://${IP_ADDRESS}/zabbixにアクセスする。

f:id:mattintosh4:20170627010257p:plain

わーい。

足りないものがあったので追加設定。

$ sudo gzip -k /etc/zabbix/apache.conf
$ sudo vim /etc/zabbix/apache.conf
$ diff -u <(zcat /etc/zabbix/apache.conf.gz) /etc/zabbix/apache.conf
--- /dev/fd/63  2017-06-27 01:12:46.346248048 +0900+++ /etc/zabbix/apache.conf     2017-06-27 01:05:10.285505239 +0900@@ -25,7 +25,7 @@
         php_value upload_max_filesize 2M
         php_value max_input_time 300
         php_value always_populate_raw_post_data -1
-        # php_value date.timezone Europe/Riga+        php_value date.timezone Asia/Tokyo</IfModule>
 </Directory>
$ sudo apt-get install php7.0-{bcmath,mbstring,xml}
$ sudo systemctl restart apache2

オッケー。

f:id:mattintosh4:20170627011433p:plain

f:id:mattintosh4:20170627011632p:plain

CentOS 7 より断然楽。メモリも少なめでよい。

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            991         222         349          16         420         583
Swap:          1906           0        1906

あとはコンテナ化したいなー。

あと、ja_JP.UTF-8を有効にしてなかったので日本語が選択できなかった。

$ sudo vim /etc/locale.gen
$ sudo systemctl restart apache2

Raspberry Pi と Bluetooth 経由でシリアル通信する

$
0
0

前回は USB シリアル変換アダプタによる通信だったので今回は Bluetoothで。

メインの Ubuntuから Raspberry PiBluetoothで接続してシェルで操作できるようにするまで。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 17.04
Release:        17.04
Codename:       zesty
pi@raspberrypi:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Raspbian
Description:    Raspbian GNU/Linux 8.0 (jessie)
Release:        8.0
Codename:       jessie

とりあえず bluetoothctlでのペアリングが終わってるものとする。

まず、Bluetoothでシリアル通信を行うには bluetoothd-Cオプション付きで起動しなければならない。-Cオプションが無い場合、sdptoolが使えない。

サービスとして起動している bluetoothdを一旦止める。

pi@raspberrypi:~$ sudo systemctl stop bluetooth

bluetoothdを手動で起動。アダプタが落ちていることがあるので立ち上げ直しておく。

pi@raspberrypi:~$ sudo bluetoothd -C
pi@raspberrypi:~$ sudo hciconfig hci0 up

この時点ではまだシリアル通信ができない。

pi@raspberrypi:~$ sudo sdptool browse local | grep -i serial

sdptoolで SPP を追加する。add --channel={n}で任意のチャンネルも指定できる。

pi@raspberrypi:~$ sudo sdptool add SP
pi@raspberrypi:~$ sudo sdptool browse local | grep -i serial
Service Name: Serial Port
  "Serial Port" (0x1101)
  "Serial Port" (0x1101)

/dev/rfcomm0に端末を割り当てて待機状態にする。rfcommコマンドの使い方がまだ掴めていない。gettyagettyへのリンク。

書式とオプションは以下の通り。

RFCOMM configuration utility ver 5.43
Usage:
        rfcomm [options] <command> <dev>

Options:
        -i, --device [hciX|bdaddr]     Local HCI device or BD Address
        -h, --help                     Display help
        -r, --raw                      Switch TTY into raw mode
        -A, --auth                     Enable authentication
        -E, --encrypt                  Enable encryption
        -S, --secure                   Secure connection
        -M, --master                   Become the master of a piconet
        -L, --linger [seconds]         Set linger timeout
        -a                             Show all devices (default)

Commands:
        bind     <dev> <bdaddr> [channel]       Bind device
        release  <dev>                          Release device
        show     <dev>                          Show device
        connect  <dev> <bdaddr> [channel]       Connect device
        listen   <dev> [channel [cmd]]          Listen
        watch    <dev> [channel [cmd]]          Watch

普通にログインさせる場合。

pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty rfcomm0 115200 linux

ユーザ piでオートログインするさせる場合。

pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty rfcomm0 115200 linux -a pi

認証無しでルートログインさせる場合。

pi@raspberrypi:~$ sudo rfcomm watch 0 1 agetty -n -l /bin/bash rfcomm0 115200 linux

watchではなく listenもあるが、こっちは接続を切るとサーバ側の rfcommも終了する。

agettyのオプションがよくわからんのだが、ログイン後に下記のエラーが表示される。apt-get updateなんかをやると躓く。

-bash: cannot set terminal process group (1825): Inappropriate ioctl for device
-bash: no job control in this shell

接続元からは screenコマンドなどで接続しにいくので rfcomm connectではなく rfcomm bindしておく。

■書式

bind <dev> <bdaddr> [channel]

チャンネルは指定しなくても勝手に見つけてくれる。

$ sudo rfcomm bind 0 01:23:45:67:89:AB
$ rfcomm
rfcomm0: 01:23:45:67:89:AB channel 1 clean

これで接続元の /dev/rfcomm0を使って接続する準備ができた。

screenコマンドで rfcomm bindしてある /dev/rfcomm0に接続する。

$ screen /dev/rfcomm0 115200
Raspbian GNU/Linux 8 raspberrypi rfcomm0

raspberrypi login: 

別の端末で watchなんかで状態のチェックをしておくといいかもしれない。

$ watch rfcomm -a
rfcomm0: B8:27:EB:0D:F6:C4 channel 1 connected [tty-attached]

無事 Raspberry Piに接続できたが、接続する度に最初に AT AT ???みたいな ATコマンドを何か送ってるっぽいのだが何だこれ?

USB シリアル変換アダプタで接続しているときは出ないので多分 rfcomm関係だが ATというワードで探すのは辛い…。なんとか見つけた「Disable AT command on rfcomm connect」に書いてあった。

stackoverflow.com

ModemManager よ、またお前か…。

$ sudo systemctl stop ModemManager
$ sudo systemctl disable ModemManager

コンソールのサイズが小さいのは sttyで調整。tmuxを使っている場合は一回 detachしてから。

$ stty rows 44 cols 148
$ tmux

とりあえずプロセスグループが設定できない問題以外はなんとかなったので /lib/systemd/system/bluetooth.serviceを変更して起動時に Bluetoothシリアル通信ができるようにしておく。

pi@raspberrypi:~$ diff -u <(zcat /lib/systemd/system/bluetooth.service.gz) /lib/systemd/system/bluetooth.service
--- /dev/fd/63  2017-07-02 14:53:53.958932366 +0900+++ /lib/systemd/system/bluetooth.service       2017-07-02 13:35:31.721916663 +0900@@ -5,7 +5,8 @@
 [Service]
 Type=dbus
 BusName=org.bluez
-ExecStart=/usr/lib/bluetooth/bluetoothd+ExecStart=/usr/lib/bluetooth/bluetoothd -C+ExecStartPost=/usr/bin/sdptool add SP
 NotifyAccess=main
 #WatchdogSec=10
 #Restart=on-failure
pi@raspberrypi:~$ sudo systemctl daemon-reload
pi@raspberrypi:~$ sudo systemctl restart bluetooth

/etc/systemd/system/rfcomm.serviceを作成。

[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service
 
[Service]
ExecStart=/usr/bin/rfcomm watch 0 1 /sbin/agetty rfcomm0 115200 linux
 
[Install]
WantedBy=multi-user.target
pi@raspberrypi:~$ sudo systemctl daemon-reload
pi@raspberrypi:~$ sudo systemctl start rfcomm
pi@raspberrypi:~$ sudo systemctl enable rfcomm

プロセスグループが設定できない問題はよくわからんが、とりあえず Raspberry Piにログインしたあとに tmux起動すればいいっぽいので今日はここまで。(ctrl+a と ctrl+b が…)

Zabbix Server と Zabbix Agent の連携

$
0
0

Raspberry Piに Zabbix Agent をインストールして先日構築した Zabbix Server にデータを収集してもらう。

zabbix-agentパッケージをインストール。

$ sudo apt-get install zabbix-agent

/etc/zabbix/zabbix_agentd.confを編集。バックアップは任意でどうぞ。

$ sudo gzip -k /etc/zabbix/zabbix_agentd.conf
$ sudo -e /etc/zabbix/zabbix_agentd.conf

とりあえず簡単に許可するサーバのみ追加。

Server=127.0.0.1
$ diff -u <(zcat /etc/zabbix/zabbix_agentd.conf.gz) /etc/zabbix/zabbix_agentd.conf
--- /dev/fd/63  2017-07-04 23:02:05.893855427 +0900+++ /etc/zabbix/zabbix_agentd.conf      2017-07-04 23:01:40.664122452 +0900@@ -82,7 +82,7 @@
 # Default:
 # Server=
 
-Server=127.0.0.1+Server=127.0.0.1,10.16.0.152
 
 ### Option: ListenPort
 #      Agent will listen on this port for connections from the server.

Zabbix Agent の起動。

$ systemctl start zabbix-agent
$ ^start^status
sudo systemctl status zabbix-agent
● zabbix-agent.service - LSB: Start zabbix-agent daemon
   Loaded: loaded (/etc/init.d/zabbix-agent)
   Active: active (running) since Tue 2017-07-04 23:09:39 JST; 12s ago
  Process: 23551 ExecStop=/etc/init.d/zabbix-agent stop (code=exited, status=0/SUCCESS)
  Process: 23878 ExecStart=/etc/init.d/zabbix-agent start (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/zabbix-agent.service
           ├─23885 /usr/sbin/zabbix_agentd
           ├─23886 /usr/sbin/zabbix_agentd: collector [idle 1 sec]
           ├─23887 /usr/sbin/zabbix_agentd: listener #1 [waiting for connection]
           ├─23888 /usr/sbin/zabbix_agentd: listener #2 [waiting for connection]
           ├─23889 /usr/sbin/zabbix_agentd: listener #3 [waiting for connection]
           └─23890 /usr/sbin/zabbix_agentd: active checks #1 [idle 1 sec]

Jul 04 23:09:39 raspberrypi zabbix-agent[23878]: zabbix_agentd starting...done.
Jul 04 23:09:39 raspberrypi systemd[1]: Started LSB: Start zabbix-agent daemon.
Jul 04 23:09:46 raspberrypi systemd[1]: Started LSB: Start zabbix-agent daemon.

テストしようと思ったけど zabbix_getがねぇ…。わざわざ zabbix-server-*をインストールしなきゃいけないんだろうか…。

Zabbix Server インストール済みのマシンから zabbix_getを叩く。エラーが出なければOK。

$ zabbix_get -s 192.168.1.99 -k system.hostname
raspberrypi

※公式リポジトリには zabbix-agent単体のパッケージが存在する。

エージェントの登録

[設定]>[ホスト]から[ホストの作成]をクリック。

Zabbix Agent を入れたマシンの情報を追加する。

あとはダッシュボードなどでデータが取得できているか確認しましょう。

Raspberry Pi の CPU 温度を Zabbix Server に送る

$
0
0

Zabbix Agent で Raspberry Piの CPU 使用率やネットワーク使用率は Zabbix Server と連携できるようになったけど、CPU の温度までは連携してくれない。

そこで Zabbix Sender を使って Raspberry Piから Zabbix Server に能動的にデータを送る。

Raspberry Piの CPU 温度は vcgencmd measure_tempか、/sys/class/thermal/thermal_zone0/tempで調べることができる。

$ vcgencmd measure_temp; cat /sys/class/thermal/thermal_zone0/temp
temp=52.1'C
52615

これを例えば 52.615として Zabbix に送るには多少整形が必要になる。シェルによっては浮動小数点数を扱うことができるけど、出来ないという想定で、bcawkを使う方法なんかを書いておく。(文字列として扱うのであればなんとでもできるけど)

bcは追加インストールが必要なことがあるので awkの例。Zabbix Sender は通信がうまく出来たかどうか返してくれるけどとりあえず今日はやらない。

#!/bin/bashset-e#set -x#set -uZABBIX_SERVER=10.0.0.254
KEY=sys__class__thermal__thermal_zone0__temp

temp=$(awk 'BEGIN { getline < "/sys/class/thermal/thermal_zone0/temp"; print $0/1000 }')test-n"${temp}"

zabbix_sender -z"${ZABBIX_SERVER}"-s"${HOSTNAME}"-k"${KEY}"-o"${temp}"

こっちは bc。キーは別に被らなければ長くなくてもよい。

#!/bin/bashset-e#set -x#set -uZABBIX_SERVER=10.0.0.254
KEY=sys__class__thermal__thermal_zone0__temp

temp=$(echo"scale=3; $(cat /sys/class/thermal/thermal_zone0/temp)/1000"| bc -l)test-n"${temp}"

zabbix_sender -z"${ZABBIX_SERVER}"-s"${HOSTNAME}"-k"${KEY}"-o"${temp}"

Zabbix 側でホストのアイテムに「Zabbix トラッパー」を追加しておく。

f:id:mattintosh4:20170706233320p:plain

Zabbix Server との連携確認用に watchで実行させておく。しばらく実行させたままにするなら TMUX などで実行しておけば端末を落としても大丈夫。うまく連携できることを確認したら cron に任せる。

$ watch -pn 10 ./zabbix_sender.sh

Zabbix の「計算アイテム」を使う

Zabbix には「計算アイテム」と呼ばれるものがある。名前の通り、他の値を計算するアイテム。これを使えば 52615というような温度も Zabbix 側で計算して 52.62のようにすることができるのでわざわざシェルで整形する必要がない。

#!/bin/bashset-e#set -x#set -uZABBIX_SERVER=10.0.0.254
KEY=sys__class__thermal__thermal_zone0__temp

temp=$(< /sys/class/thermal/thermal_zone0/temp)test-n"${temp}"

zabbix_sender -z"${ZABBIX_SERVER}"-s"${HOSTNAME}"-k"${KEY}"-o"${temp}"

新しく計算アイテムを作る。

f:id:mattintosh4:20170706233330p:plain

計算式はこんな感じ。

last(sys__class__thermal__thermal_zone0__temp) / 1000

正しくアイテムが登録されれば計算した値を出してくれる。

f:id:mattintosh4:20170706233339p:plain

今回作った計算アイテムを使えば 1/1000 の値でグラフが作れる。

Zabbix で SNMP Agent と通信する

$
0
0

Ubuntu 16.04 LTS で SNMP Agent を構築していく。

snmpsnmpdsnmp-mibs-downloaderをインストールする。

$ sudo apt-get install snmp snmpd snmp-mibs-downloader

/etc/snmp/snmp.confmibs :行をコメントアウトする。(+ALLでもいい?)

$ diff -u <(zcat /etc/snmp/snmp.conf.gz) /etc/snmp/snmp.conf
--- /dev/fd/63  2017-07-07 16:04:36.230571510 +0000+++ /etc/snmp/snmp.conf 2017-07-07 16:04:15.106009951 +0000@@ -1,4 +1,4 @@
 # As the snmp packages come without MIB files due to license reasons, loading
 # of MIBs is disabled by default. If you added the MIBs you can reenable
 # loading them by commenting out the following line.
-mibs :+#mibs :

/etc/snmp/snmpd.confagentAddress行と rocommunity public行を編集する。本来は IP アドレスを制限すべきだが、LXC 内のネットワークを使用するので無制限とした。

$ diff -u <(zcat /etc/snmp/snmpd.conf.gz) /etc/snmp/snmpd.conf
--- /dev/fd/63  2017-07-07 16:07:20.342934468 +0000+++ /etc/snmp/snmpd.conf        2017-07-07 16:06:45.642011890 +0000@@ -12,9 +12,9 @@
 #
 
 #  Listen for connections from the local system only
- agentAddress  udp:127.0.0.1:161+#agentAddress  udp:127.0.0.1:161
 #  Listen for connections on all interfaces (both IPv4 *and* IPv6)
-#agentAddress udp:161,udp6:[::1]:161+ agentAddress udp:161,udp6:[::1]:161@@ -47,6 +47,7 @@
 
                                                  #  Full access from the local host
 #rocommunity public  localhost
+ rocommunity public  10.0.3.0/24
                                                  #  Default access to basic system info
  rocommunity public  default    -V systemonly
                                                  #  rocommunity6 is for IPv6

snmpdを再起動する。

$ sudo systemctl restart snmpd

Zabbix Server から snmpwalkを使って接続をテストしてみる。下記のような表示が返ってくればOK。

zabbix-server$ snmpwak -v2c -c public 10.0.3.98
SNMPv2-MIB::sysDescr.0 = STRING: Linux snmp_agent_2 4.4.0-83-generic #106-Ubuntu SMP Mon Jun 26 17:54:43 UTC 2017 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (115105) 0:19:11.05
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>
SNMPv2-MIB::sysName.0 = STRING: snmp_agent_2
SNMPv2-MIB::sysLocation.0 = STRING: Sitting on the Dock of the Bay
SNMPv2-MIB::sysServices.0 = INTEGER: 72
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (0) 0:00:00.00
SNMPv2-MIB::sysORID.1 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.2 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
:
:

Zabbix でホストを登録する。今回は SNMPなので「SNMPインターフェイス」で作成する。

f:id:mattintosh4:20170708011456p:plain

テンプレートのタブで「Template SNMP OS Linux」を追加する。

f:id:mattintosh4:20170708011506p:plain

データが「最新データ」に反映されていたらOK。

Zabbix Sender 無しで Zabbix Server にデータを送る

$
0
0

Zabbix APIについて色々調べてたけど…

「あれ?これってアイテムのデータ追加できなくない?」

という問題にぶち当たった。Slack みたいにデータを追加できるものかと思ったのだが、どうも "request": "sender data"を受け付けない。Zabbix のドキュメントルートを探してみても sender dataという文字列は見当たらない。ということは Zabbix Sender が使えないデバイスはデータの追加が出来ないのでは?

いやいやでも Pythonのモジュールとかあるじゃん。

ってことで Python系の Zabbix モジュールを色々探して読んでみた。

github.com

このコードを見て、サーバーに送る部分で何をやってるかというと、

  1. Zabbix サーバーの 10051 ポートに接続する
  2. JSONぶん投げる

以上。マジでこれしかやってないっぽい。

ってことは ncコマンドで接続して JSON投げるだけで出来るんじゃね?

$ nc 10.0.3.3 10051 <<!
{
    "request": "sender data"
,   "data": [
        {
            "host": "raspberrypi"
        ,   "key": "room_temperature"
        ,   "value": "0"
        }
    ]
,   "clock": `date +%s`
}
!
ZBXDZ{"response":"success","info":"processed: 1; failed: 0; total: 1; seconds spent: 0.000074"}

Zabbix Sender 要らないやんけええええええええ

Zabbix Sender とは一体…。

つまり Zabbix Sender さんのお仕事は -s-k-oオプションで受けった引数から JSONを生成して -zのサーバに投げてるだけということだ。これなら Zabbix Sender をインストールできないデバイスでも使えそう。

FlashAir の Luaでも使おうと思ってるので Luaでソケット通信を簡単に書いてみる。Luaは全然やったことがないから作法とかがよくわからない。

#!/usr/bin/lualocal socket = require("socket")
local client = assert(socket.connect("10.0.3.3", 10051))
local json = [[{"request": "sender data",   "data": [        {"host": "alarmpi"        ,   "key": "room_temperature"        ,   "value": "0"        }    ]}]]
client:send(json)
socket.sleep(0.5)
local line = client:receive()
print(line)
client:close()

一応 Zabbix にデータは入るんだけど、client:receive()nilで返ってきちゃうなぁ…。そもそも FlashAir で socketが使えるのかどうかわからんな…。HTTP リクエストはできるから REST かなぁ。

$ lua zabbix_sender.lua
nil

Docker で Zabbix サーバーを建てる

$
0
0

Docker 覚えよーってことで Zabbix がすぐに使えるコンテナを作ることにした。

いまこんな状態。

  • LXC は使ってるけど Docker はほとんど使ってない
  • Mastodonインスタンスを作るときに Docker を触った
  • 知ってるよ!クジラのアレでしょアレ!!

Ubuntuに Docker を入れる

とりあえず Docker を使えるように。dockerというパッケージはすでに Macライクなドックを実現するためのパッケージで使われているので Docker は docker.ioというパッケージ。

$ sudo apt-get install docker.io

dockerグループに所属していないと毎回 sudoすることになるので usermodgpasswdで自分を dockerグループに追加しておく。

$ sudo usermod -aG docker $UID

ここで一旦ログアウト。

イメージを入手する

docker imagesでローカルのイメージを見てみる。当然まだ何もない。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

docker searchcentosにマッチするものを探してみる。デフォルトの表示件数は25件まで。

$ docker search centos
NAME                           DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                         The official build of CentOS.                   3475      [OK]
jdeathe/centos-ssh             CentOS-6 6.9 x86_64 / CentOS-7 7.3.1611 x8...   77                   [OK]
tutum/centos                   Simple CentOS docker image with SSH access      32
kinogmt/centos-ssh             CentOS with SSH                                 15                   [OK]
centos/postgresql-94-centos7   PostgreSQL 9.4 SQL database server              10
centos/mysql-57-centos7        MySQL 5.7 SQL database server                   8
centos/php-56-centos7          PHP 5.6 platform for building and running ...   6
centos/python-35-centos7       Python 3.5 platform for building and runni...   4
centos/mongodb-26-centos7      MongoDB 2.6 NoSQL database server               4
 :

オフィシャルなリポジトリだけに絞り込みたいときは -f|--filterオプションで is-official=trueを追加する。

$ docker search -f is-official=true centos
NAME      DESCRIPTION                     STARS     OFFICIAL   AUTOMATED
centos    The official build of CentOS.   3475      [OK]

STARS が 3以上のものに絞り込みたい場合は stars=3とする。

$ docker search -f stars=3 centos
NAME                           DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                         The official build of CentOS.                   3475      [OK]
jdeathe/centos-ssh             CentOS-6 6.9 x86_64 / CentOS-7 7.3.1611 x8...   77                   [OK]
tutum/centos                   Simple CentOS docker image with SSH access      32
kinogmt/centos-ssh             CentOS with SSH                                 15                   [OK]
centos/postgresql-94-centos7   PostgreSQL 9.4 SQL database server              10
centos/mysql-57-centos7        MySQL 5.7 SQL database server                   8
centos/php-56-centos7          PHP 5.6 platform for building and running ...   6
centos/mysql-56-centos7        MySQL 5.6 SQL database server                   4
centos/mongodb-26-centos7      MongoDB 2.6 NoSQL database server               4
centos/python-35-centos7       Python 3.5 platform for building and runni...   4
centos/redis                   Redis built for CentOS                          3                    [OK]

せっかくなので ubuntuも検索してみる。CentOSより星の数が多い。

$ docker search -f stars=3 ubuntu
NAME                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
ubuntu                   Ubuntu is a Debian-based Linux operating s...   6269      [OK]
rastasheep/ubuntu-sshd   Dockerized SSH service, built on top of of...   91                   [OK]
ubuntu-upstart           Upstart is an event-based replacement for ...   74        [OK]
neurodebian              NeuroDebian provides neuroscience research...   37        [OK]
ubuntu-debootstrap       debootstrap --variant=minbase --components...   30        [OK]
32bit/ubuntu             Ubuntu for i386 (32bit)                         30
armhf/ubuntu             Ubuntu is a Debian-based Linux operating s...   27
nuagebec/ubuntu          Simple always updated Ubuntu docker images...   22                   [OK]
tutum/ubuntu             Simple Ubuntu docker images with SSH access     18
ppc64le/ubuntu           Ubuntu is a Debian-based Linux operating s...   10
sameersbn/ubuntu                                                         9                    [OK]
aarch64/ubuntu           Ubuntu is a Debian-based Linux operating s...   9
nimmis/ubuntu            This is a docker images different LTS vers...   7                    [OK]
i386/ubuntu              Ubuntu is a Debian-based Linux operating s...   7
libmesos/ubuntu                                                          3
darksheer/ubuntu         Base Ubuntu Image -- Updated hourly             3                    [OK]

よくわからない場合は https://hub.docker.com/explore/を見に行けばいいんじゃないかな。

とりあえず CentOS入れましょう。NAME[:TAG]書式でタグが指定できます。タグの一覧は https://hub.docker.com/r/library/centos/tags/とかで。

$ docker pull centos:latest

端末上でタグの一覧が見たければ https://registry.hub.docker.com/v1/repositories/${name}/tagsの結果を jqでパース。

$ curl -s 'https://registry.hub.docker.com/v1/repositories/centos/tags' | jq -r .[].name
latest
5
5.11
6
6.6
6.7
6.8
6.9
7
7.0.1406
7.1.1503
7.2.1511
7.3.1611
centos5
centos5.11
centos6
centos6.6
centos6.7
centos6.8
centos6.9
centos7
centos7.0.1406
centos7.1.1503
centos7.2.1511
centos7.3.1611

docker imagesでイメージを見てみます。名前やタグを指定すれば絞り込みができます。

$ docker images centos:latest
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
centos              latest              36540f359ca3        10 days ago         192.5 MB

コンテナを作る

docker runでコンテナを作ります。

  • -i|--interactive:接続されていなくても標準入力を開いたままにします
  • -t|--tty:疑似端末を割り当てます
  • --rm:コンテナを自動的に削除します
$ docker run -ti centos
[root@dd4b64cdb392 /]# cat /etc/system-release
CentOS Linux release 7.3.1611 (Core)
[root@dd4b64cdb392 /]#

別の端末で docker psを使って稼働中のコンテナを確認してみる。

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
dd4b64cdb392        centos:latest       "/bin/bash"         38 seconds ago      Up 35 seconds                           hungry_blackwell

exitや Ctrl+d でコンテナを終了させる。デタッチだけであれば Ctrl+p, Ctrl+q。

今度は -d|--detachで起動。

$ docker run -dti centos
762ea423472ea002b3c28bb88841bc7a66ce5f3b2b7257404ecb022d1cc4d562
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
762ea423472e        centos              "/bin/bash"         7 seconds ago       Up 4 seconds                            modest_bose

docker execでコマンドを与えればコンテナ内で実行してくれる。

$ docker exec modest_bose cat /etc/system-release
CentOS Linux release 7.3.1611 (Core)

アタッチ。

$ docker attach modest_bose
[root@762ea423472e /]#

別のシェルを起動してそっちでアタッチ。

$ docker exec -ti modest_bose /bin/bash
[root@762ea423472e /]#

デタッチしてまたアタッチの流れ。

$ docker run -ti centos
[root@f48847bbf999 /]# ここで Ctrl+p, Ctrl+q を押すとデタッチされる
$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
f48847bbf999        centos              "/bin/bash"         10 seconds ago      Up 6 seconds                            agitated_morse
$ docker attach agitated_morse
[root@f48847bbf999 /]#

コンテナ名は毎回変わるので固定したい場合は docker run --name my-containerのように --nameオプションでコンテナ名を指定すればよい。

コンテナが量産されるんだけど…

必要なものがあればコミットしときましょう。

$ docker commit コンテナ名 イメージ名

全部要らないならまとめて消せばいいんじゃないかな。

$ docker rm `docker ps -qa`

Zabbix サーバ用の Dockerfile を書くよ

Docker に簡単に慣れたところで Zabbix サーバを構築するための Dockerfile を書いてみることにした。

が、よくよく調べてみると docker buildでは --privilegedオプションが使えないので systemdが動かないらしい。まぁなんとかなるだろ。

Dockerfile を作っている途中、何故か yum install zabbix-server-mysqlをしても /usr/share/doc/zabbix-server-mysql-3.0.*が作成されず、SQLのテンプレートがコピーされない問題があった。yum install --downloadonlyyumdownloader zabbix-server-mysqlRPMを落としてきて RPMでインストールするとインストールされる…謎。

とりあえず今のところはローカル再インストールで済ませてる。

# yumdownloader zabbix-server-mysql
# rpm -ivh --replacepkgs zabbix-server-mysql-3.0.*.rpm
# rm -f zabbix-server-mysql-3.0.*.rpm

最初から入れるなら依存関係先に入れないと RPMが怒る。

# yum install -y http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-release-3.0-1.el7.noarch.rpm
# yum install -y `yum deplist zabbix-server-mysql | awk '/provider:/{ print $2 }' | grep -v zabbix-server-mysql | sort -u`
# yumdownloader zabbix-server-mysql
# rpm -ivh zabbix-server-mysql-3.0.*.rpm
# rm -f zabbix-server-mysql-3.0.*.rpm

それか RPMをぶちまけるか。

# rpm2cpio zabbix-server-mysql-3.0.* | cpio -idmv

mysqld_safeはバックグラウンドで動かせないし、かなり無理矢理だけどとりあえずモノは出来た。Dockerfile は Gist で作業中。

$ git clone https://gist.github.com/6c7b79b48c11eec3181fc252dd5afb5a.git docker-test
$ cd docker-test
$ docker pull centos:centos7
$ docker build .
$ docker run -ti --name zabbix -p 80:80 -p 10051:10051 ${IMAGE_ID}

systemd で動くやつ作ろうよ

systemctl start zabbix-serverしたいじゃん?

centos:centos7イメージからベースになる tempコンテナを作って --privileged/sbin/initを実行させておく。

$ docker run -dti --privileged --name temp centos:centos7 /sbin/init

tempコンテナで /bin/bashを起動。

$ docker exec -ti temp /bin/bash

コンテナの中にスクリプトをぶち込む。

localedef -i ja_JP -f UTF-8 /usr/lib/locale/ja_JP.UTF-8
yum install -y http://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-release-3.0-1.el7.noarch.rpm
yum install -y zabbix-server-mysql zabbix-web-mysql zabbix-web-japanese zabbix-agent mariadb-server
yumdownloader zabbix-server-mysql
rpm -ivh --replacepkgs zabbix-server-mysql-3.0.*.rpm
rm -f zabbix-server-mysql-3.0.*.rpm
systemctl start mariadb
systemctl enable mariadb
echo 'create database zabbix character set utf8 collate utf8_bin;' | mysql -uroot
echo 'grant all on zabbix.* to zabbix@localhost;' | mysql -uroot
zcat /usr/share/doc/zabbix-server-mysql-3.0.*/create.sql.gz | mysql -uzabbix zabbix
sed -i'' '/# php_value date\.timezone/{s|# ||;s|Europe/Riga|Asia/Tokyo|}' /etc/httpd/conf.d/zabbix.conf
systemctl start httpd
systemctl enable httpd
systemctl start zabbix-server
systemctl enable zabbix-server
systemctl start zabbix-agent
systemctl enable zabbix-agent
exit

tempコンテナから zabbix3.0イメージを作成。サイズは約600MB。

$ docker commit temp zabbix3.0
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
zabbix3.0           latest              a3c42c570541        21 minutes ago      602.8 MB

tempコンテナを停止して削除。

$ docker stop temp
$ docker rm temp

runするときは --previlegedを忘れずに。

$ docker run --privileged -d -p80:80 zabbix3.0 /sbin/init

これでいつでも Zabbix に会えるね!!!(特に嬉しくはない)

f:id:mattintosh4:20170716214352p:plain

会社内での説明用に撮ったもの。


Docker で Ubuntu Xenial な Zabbix Server を立てる

$
0
0

CentOS版やったし、Ubuntu版もやるよねってことで。

mattintosh.hatenablog.com

CentOSよりは楽な印象。

ubuntu:xenialでコンテナ作る。

docker run -ti--name hogehoge ubuntu:xenial /bin/bash

こっからコンテナ内のシェルで実行していく。

apt-get update
apt-get install -y curl language-pack-ja
curl -O http://repo.zabbix.com/zabbix/3.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_3.0-2+xenial_all.deb
dpkg -i zabbix-release_3.0-2+xenial_all.deb
rm zabbix-release_3.0-2+xenial_all.deb
apt-get update
apt-get install -y--install-recommends zabbix-server-mysql zabbix-agent zabbix-frontend-php php7.0-bcmath php7.0-mbstring php7.0-xml

なんとびっくり viすら入ってないので sedで。

sed-i'''/php_value date.timezone/{s|# ||;s|Europe/Riga|Asia/Tokyo|}' /etc/zabbix/apache.conf

これやっとかないと「PID ファイル作れないんぢゃ!!!」って怒られる。

install -d-o zabbix -g zabbix /var/run/zabbix

mysqld_safeはバックグラウンドで動かさないと返ってこれなくなる。(別の端末で docker exec /bin/bashとかしなきゃいけない)

mysqld_safe &
mysql -uroot
create database zabbix characterset utf8 collate utf8_bin;
grantallon zabbix.* to zabbix@localhost
quit

テンプレートからテーブル作る。これが一番時間かかる。

zcat /usr/share/doc/zabbix-server-mysql/create.sql.gz | mysql -uzabbix zabbix

一回デタッチしてコミット。すごく…大きいです。

$ docker commit hogehoge ubuntu:zabbix3.0
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              zabbix3.0           f3f706f706f2        26 seconds ago      690.2 MB
centos              zabbix3.0           22e1f36e12f7        12 hours ago        603.5 MB

各種サーバーを起動してみる。

zabbix_server
zabbix_agentd
apache2ctl start

問題なさげ。

f:id:mattintosh4:20170718022808p:plain

使い捨てで起動する場合。

docker run --rm-ti ubuntu:zabbix3.0 sh -c'mysqld_safe & zabbix_server && zabbix_agentd && . /etc/apache2/envvars && apache2 -DFOREGROUND'

全作業をスクリプト化。

(まだ作ってないけど)Dockerfileでやるときは Apacheをフォアグランドに持ってきて動かさないとだめかも。Zabbix Server と Zabbix Agent には --foregroundオプションがあるけど root で実行できない。

CMD sh -c '. /etc/apache2/envvars && apache2 -DFOREGROUND'

CentOS 6/7 CUI Installation

$
0
0

GUIインストールが嫌いなので。VirtualBoxで試してみたけど10分かからずにインストール終わった。(CentOS 6 は5分もあればいける)

CentOS 7

インストーラメニューで TABキーを押す。

f:id:mattintosh4:20170718221720p:plain

ブートオプションに textを追加して ENTER

f:id:mattintosh4:20170718221740p:plain

タイムゾーンの設定

1を入力してタイムゾーンの設定へ進む。6を入力して Asiaを選択。

f:id:mattintosh4:20170718221852p:plain

一覧が表示されるので ENTERを押して進む。

f:id:mattintosh4:20170718221956p:plain

71Tokyoを選択。

f:id:mattintosh4:20170718222034p:plain

インストール先(ストレージ)の設定

4でインストール先の設定へ。

f:id:mattintosh4:20170718222103p:plain

xの付いているストレージがインストール先に指定されている状態。cを押して進む。

f:id:mattintosh4:20170718222208p:plain

xが付いているパーティショニングオプションが選択される。デフォルトは 2の “Use All Space"(すべての領域)。cを入力して進む。

f:id:mattintosh4:20170718222249p:plain

パーティションスキームを選択する。デフォルトは 2の “LVM"(Logical Volume Manager)。cを入力して進む。

f:id:mattintosh4:20170718222449p:plain

なお、この画面は TMUX で動いているので CTRL+b, nを押せば隣のシェルウィンドウへ移動することができる。fdiskpartedなど、パーティショニングに必要なものは一通り揃っているのでここで好みのパーティショニングをすることもできる。

f:id:mattintosh4:20170718224519p:plain

f:id:mattintosh4:20170718224332p:plain

ネットワークの設定

5を入力してネットワーク設定へ進む。

f:id:mattintosh4:20170718222809p:plain

1を入力してホスト名を設定する。

f:id:mattintosh4:20170718222853p:plain

ホスト名を入力する。

f:id:mattintosh4:20170719001716p:plain

2を入力してネットワークアダプタの設定へ進む。

f:id:mattintosh4:20170719001739p:plain

7を入力して自動起動を有効にする。これを忘れた場合は通常起動後に /etc/sysconfig/network-scripts/ifcfg-eth0ONBOOT=noONBOOT=yesにすればよい。

f:id:mattintosh4:20170719001802p:plain

cを入力して先へ進む。

f:id:mattintosh4:20170719001814p:plain

cを入力して先へ進む。

f:id:mattintosh4:20170719002006p:plain

ルートパスワードの設定

6を入力して進む。

f:id:mattintosh4:20170719002222p:plain

パスワードと確認用パスワードを入力する。

f:id:mattintosh4:20170718233745p:plain

脆弱なパスワードの場合、注意されるがここでは yesで無視する。

f:id:mattintosh4:20170718233813p:plain

インストー

bを入力して進む。

f:id:mattintosh4:20170718233855p:plain

インストールが開始される。

f:id:mattintosh4:20170718234013p:plain

インストールが終わったら ENTERで再起動する。

f:id:mattintosh4:20170718234052p:plain

CentOS 6

そのうち書く。

Panasonic Let's note CF-N10 のメモリ情報

$
0
0

メモリ増設予定なのでメモ。公式だと最大 8 GB っぽいが、dmidecodeで見てみると最大 16 GB だな。+ 4 GB で SSDにすりゃいいか…。

$ sudo dmidecode -t memory
# dmidecode 3.0
Getting SMBIOS data from sysfs.
SMBIOS 2.6 present.

Handle 0x000C, DMI type 16, 15 bytes
Physical Memory Array
    Location: System Board Or Motherboard
    Use: System Memory
    Error Correction Type: None
    Maximum Capacity: 16 GB
    Error Information Handle: Not Provided
    Number Of Devices: 2

Handle 0x000E, DMI type 17, 28 bytes
Memory Device
    Array Handle: 0x000C
    Error Information Handle: Not Provided
    Total Width: 64 bits
    Data Width: 64 bits
    Size: 4096 MB
    Form Factor: SODIMM
    Set: None
    Locator: DIMM 1
    Bank Locator: DIMM 1
    Type: DDR3
    Type Detail: Synchronous
    Speed: 1067 MHz
    Manufacturer: Not Specified
    Serial Number: 61B63AAE
    Asset Tag: Not Specified
    Part Number: Not Specified
    Rank: Unknown

Handle 0x0010, DMI type 17, 28 bytes
Memory Device
    Array Handle: 0x000C
    Error Information Handle: Not Provided
    Total Width: Unknown
    Data Width: Unknown
    Size: No Module Installed
    Form Factor: SODIMM
    Set: None
    Locator: DIMM 2
    Bank Locator: DIMM 2
    Type: Unknown
    Type Detail: Synchronous
    Speed: Unknown
    Manufacturer: Not Specified
    Serial Number: Not Specified
    Asset Tag: Not Specified
    Part Number: Not Specified
    Rank: Unknown

Handle 0x0012, DMI type 16, 15 bytes
Physical Memory Array
    Location: System Board Or Motherboard
    Use: Flash Memory
    Error Correction Type: None
    Maximum Capacity: 8 MB
    Error Information Handle: Not Provided
    Number Of Devices: 1

Handle 0x0014, DMI type 17, 28 bytes
Memory Device
    Array Handle: 0x0012
    Error Information Handle: Not Provided
    Total Width: 8 bits
    Data Width: 8 bits
    Size: 8192 kB
    Form Factor: TSOP
    Set: None
    Locator: Flash ROM
    Bank Locator: Flash ROM
    Type: Flash
    Type Detail: Non-Volatile
    Speed: Unknown
    Manufacturer: Not Specified
    Serial Number: Not Specified
    Asset Tag: Not Specified
    Part Number: Not Specified
    Rank: Unknown

Wine 2.18 版 EasyWine.app 他をアップしました

$
0
0

前回のアップが今年の4月16日っぽいので約半年振り。いつものとこに置いてあるよ。

matome.naver.jp

リリースの頻度が低い理由は色々とありますが、

  • 仕事が忙しい
  • Mac使ってない

が理由でしょうか。仕事が忙しいので Wine のリリースノート読む余裕もないし、テストする暇もない。というか特に使いたい Windowsアプリが無いのでテストする意欲が湧かない。

我が家で唯一の Macである MacBook Airは Late 2010 なんでもう7年目。バッテリーはまだ持つので外出の際にたまに使ってはいたけど、先日、秋葉原で i5 の中古ノートPCを買ったので完全に Linuxに移行した感じ。

つまり私はもう Macユーザーではないんだね!

「EasyWine とか Nihonshu なんてただの野良ビルドだし、Macユーザーの皆は Homebrew なり入れて自分でインストールすればいいじゃん!CrossOver 買おうよ!」

って思ったりするわけですが、上京してからは東方の音楽を聴くようになったので未だにリリースを続けているのは一部の東方ユーザーのためでもあったり。(そういやコミケ例大祭にはよく行くけど Macをデモ機で置いてるサークルがあるのかあまり気にして見てなかったなぁ)

共同開発する人でもいりゃもう少し意欲も湧くんだろうけど。

次回のリリースは来年以降の予定です。ではでは。

アズレン一覧めーかー的なもの(図鑑一覧生成スクリプト)

$
0
0

最近、アズールレーンをやってるんだけど、艦の種類が多い。(まだ日本版未実装の艦もいるっていうのだからそれはもう大変)

Wikiとか攻略サイトは見ないで進めてるんだけど、駆逐艦駆逐艦でも火力重視や対空重視など色々いるので図鑑のパラメータを一覧で見れると楽だな〜と思ったので、以前作った艦これ一覧めーかー的なもののアズールレーン版を作ってみた。

艦これ版は↓

mattintosh.hatenablog.com

駆逐とか軽巡とかのフォルダにスクショをぽぽぽーんと突っ込んでおくとぽぽぽぽーん!と↓みたいな画像が出来上がる。

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171022/20171022030417_original.jpg

中間ファイルは透過PNGなので背景のアレンジも可。

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171022/20171022025902_original.png

やってることはいつもの ImageMagickだけど、今回は枚数が多いのでパラレルで実行することで生成時間を短縮。(マシンによっては逆に遅くなるか止まる可能性あり)

入力ファイルのプロパティを処理中に拾う方法があったような気がするんだけど忘れたので関数にして解析と生成で2回実行することにした。ImageMagickは時間が経つといつも忘れる…。まだ直書きな部分があるのでそのうち直す。あと全艦並べてしまうと画像が大きくなりすぎるので前衛部隊と主力部隊で分けて出力するようにしようかな。

使用しているフォントは Stencil Cargo Army というものと Stencil WW II の2種類。いずれも 1001 Free Fonts から無料でダウンロードできる。

www.1001freefonts.com

www.1001freefonts.com

アズレン一覧めーかーの続き

$
0
0

昨日に引き続きアズールレーンネタで昨日作ったやつをちょっと改良。

mattintosh.hatenablog.com

図鑑のスクショを全部並べるとデカイのでちょっと小さくしようかなと。元の画像が大きいもんね。

f:id:mattintosh4:20171022225849p:plain

元の状態から必要な部分だけ切り出して GIMPでレイアウト調整してみる。「コメント」とかのボタンに被るのは仕方ない。

f:id:mattintosh4:20171022225824p:plain

ひとまず各パーツごとに切り出して、あとから各パーツを -compose Over -compositeで合成するようにした。

#!/bin/bash

convert -alpha on 001.png -crop 657x592+0+47+repage x001.png
convert -alpha on \'(' 001.png -crop 342x208+707+137+repage')'\'('-size 342x208 xc:none -draw'roundrectangle 0,0 341,207 5,5'')'\-compose DstIn -composite x002.png
convert -alpha on \'(' 001.png -crop 88x88+725+421+repage')'\'('-size 88x88 xc:none -draw'roundrectangle 0,0 87,87 8,8'')'\-compose DstIn -composite x003.png
convert -alpha on \'(' 001.png -crop 88x88+833+421+repage')'\'('-size 88x88 xc:none -draw'roundrectangle 0,0 87,87 8,8'')'\-compose DstIn -composite x004.png
convert -alpha on \'(' 001.png -crop 88x88+942+421+repage')'\'('-size 88x88 xc:none -draw'roundrectangle 0,0 87,87 8,8'')'\-compose DstIn -composite x005.png

convert x001.png \-gravity NorthEast \-compose over \
                x002.png -geometry+8+350-composite\
                x003.png -geometry+8+65-composite\
                x004.png -geometry+8+157-composite\
                x005.png -geometry+8+249-composite\
        x006.png

レイアウトが概ね決まったら今度は1コマンド化。よく考えたら土台になる部分(上で言うと x001.png)は切り出す必要がなく、チャートやアイコンを重ねて最後にまとめてクロップしてしまえばよいことに気づいた。

-clone 0でベースの画像を複製して重ねて複製して重ねて…の繰り返し。+clone+swapとか -swap {index},{index}とか使ってやる気だったけど -clone {index}があるんだった…。マジで ImageMagick忘れる…。

#!/bin/bash

convert "${1}" \
  '(' -clone 0 -alpha on -crop 342x208+707+137 '(' -size 342x208 xc:none -draw 'roundrectangle 0,0 341,207 5,5' ')' -compose DstIn -composite -geometry +307+397 ')' -compose Over -composite \
  '(' -clone 0 -alpha on -crop   88x88+725+421 '(' -size 88x88   xc:none -draw 'roundrectangle 0,0 [f:id:mattintosh4:20171022231147j:plain][f:id:mattintosh4:20171022231215j:plain]  87,87 8,8' ')' -compose DstIn -composite -geometry +561+112 ')' -compose Over -composite \
  '(' -clone 0 -alpha on -crop   88x88+833+421 '(' -size 88x88   xc:none -draw 'roundrectangle 0,0   87,87 8,8' ')' -compose DstIn -composite -geometry +561+204 ')' -compose Over -composite \
  '(' -clone 0 -alpha on -crop   88x88+942+421 '(' -size 88x88   xc:none -draw 'roundrectangle 0,0   87,87 8,8' ')' -compose DstIn -composite -geometry +561+296 ')' -compose Over -composite \
  -crop 657x592+0+47 +repage "${1%.*}"_.png

最後の結合もお好みで分割できるようにしたのでだいぶコンパクトになった。

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171022/20171022231601_original.jpg

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171022/20171022231547_original.jpg

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171022/20171022231540_original.jpg

あとは加賀とエンタープライズが来てくれれば…(´;ω;`)

アズレン一覧めーかーで3-4ドロップリスト

$
0
0

アズールレーンネタ3日目。

遂にうちにも加賀様がっ!!!(∩´∀`)∩ワーイ (300周以上はしたと思う…赤城は1周目で出たのに…涙)

ってことで3-4コンプしたのでドロップリストの並び順で作ってみた。ちょっとアレンジ加えてカードの角にカット入れました。コンプ報酬対象の場合はカットの部分の色変えてみたりすると面白いかも。

https://cdn-ak2.f.st-hatena.com/images/fotolife/m/mattintosh4/20171025/20171025015250_original.jpg

エンタープライズはまだ来ない。次は扶桑山城かな。

f:id:mattintosh4:20171025015059p:plain


Wacom のペンタブレット CTH-490/K1 を買った

$
0
0

昔から「ペンタブ欲しいな〜」とは思っていたもののなかなか機会がないまま十数年。資料作りとかすることがちょいちょい増えてきそうだったのでとりあえず入門機を買ってみた。

このシリーズはタブレットのサイズ(SまたはM)と付属するソフトウェアの違いで商品が分けれている。ソフトウェアはいずれも Linuxでは使えないのでタブレット本体だけでいいかなと思ったら、そちらはタッチ機能が無いようだ。(ぐぬぬ

一応、Macはあるので CLIP STUDIO PAINT(通称クリスタ)同梱版を買うことにした。

ペンタブ買ったンゴ

A post shared by Makoto Yoshida (@mattintosh4) on

自分は KDE環境で使っているんだけど、とりあえず USB 接続してみたらそのまま使えた。

GIMPでなんか適当なものを描いてみる。GIMPって筆圧検知あったっけ?

頭の悪い人描いた

A post shared by Makoto Yoshida (@mattintosh4) on

Krita は筆圧検知OK。何段階かは調べてないから知らない。(いや〜ようやく Krita が使える日がやってきた…)

f:id:mattintosh4:20171029220224p:plain

最初はしばらく右手の妙な動きに頭がついていかず苦労したけど2、3日使ってみると慣れてきた。ただ、残念ながらタッチ機能は良いとは言えないのでオフにして使っている。ドライバで補正するようにしているのかもしれないけど、ハードウェア的になんとかならないかなぁ。(Windowsのノートを使っていても思うけど何故 Macトラックパッド並のクオリティのものが一般的にならないのか不思議)

とりあえずタブレットがあるとこういうメモ書き的なものが楽ちん。

f:id:mattintosh4:20171029211148p:plain

マウスとして使うには若干不安があるんだけど、本職の人たちってどうやって使ってるんだろう。マウス操作はやっぱりマウスの方がいいのかな。

なんかペンが使いづらい気がするので別売のやつ買おうかな。


金曜日からアズールレーンでイベントが始まりましたが、とりあえずノーマルは全部クリア。B3 の削りは ユニコーンと シグニット で回していたけど、祥鳳 が育ってきたのでいまは 祥鳳 と シグニット で燃料16くらいで回している。本隊はレベリングも兼ねているので燃料ちょっと多めに40くらい。B3の最短は5戦+1戦なので 16 * 5 + 40 + 10 = 130 くらいが1周。

無事に 暁 もゲットできたのでこれでノーマルの巡回は終わり。(瑞鶴は絵馬交換でいいかな)

途中、扶桑 や クリーブランドもゲットできたので図鑑一覧を更新。いまのところ駆逐だけコンプ報酬対象に目印が付くようにしてある。これは ImageMagick-draw 'polygon'をシェルの変数で展開するようにしてたんだけど、シェルのパーサーが 'polygon 0,0 0,24 24,0'をバラバラに展開してしまうという罠があった。他のパラメータもすべて配列に入れれば解決するんだけどめんどくさいので -draw @inputでファイルからパラメータを読み込むようにした。

f:id:mattintosh4:20171029221235j:plain

Linux勢なので頑張って Krita の使い方を覚えなければ…。

Linux で Wacom CTH-490 を使うときの設定

$
0
0

Wacom CTH-490 を買ったのでちょっと設定を弄ってみる。CTH-490 だけど、サイズが違うだけの CTH-690 と共通だと思う。UbuntuKDEWacomタブレットドライバの環境は下記の通り。

$ lsb_release -a
Distributor ID: Ubuntu
Description:    Ubuntu 17.04
Release:    17.04
Codename:   zesty

$ kf5-config --version
Qt: 5.7.1
KDE Frameworks: 5.31.0
kf5-config: 1.0

$ plasmashell --version
plasmashell 5.9.5

$ modinfo wacom
filename:       /lib/modules/4.10.0-37-generic/kernel/drivers/hid/wacom.ko
license:        GPL
description:    USB Wacom tablet driver
author:         Vojtech Pavlik <vojtech@ucw.cz>
version:        v2.00
srcversion:     743E49E67E51AC164090406
alias:          hid:b0018g0101v0000056Ap*
alias:          hid:b0003g0101v0000056Ap*
alias:          hid:b0003g*v000017EFp00006004
alias:          hid:b0003g0101v0000056Ap00005002
alias:          hid:b0003g0101v0000056Ap00005000
alias:          hid:b0003g0101v0000056Ap00004004
alias:          hid:b0003g0101v0000056Ap00004001
alias:          hid:b0003g0101v0000056Ap00000343
alias:          hid:b0003g0101v0000056Ap0000033E
alias:          hid:b0003g0101v0000056Ap0000033D
alias:          hid:b0003g0101v0000056Ap0000033C
alias:          hid:b0003g0101v0000056Ap0000033B
alias:          hid:b0003g0101v0000056Ap00000336
alias:          hid:b0003g0101v0000056Ap00000335
alias:          hid:b0003g0101v0000056Ap00000333
alias:          hid:b0003g0101v0000056Ap00000331
alias:          hid:b0003g0101v0000056Ap0000032F
alias:          hid:b0003g0101v0000056Ap0000032C
alias:          hid:b0003g0101v0000056Ap0000032B
alias:          hid:b0003g0101v0000056Ap0000032A
alias:          hid:b0003g0101v0000056Ap00000326
alias:          hid:b0003g0101v0000056Ap00000325
alias:          hid:b0003g0101v0000056Ap00000323
alias:          hid:b0003g0101v0000056Ap00000319
alias:          hid:b0003g0101v0000056Ap00000318
alias:          hid:b0003g0101v0000056Ap00000317
alias:          hid:b0003g0101v0000056Ap00000315
alias:          hid:b0003g0101v0000056Ap00000314
alias:          hid:b0003g0101v0000056Ap0000030E
alias:          hid:b0003g0101v0000056Ap0000030C
alias:          hid:b0003g0101v0000056Ap0000030A
alias:          hid:b0003g0101v0000056Ap00000309
alias:          hid:b0003g0101v0000056Ap00000307
alias:          hid:b0003g0101v0000056Ap00000304
alias:          hid:b0003g0101v0000056Ap00000303
alias:          hid:b0003g0101v0000056Ap00000302
alias:          hid:b0003g0101v0000056Ap00000301
alias:          hid:b0003g0101v0000056Ap00000300
alias:          hid:b0003g0101v0000056Ap0000012C
alias:          hid:b0003g0101v0000056Ap00000116
alias:          hid:b0003g0101v0000056Ap0000010F
alias:          hid:b0003g0101v0000056Ap0000010E
alias:          hid:b0003g0101v0000056Ap0000010D
alias:          hid:b0003g0101v0000056Ap00000101
alias:          hid:b0003g0101v0000056Ap00000100
alias:          hid:b0003g0101v0000056Ap000000FB
alias:          hid:b0003g0101v0000056Ap000000FA
alias:          hid:b0003g0101v0000056Ap000000F8
alias:          hid:b0003g0101v0000056Ap000000F6
alias:          hid:b0003g0101v0000056Ap000000F4
alias:          hid:b0003g0101v0000056Ap000000F0
alias:          hid:b0003g0101v0000056Ap000000EF
alias:          hid:b0003g0101v0000056Ap000000ED
alias:          hid:b0003g0101v0000056Ap000000EC
alias:          hid:b0003g0101v0000056Ap000000E6
alias:          hid:b0003g0101v0000056Ap000000E5
alias:          hid:b0003g0101v0000056Ap000000E3
alias:          hid:b0003g0101v0000056Ap000000E2
alias:          hid:b0003g0101v0000056Ap000000DF
alias:          hid:b0003g0101v0000056Ap000000DE
alias:          hid:b0003g0101v0000056Ap000000DD
alias:          hid:b0003g0101v0000056Ap000000DB
alias:          hid:b0003g0101v0000056Ap000000DA
alias:          hid:b0003g0101v0000056Ap000000D8
alias:          hid:b0003g0101v0000056Ap000000D7
alias:          hid:b0003g0101v0000056Ap000000D6
alias:          hid:b0003g0101v0000056Ap000000D5
alias:          hid:b0003g0101v0000056Ap000000D4
alias:          hid:b0003g0101v0000056Ap000000D3
alias:          hid:b0003g0101v0000056Ap000000D2
alias:          hid:b0003g0101v0000056Ap000000D1
alias:          hid:b0003g0101v0000056Ap000000D0
alias:          hid:b0003g0101v0000056Ap000000CE
alias:          hid:b0003g0101v0000056Ap000000CC
alias:          hid:b0003g0101v0000056Ap000000C7
alias:          hid:b0003g0101v0000056Ap000000C6
alias:          hid:b0003g0101v0000056Ap000000C5
alias:          hid:b0003g0101v0000056Ap000000C4
alias:          hid:b0003g0101v0000056Ap000000C2
alias:          hid:b0003g0101v0000056Ap000000C0
alias:          hid:b0005g0101v0000056Ap000000BD
alias:          hid:b0003g0101v0000056Ap000000BC
alias:          hid:b0003g0101v0000056Ap000000BB
alias:          hid:b0003g0101v0000056Ap000000BA
alias:          hid:b0003g0101v0000056Ap000000B9
alias:          hid:b0003g0101v0000056Ap000000B8
alias:          hid:b0003g0101v0000056Ap000000B7
alias:          hid:b0003g0101v0000056Ap000000B5
alias:          hid:b0003g0101v0000056Ap000000B4
alias:          hid:b0003g0101v0000056Ap000000B3
alias:          hid:b0003g0101v0000056Ap000000B2
alias:          hid:b0003g0101v0000056Ap000000B1
alias:          hid:b0003g0101v0000056Ap000000B0
alias:          hid:b0003g0101v0000056Ap0000009F
alias:          hid:b0003g0101v0000056Ap0000009A
alias:          hid:b0003g0101v0000056Ap00000097
alias:          hid:b0003g0101v0000056Ap00000093
alias:          hid:b0003g0101v0000056Ap00000090
alias:          hid:b0003g0101v0000056Ap00000084
alias:          hid:b0005g0101v0000056Ap00000081
alias:          hid:b0003g0101v0000056Ap0000006B
alias:          hid:b0003g0101v0000056Ap0000006A
alias:          hid:b0003g0101v0000056Ap00000069
alias:          hid:b0003g0101v0000056Ap00000065
alias:          hid:b0003g0101v0000056Ap00000064
alias:          hid:b0003g0101v0000056Ap00000063
alias:          hid:b0003g0101v0000056Ap00000062
alias:          hid:b0003g0101v0000056Ap00000061
alias:          hid:b0003g0101v0000056Ap00000060
alias:          hid:b0003g0101v0000056Ap0000005E
alias:          hid:b0003g0101v0000056Ap0000005D
alias:          hid:b0003g0101v0000056Ap0000005B
alias:          hid:b0003g0101v0000056Ap00000059
alias:          hid:b0003g0101v0000056Ap00000057
alias:          hid:b0003g0101v0000056Ap00000047
alias:          hid:b0003g0101v0000056Ap00000045
alias:          hid:b0003g0101v0000056Ap00000044
alias:          hid:b0003g0101v0000056Ap00000043
alias:          hid:b0003g0101v0000056Ap00000042
alias:          hid:b0003g0101v0000056Ap00000041
alias:          hid:b0003g0101v0000056Ap0000003F
alias:          hid:b0003g0101v0000056Ap00000039
alias:          hid:b0003g0101v0000056Ap00000038
alias:          hid:b0003g0101v0000056Ap00000037
alias:          hid:b0003g0101v0000056Ap00000035
alias:          hid:b0003g0101v0000056Ap00000034
alias:          hid:b0003g0101v0000056Ap00000033
alias:          hid:b0003g0101v0000056Ap00000032
alias:          hid:b0003g0101v0000056Ap00000031
alias:          hid:b0003g0101v0000056Ap00000030
alias:          hid:b0003g0101v0000056Ap0000002A
alias:          hid:b0003g0101v0000056Ap00000029
alias:          hid:b0003g0101v0000056Ap00000028
alias:          hid:b0003g0101v0000056Ap00000027
alias:          hid:b0003g0101v0000056Ap00000026
alias:          hid:b0003g0101v0000056Ap00000024
alias:          hid:b0003g0101v0000056Ap00000023
alias:          hid:b0003g0101v0000056Ap00000022
alias:          hid:b0003g0101v0000056Ap00000021
alias:          hid:b0003g0101v0000056Ap00000020
alias:          hid:b0003g0101v0000056Ap00000019
alias:          hid:b0003g0101v0000056Ap00000018
alias:          hid:b0003g0101v0000056Ap00000017
alias:          hid:b0003g0101v0000056Ap00000016
alias:          hid:b0003g0101v0000056Ap00000015
alias:          hid:b0003g0101v0000056Ap00000014
alias:          hid:b0003g0101v0000056Ap00000013
alias:          hid:b0003g0101v0000056Ap00000012
alias:          hid:b0003g0101v0000056Ap00000011
alias:          hid:b0003g0101v0000056Ap00000010
alias:          hid:b0003g0101v0000056Ap00000003
alias:          hid:b0003g0101v0000056Ap00000000
depends:        hid
intree:         Y
vermagic:       4.10.0-37-generic SMP mod_unload 
parm:           touch_arbitration: on (Y) off (N) (bool)

ワコムタブレットの設定で使うコマンド

xsetwacom

xserver-xorg-input-wacomパッケージに含まれるコマンド。http://linuxwacom.sourceforge.net/wiki/index.php/Xsetwacomに説明がある。いくつかパラメータ名が古い(気がする)。

Usage: xsetwacom [options] [command [arguments...]]
Options:
 -h, --help                 - usage
 -v, --verbose              - verbose output
 -V, --version              - version info
 -d, --display "display"    - override default display
 -s, --shell                - generate shell commands for 'get'
 -x, --xconf                - generate xorg.conf lines for 'get'

Commands:
 --list devices             - display detected devices
 --list parameters          - display supported parameters
 --list modifiers           - display supported modifier and specific keys for keystrokes
 --set "device name" parameter [values...] - set device parameter by name
 --get "device name" parameter [param...]  - get current device parameter(s) value by name

xinput

xinput パッケージに含まれるコマンド。ワコムタブレットにかかわらず、ノートPCのタッチパットやキーボードなど入力に関するデバイスの制御を行う。

$ xinput --help
usage :
    xinput get-feedbacks <device name>
    xinput set-ptr-feedback <device name> <threshold> <num> <denom>
    xinput set-integer-feedback <device name> <feedback id> <value>
    xinput get-button-map <device name>
    xinput set-button-map <device name> <map button 1> [<map button 2> [...]]
    xinput set-pointer <device name> [<x index> <y index>]
    xinput set-mode <device name> ABSOLUTE|RELATIVE
    xinput list [--short || --long || --name-only || --id-only] [<device name>...]
    xinput query-state <device name>
    xinput test [-proximity] <device name>
    xinput create-master <id> [<sendCore (dflt:1)>] [<enable (dflt:1)>]
    xinput remove-master <id> [Floating|AttachToMaster (dflt:Floating)] [<returnPointer>] [<returnKeyboard>]
    xinput reattach <id> <master>
    xinput float <id>
    xinput set-cp <window> <device>
    xinput test-xi2 [--root] <device>
    xinput map-to-output <device> <output name>
    xinput list-props <device> [<device> ...]
    xinput set-int-prop <device> <property> <format (8, 16, 32)> <val> [<val> ...]
    xinput set-float-prop <device> <property> <val> [<val> ...]
    xinput set-atom-prop <device> <property> <val> [<val> ...]
    xinput watch-props <device>
    xinput delete-prop <device> <property>
    xinput set-prop <device> [--type=atom|float|int] [--format=8|16|32] <property> <val> [<val> ...]
    xinput disable <device>
    xinput enable <device>

バイスの検索

CTH-490 はタッチ対応モデルなのでタッチデバイスが出てくる。

$ xsetwacom --list devices
Wacom Intuos PT S 2 Pen stylus      id: 9   type: STYLUS    
Wacom Intuos PT S 2 Finger touch    id: 10  type: TOUCH     
Wacom Intuos PT S 2 Pad pad         id: 11  type: PAD       

$ xinput list
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Pen stylus            id=9    [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Pad pad               id=10   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Finger touch          id=11   [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Video Bus                                   id=7    [slave  keyboard (3)]
    ↳ Power Button                                id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                id=12   [slave  keyboard (3)]
    ↳ Panasonic Laptop Support                    id=14   [slave  keyboard (3)]

設定の確認

xsetwacom では --list paramで設定の一覧を確認することができる。ただしこれはドライバが対応しているだけで CTH-490 がすべて対応しているわけではない。

$ xsetwacom --list param
Area             - Valid tablet area in device coordinates. 
Button           - X11 event to which the given button should be mapped. 
ToolDebugLevel   - Level of debugging trace for individual tools (default is 0 [off]). 
TabletDebugLevel - Level of debugging statements applied to shared code paths between all tools associated with the same tablet (default is 0 [off]). 
Suppress         - Number of points trimmed (default is 2). 
RawSample        - Number of raw data used to filter the points (default is 4). 
PressureCurve    - Bezier curve for pressure (default is 0 0 100 100 [linear]). 
Mode             - Switches cursor movement mode (default is absolute). 
TabletPCButton   - Turns on/off Tablet PC buttons (default is off for regular tablets, on for Tablet PC). 
Touch            - Turns on/off Touch events (default is on). 
HWTouchSwitchState - Touch events turned on/off by hardware switch. 
Gesture          - Turns on/off multi-touch gesture events (default is on). 
ZoomDistance     - Minimum distance for a zoom gesture (default is 50). 
ScrollDistance   - Minimum motion before sending a scroll gesture (default is 20). 
TapTime          - Minimum time between taps for a right click (default is 250). 
CursorProximity  - Sets cursor distance for proximity-out in distance from the tablet (default is 10 for Intuos series, 42 for Graphire series). 
Rotate           - Sets the rotation of the tablet. Values = none, cw, ccw, half (default is none). 
RelWheelUp       - X11 event to which relative wheel up should be mapped. 
RelWheelDown     - X11 event to which relative wheel down should be mapped. 
AbsWheelUp       - X11 event to which absolute wheel up should be mapped. 
AbsWheelDown     - X11 event to which absolute wheel down should be mapped. 
AbsWheel2Up      - X11 event to which absolute wheel up should be mapped. 
AbsWheel2Down    - X11 event to which absolute wheel down should be mapped. 
StripLeftUp      - X11 event to which left strip up should be mapped. 
StripLeftDown    - X11 event to which left strip down should be mapped. 
StripRightUp     - X11 event to which right strip up should be mapped. 
StripRightDown   - X11 event to which right strip down should be mapped. 
Threshold        - Sets tip/eraser pressure threshold (default is 27). 
ResetArea        - Resets the bounding coordinates to default in tablet units. 
ToolType         - Returns the tool type of the associated device. 
ToolSerial       - Returns the serial number of the current device in proximity.
ToolID           - Returns the tool ID of the current tool in proximity.
ToolSerialPrevious - Returns the serial number of the previous device in proximity.
BindToSerial     - Binds this device to the serial number.
TabletID         - Returns the tablet ID of the associated device. 
PressureRecalibration - Turns on/off Tablet pressure recalibration
MapToOutput      - Map the device to the given output. 
all              - Get value for all parameters. 

get デバイス名 allタブレットの設定値をすべて呼び出す。デバイス名の指定方法は確認した限りでは2種類で、デバイス名とデバイス ID で指定する方法がある。デバイス ID は変わることがあるので注意。

$ xsetwacom --list devices
Wacom Intuos PT S 2 Pen stylus      id: 9   type: STYLUS    
Wacom Intuos PT S 2 Finger touch    id: 10  type: TOUCH     
Wacom Intuos PT S 2 Pad pad         id: 11  type: PAD       

$ xsetwacom --get "Wacom Intuos PT S 2 Pen stylus" all # デバイス名で指定する場合
$ xsetwacom --get 9 all # デバイスIDで指定する場合

xsetwacom --list devicesの出力はタブ区切りになっているので grepcutawkでデバイス名だけを取り出すことができる。ただし、余計な空白を含んでいるようなので変数などに入れて呼び出したい場合は文字列の後ろにある空白を取り除く処理が必要になる。いくつかサンプルを掲載しておくけどここではシェルのお勉強はしないので方法はお好みで。

$ xsetwacom --list devices | awk -F $'\t' '/type: STYLUS/{ print $1 }'
Wacom Intuos PT S 2 Pen stylus  ←ここに微妙にスペースが残っている
$ echo `xsetwacom --list devices | awk -F $'\t' '/type: STYLUS/{ print $1 }'` # 文字列前後の余計な空白を取り除いてデバイス名を取り出す
Wacom Intuos PT S 2 Pen stylus
$ xsetwacom --list devices | grep 'type: PAD' | cut -d $'\t' -f2 | grep -o '[0-9]*' # デバイスIDだけ取り出す
11

以降はわかりやすくデバイスWacom Intuos PT S 2 Pen stylusを使うことにする。

とりあえず allで全項目を見る。

$ xsetwacom --get "Wacom Intuos PT S 2 Pen stylus" all
Button: Actions are not supported by xorg.conf. Try shell format (-s) instead.
Button: Actions are not supported by xorg.conf. Try shell format (-s) instead.
Button: Actions are not supported by xorg.conf. Try shell format (-s) instead.
Property 'Wacom Hardware Touch Switch' does not exist on device.
Property 'Wacom Proximity Threshold' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Wheel Buttons' does not exist on device.
Property 'Wacom Strip Buttons' does not exist on device.
Property 'Wacom Strip Buttons' does not exist on device.
Property 'Wacom Strip Buttons' does not exist on device.
Property 'Wacom Strip Buttons' does not exist on device.
Option "Area" "0 0 15200 9500"
Option "DebugLevel" "0"
Option "CommonDBG" "0"
Option "Suppress" "2"
Option "RawSample" "4"
Option "PressCurve" "0 0 100 100"
Option "Mode" "Absolute"
Option "TPCButton" "off"
Option "Touch" "off"
Option "Gesture" "off"
Option "ZoomDistance" "0"
Option "ScrollDistance" "0"
Option "TapTime" "250"
Option "Rotate" "none"
Option "Threshold" "27"
Option "Serial" "0"
Option "PressureRecalibration" "on"

いくつかは設定値が存在しないためエラーとなる。これが煩わしければこれらは標準エラー出力に出ているので捨てれば良い。

$ xsetwacom --get "Wacom Intuos PT S 2 stylus" all 2>/dev/null
Option "Area" "0 0 15200 9500"
Option "DebugLevel" "0"
Option "CommonDBG" "0"
Option "Suppress" "2"
Option "RawSample" "4"
Option "PressCurve" "0 0 100 100"
Option "Mode" "Absolute"
Option "TPCButton" "off"
Option "Touch" "off"
Option "Gesture" "off"
Option "ZoomDistance" "0"
Option "ScrollDistance" "0"
Option "TapTime" "250"
Option "Rotate" "none"
Option "Threshold" "27"
Option "Serial" "0"
Option "PressureRecalibration" "on"

見てみると Option "Mode""Absolute"があるので、マウスのように相対位置でカーソルを動かすこともできるようだ。(やってみたが恐らく Areaも弄らないととんでもない移動量になる)

Thresholdしきい値だが、どれくらいの筆圧から検知するかの設定だと思う。デフォルトは 27だけど 1にすれば弱く書いても反応するし、1024に設定すれば筆圧を強くしないと書けない。

PressCurveは筆圧カーブだと思う。設定に関する情報は Wacom タブレット - ArchWikiに書いてある。また、Xsetwacom - linuxwacomには下記のような説明がある。

  0 100   0 100  # ridiculously soft
  0  50  50 100  # very soft
  0   0 100 100  # linear, the default
 50   0 100  50  # very firm
100   0 100   0  # unbelievably firm

PressCurveは現在、PressureCurveに変わっていたりする。新しい名称は Xsetwacom - linuxwacomに書かれている。

xinput でも同様に設定値の確認ができる。こちらもデバイス名またはデバイス ID を使用することができる。設定値の隣にある ()内の数値はデフォルト値などではなく、設定 ID のようだ。

$ xinput list
⎡ Virtual core pointer                        id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=13   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Pen stylus            id=9    [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Pad pad               id=10   [slave  pointer  (2)]
⎜   ↳ Wacom Intuos PT S 2 Finger touch          id=11   [slave  pointer  (2)]
⎣ Virtual core keyboard                       id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard                 id=5    [slave  keyboard (3)]
    ↳ Power Button                                id=6    [slave  keyboard (3)]
    ↳ Video Bus                                   id=7    [slave  keyboard (3)]
    ↳ Power Button                                id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard                id=12   [slave  keyboard (3)]
    ↳ Panasonic Laptop Support                    id=14   [slave  keyboard (3)]

$ xinput list-props 'Wacom Intuos PT S 2 Pen stylus'
Device 'Wacom Intuos PT S 2 Pen stylus':
    Device Enabled (139):   1
    Coordinate Transformation Matrix (141): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
    Device Accel Profile (268): 0
    Device Accel Constant Deceleration (269):   1.000000
    Device Accel Adaptive Deceleration (270):   1.000000
    Device Accel Velocity Scaling (271):    10.000000
    Device Node (265):  "/dev/input/event4"
    Wacom Tablet Area (278):    0, 0, 15200, 9500
    Wacom Rotation (279):   0
    Wacom Pressurecurve (280):  0, 0, 100, 100
    Wacom Serial IDs (281): 828, 2021887582, 2274, 0, 0
    Wacom Serial ID binding (282):  0
    Wacom Pressure Threshold (283): 27
    Wacom Sample and Suppress (284):    2, 4
    Wacom Enable Touch (285):   0
    Wacom Hover Click (286):    1
    Wacom Enable Touch Gesture (287):   0
    Wacom Touch Gesture Parameters (288):   0, 0, 250
    Wacom Tool Type (289):  "STYLUS" (267)
    Wacom Button Actions (290): "Wacom button action 0" (291), "Wacom button action 1" (292), "Wacom button action 2" (293)
    Wacom button action 0 (291):    1572865
    Wacom button action 1 (292):    1572866
    Wacom button action 2 (293):    1572867
    Wacom Pressure Recalibration (294): 1
    Device Product ID (266):    1386, 828
    Wacom Debug Levels (295):   0, 0

$ xinput list-props 9
Device 'Wacom Intuos PT S 2 Pen stylus':
    Device Enabled (139):   1
    Coordinate Transformation Matrix (141): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
    Device Accel Profile (268): 0
    Device Accel Constant Deceleration (269):   1.000000
    Device Accel Adaptive Deceleration (270):   1.000000
    Device Accel Velocity Scaling (271):    10.000000
    Device Node (265):  "/dev/input/event4"
    Wacom Tablet Area (278):    0, 0, 15200, 9500
    Wacom Rotation (279):   0
    Wacom Pressurecurve (280):  0, 0, 100, 100
    Wacom Serial IDs (281): 828, 2021887582, 2274, 0, 0
    Wacom Serial ID binding (282):  0
    Wacom Pressure Threshold (283): 27
    Wacom Sample and Suppress (284):    2, 4
    Wacom Enable Touch (285):   0
    Wacom Hover Click (286):    1
    Wacom Enable Touch Gesture (287):   0
    Wacom Touch Gesture Parameters (288):   0, 0, 250
    Wacom Tool Type (289):  "STYLUS" (267)
    Wacom Button Actions (290): "Wacom button action 0" (291), "Wacom button action 1" (292), "Wacom button action 2" (293)
    Wacom button action 0 (291):    1572865
    Wacom button action 1 (292):    1572866
    Wacom button action 2 (293):    1572867
    Wacom Pressure Recalibration (294): 1
    Device Product ID (266):    1386, 828
    Wacom Debug Levels (295):   0, 0

こちらもデバイス名またはデバイス ID で指定することができる。設定値の方も ID が使用可能。

$ xinput set-prop 'Wacom Intuos PT S 2 Pen stylus' 'Wacom Pressure Threshold' 1
$ xinput set-prop 9 283 1

watch-propsでは設定値のモニタリングができるので設定が変更されたときに変更点を随時表示してくれる。

$ xinput watch-props 9

設定の自動反映

※ここからは検証中

xsetwacomで設定した内容はタブレットを接続し直すと元に戻ってしまうので udev でコントロールする。が、xsetwacomxinputもデバイスが接続されたあとでなければ意味が無いのでどうしようかな、と。(スリープ?いや、なんかダサい…)

とりあえず udev か xorg.confで設定することになると思うが、とりあえずデバイス ID を調べる…。

$ lsusb
Bus 002 Device 046: ID 056a:033c Wacom Co., Ltd 
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

CTH-490 はベンダー ID 056a、製品 ID 033cのようだ。が、

$ udevadm info -p `udevadm -nva idProduct=033c`
P: /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
N: bus/usb/002/046
E: BUSNUM=002
E: DEVNAME=/dev/bus/usb/002/046
E: DEVNUM=046
E: DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2
E: DEVTYPE=usb_device
E: DRIVER=usb
E: ID_BUS=usb
E: ID_MODEL=Intuos_PTS
E: ID_MODEL_ENC=Intuos\x20PTS
E: ID_MODEL_ID=033c
E: ID_REVISION=0100
E: ID_SERIAL=Wacom_Co._Ltd._Intuos_PTS
E: ID_USB_INTERFACES=:030000:030102:
E: ID_VENDOR=Wacom_Co._Ltd.
E: ID_VENDOR_ENC=Wacom\x20Co.\x2cLtd.
E: ID_VENDOR_FROM_DATABASE=Wacom Co., Ltd
E: ID_VENDOR_ID=056a
E: MAJOR=189
E: MINOR=173
E: PRODUCT=56a/33c/100
E: SUBSYSTEM=usb
E: TYPE=0/0/0
E: USEC_INITIALIZED=12674327735

と、やってみたが SUBSYSTEM=usbじゃなくて SUBSYSTEM=inputなんだよな…。/dev/input以下を見ると色々あるが、どれがスタイラスとかパッドかわからない。

$ ls /dev/input
by-id
by-path
event0
event1
event10
event11
event12
event2
event3
event4
event5
event6
event7
event8
event9
js0
mice
mouse0
mouse1
mouse2
mouse3

xinput の Device Node を見てみるとスタイラスはいまのところ /dev/input/event4のようだ。(接続したタイミングで変わるので注意)

$ xinput list-props 9 | grep Node
        Device Node (265):      "/dev/input/event4"

んで /dev/input/event4を udevadm で見てみる。

$ udevadm info -a $(eval echo $(xinput list-props 9 | grep Node | cut -f 3))
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/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0082/input/input275/event4':
    KERNEL=="event4"
    SUBSYSTEM=="input"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0082/input/input275':
    KERNELS=="input275"
    SUBSYSTEMS=="input"
    DRIVERS==""
    ATTRS{name}=="Wacom Intuos PT S 2 Pen"
    ATTRS{phys}=="usb-0000:00:1d.0-1.2/input0"
    ATTRS{properties}=="1"
    ATTRS{uniq}==""

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0082':
    KERNELS=="0003:056A:033C.0082"
    SUBSYSTEMS=="hid"
    DRIVERS=="wacom"
    ATTRS{country}=="00"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0':
    KERNELS=="2-1.2:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usbhid"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="03"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bInterfaceProtocol}=="00"
    ATTRS{bInterfaceSubClass}=="00"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2':
    KERNELS=="2-1.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="498mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 3"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bmAttributes}=="80"
    ATTRS{busnum}=="2"
    ATTRS{configuration}==""
    ATTRS{devnum}=="46"
    ATTRS{devpath}=="1.2"
    ATTRS{idProduct}=="033c"
    ATTRS{idVendor}=="056a"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Wacom Co.,Ltd."
    ATTRS{maxchild}=="0"
    ATTRS{product}=="Intuos PTS"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="removable"
    ATTRS{speed}=="12"
    ATTRS{urbnum}=="366249"
    ATTRS{version}==" 2.00"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2/2-1':
    KERNELS=="2-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0000"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="2"
    ATTRS{configuration}==""
    ATTRS{devnum}=="2"
    ATTRS{devpath}=="1"
    ATTRS{idProduct}=="0024"
    ATTRS{idVendor}=="8087"
    ATTRS{ltm_capable}=="no"
    ATTRS{maxchild}=="8"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="fixed"
    ATTRS{speed}=="480"
    ATTRS{urbnum}=="1238"
    ATTRS{version}==" 2.00"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb2':
    KERNELS=="usb2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{authorized_default}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0410"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="2"
    ATTRS{configuration}==""
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{idProduct}=="0002"
    ATTRS{idVendor}=="1d6b"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.10.0-38-generic ehci_hcd"
    ATTRS{maxchild}=="3"
    ATTRS{product}=="EHCI Host Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="0000:00:1d.0"
    ATTRS{speed}=="480"
    ATTRS{urbnum}=="494"
    ATTRS{version}==" 2.00"

  looking at parent device '/devices/pci0000:00/0000:00:1d.0':
    KERNELS=="0000:00:1d.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="ehci-pci"
    ATTRS{broken_parity_status}=="0"
    ATTRS{class}=="0x0c0320"
    ATTRS{companion}==""
    ATTRS{consistent_dma_mask_bits}=="32"
    ATTRS{d3cold_allowed}=="1"
    ATTRS{device}=="0x1c26"
    ATTRS{dma_mask_bits}=="32"
    ATTRS{driver_override}=="(null)"
    ATTRS{enable}=="1"
    ATTRS{irq}=="23"
    ATTRS{local_cpulist}=="0-3"
    ATTRS{local_cpus}=="000f"
    ATTRS{msi_bus}=="1"
    ATTRS{numa_node}=="-1"
    ATTRS{revision}=="0x04"
    ATTRS{subsystem_device}=="0x8338"
    ATTRS{subsystem_vendor}=="0x10f7"
    ATTRS{uframe_periodic_max}=="100"
    ATTRS{vendor}=="0x8086"

  looking at parent device '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

適当に /etc/udev/rules.d/90-wacom.rulesを作る。

ACTION=="add", SUBSYSTEMS=="input", ATTRS{name}=="Wacom Intuos PT S 2 Pen", RUN+="/usr/bin/env XAUTHORITY=/home/me/.Xauthority DISPLAY=:0 /usr/bin/xsetwacom set 'Wacom Intuos PT S 2 Pen stylus' Threashold 1"
$ udevadm test --action=add `udevadm trigger -nva name="Wacom Intuos PT S 2 Pen"`
calling: test
version 232
=== trie on-disk ===
tool version:          232
file size:         8801854 bytes
header size             80 bytes
strings            1856302 bytes
nodes              6945472 bytes
:
中略
:
Reading rules file: /etc/udev/rules.d/99-wacom.rules
RUN '/usr/bin/env XAUTHORITY=/home/matthew/.Xauthority DISPLAY=:0 /usr/bin/xsetwacom set 'Wacom Intuos PT S 2 Pen stylus' Threashold 1' /etc/udev/rules.d/99-wacom.rules:5
Unload module index
Unloaded link configuration context.
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.

.INPUT_CLASS=mouse
.MM_USBIFNUM=00
ABS=10003000003
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0082/input/input275
EV=1b
ID_BUS=usb
ID_FOR_SEAT=input-pci-0000_00_1d_0-usb-0_1_2_1_0
ID_INPUT=1
ID_INPUT_TABLET=1
ID_MODEL=Intuos_PTS
ID_MODEL_ENC=Intuos\x20PTS
ID_MODEL_ID=033c
ID_PATH=pci-0000:00:1d.0-usb-0:1.2:1.0
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_2_1_0
ID_REVISION=0100
ID_SERIAL=Wacom_Co._Ltd._Intuos_PTS
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030000:030102:
ID_USB_INTERFACE_NUM=00
ID_VENDOR=Wacom_Co._Ltd.
ID_VENDOR_ENC=Wacom\x20Co.\x2cLtd.
ID_VENDOR_ID=056a
KEY=1c01 0 0 0 0 0
MODALIAS=input:b0003v056Ap033Ce0110-e0,1,3,4,k140,14A,14B,14C,ra0,1,18,19,28,m0,lsfw
MSC=1
NAME="Wacom Intuos PT S 2 Pen"
PHYS="usb-0000:00:1d.0-1.2/input0"
PRODUCT=3/56a/33c/110
PROP=1
SUBSYSTEM=input
TAGS=:seat:
UNIQ=""
USEC_INITIALIZED=12674348315
run: 'kmod load input:b0003v056Ap033Ce0110-e0,1,3,4,k140,14A,14B,14C,ra0,1,18,19,28,m0,lsfw'
run: '/usr/bin/env XAUTHORITY=/home/me/.Xauthority DISPLAY=:0 /usr/bin/xsetwacom set 'Wacom Intuos PT S 2 Pen stylus' Threashold 1'

udevadm のテストでは RUN+=に設定したコマンドが走るようだけど、これじゃ設定されないのよね。sleep挟んだところでこのコマンド終わらないとデバイス認識されないだろうし…。

一応、udevadm monitor --envで監視したときにスタイラスの情報を残しておく。

UDEV  [76906.924294] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0085/input/input281 (input)
.INPUT_CLASS=mouse
.MM_USBIFNUM=00
ABS=10003000003
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/0003:056A:033C.0085/input/input281
EV=1b
ID_BUS=usb
ID_FOR_SEAT=input-pci-0000_00_1d_0-usb-0_1_2_1_0
ID_INPUT=1
ID_INPUT_TABLET=1
ID_MODEL=Intuos_PTS
ID_MODEL_ENC=Intuos\x20PTS
ID_MODEL_ID=033c
ID_PATH=pci-0000:00:1d.0-usb-0:1.2:1.0
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_2_1_0
ID_REVISION=0100
ID_SERIAL=Wacom_Co._Ltd._Intuos_PTS
ID_TYPE=hid
ID_USB_DRIVER=usbhid
ID_USB_INTERFACES=:030000:030102:
ID_USB_INTERFACE_NUM=00
ID_VENDOR=Wacom_Co._Ltd.
ID_VENDOR_ENC=Wacom\x20Co.\x2cLtd.
ID_VENDOR_ID=056a
KEY=1c01 0 0 0 0 0
MODALIAS=input:b0003v056Ap033Ce0110-e0,1,3,4,k140,14A,14B,14C,ra0,1,18,19,28,m0,lsfw
MSC=1
NAME="Wacom Intuos PT S 2 Pen"
PHYS="usb-0000:00:1d.0-1.2/input0"
PRODUCT=3/56a/33c/110
PROP=1
SEQNUM=7299
SUBSYSTEM=input
TAGS=:seat:
UNIQ=""
USEC_INITIALIZED=76906917653

あとは xorg.confを使う方法。これまた /usr/share/X11/xorg.conf/90-wacom.confとかいう適当なものを作る。

Section "InputClass"
    Identifier  "Wacom CTH-490"
    MatchUSBID  "056a:033c"
    Option      "Wacom Pressure Threshold" "1"
EndSection

とりあえず時間なくて色々試す暇が無いので KDE環境のスタートアップを使うことにして、.config/autostart-scripts/wacom.shを作ってログイン時に実行するようにしておいた。

#!/bin/sh
/usr/bin/xsetwacom set "Wacom Intuos PT S 2 Pen stylus" Threshold 1

Shell と PING でネットワークの速度を監視する

$
0
0

とある場所のネットワーク速度が著しく低下することがあったので監視目的で PINGを使ってみることにした(iperf 使いたいけど相手が居ない)。とりあえず PINGの出力をパースして SQLiteに格納。GNUPLOTで可視化するけど、そのうち Zabbix とかに移して動的監視する予定。

今回は「お兄ちゃん、GREPAWKの使用を禁止します!」縛りでやります。

PINGからの文字列の取り出し

ping-c {count}で回数を指定すると最後に統計を出してくれるのでそこから min、avg、max、mdev を取得します。

$ ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.092 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.092/0.092/0.092/0.000 ms

文字列の切り出しは grepsedawkなんかを使うのが定番ですが、冒頭の宣言に従い、ここではシェルの機能のみでやっていきます。

まず、IFSを改行のみに変更して pingの出力を行ごとに位置パラメータに格納します。

IFS=$'\n'set -- $(ping -c1 localhost)

set -x(xtrace)を使ってシェルの動きを見てみます。

+ IFS=''
++ ping -c1 localhost
+ set -- 'PING localhost (127.0.0.1) 56(84) bytes of data.''64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.090 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.090/0.090/0.090/0.000 ms'

evalで遅延展開を使って位置パラメータに入っている文字列を出力してみます。

for((i = 1; i <= ${#}; i++))doevalecho LINE ${i}: \${${i}}done

行ごとに位置パラメータに格納されているのがわかります。この中で必要になるのは最後の行だけです。

LINE 1: PING localhost (127.0.0.1) 56(84) bytes of data.
LINE 2: 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.090 ms
LINE 3: --- localhost ping statistics ---
LINE 4: 1 packets transmitted, 1 received, 0% packet loss, time 0ms
LINE 5: rtt min/avg/max/mdev = 0.090/0.090/0.090/0.000 ms

なお、遅延展開には以下のような方法があります。1番目と2番目は書式が違うだけで同じ動きをしますが、(自分の備忘録によると)3番目は ZSHでは使えないようなので注意が必要です。位置パラメータが二桁を超えると {}が必要となりますので常につけておく方が無難だと思います。

evalecho\${${#}}evalecho'$'{${#}}echo${!#}

今度は最後の行だけを取り出して再度位置パラメータにセットします。現在の IFSは改行のみになっているので、予め IFSを変更して単語の分割も一緒にやってしまいます。最後の行で使われている区切り文字は space/=なのでこの3つを IFSにセットします。

IFS=' /='

そして、先程と同じように evalを使って遅延展開で最終行を展開します。

evalset -- \${${#}}

forで位置パラメータを見てみます。

for((i = 1; i <= ${#}; i++))doevalecho ITEM ${i}: \${${i}}done

これで最終行の分割ができました。

ITEM 1: rtt
ITEM 2: min
ITEM 3: avg
ITEM 4: max
ITEM 5: mdev
ITEM 6: 0.090
ITEM 7: 0.090
ITEM 8: 0.090
ITEM 9: 0.000
ITEM 10: ms

通常は ITEM 6〜ITEM 9までを取り出して変数に代入するのでしょうが、ITEM 2〜ITEM 5までの文字列が変数名に使えるのでそのまま使います。

${2}=${6}# -> min=0.090${3}=${7}# -> avg=0.090${4}=${8}# -> max=0.090${5}=${9}# -> mdev=0.000

これを evalで実行します。

eval${2}=${6}${3}=${7}${4}=${8}${5}=${9}echo MIN : ${min}echo AVG : ${avg}echo MAX : ${max}echo MDEV: ${mdev}
MIN : 0.090
AVG : 0.090
MAX : 0.090
MDEV: 0.000

for文を消して set -vxで見てみると位置パラメータが evalによってどのように展開されているかわかると思います。

IFS=$'\n'
+ IFS=''set -- $(ping -c1 localhost)
++ ping -c1 localhost
+ set -- 'PING localhost (127.0.0.1) 56(84) bytes of data.''64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.046 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.046/0.046/0.046/0.000 ms'IFS=' /='
+ IFS=' /='evalset -- \${${#}}
+ evalset -- '${5}'set -- ${5}
++ set -- rtt min avg max mdev 0.046 0.046 0.046 0.000 mseval${2}=${6}${3}=${7}${4}=${8}${5}=${9}
+ evalmin=0.046 avg=0.046 max=0.046 mdev=0.000
min=0.046 avg=0.046 max=0.046 mdev=0.000
++ min=0.046
++ avg=0.046
++ max=0.046
++ mdev=0.000

echo MIN : ${min}
+ echo MIN : 0.046
MIN : 0.046
echo AVG : ${avg}
+ echo AVG : 0.046
AVG : 0.046
echo MAX : ${max}
+ echo MAX : 0.046
MAX : 0.046
echo MDEV: ${mdev}
+ echo MDEV: 0.000
MDEV: 0.000

とりあえずまとめると以下の数行で pingコマンドの出力から変数の代入までができます。

save_IFS=${IFS}IFS=$'\n'set -- $(ping -c1 localhost)IFS=' /='evalset -- \${${#}}eval${2}=${6}${3}=${7}${4}=${8}${5}=${9}IFS=${save_IFS}

IFSをバックアップしたりするのが面倒な場合はサブシェルで実行してもいいと思います。

eval$(IFS=$'\n'    set -- $(ping -c1 localhost)IFS=' /='eval set -- \${${#}}echo${2}=${6}${3}=${7}${4}=${8}${5}=${9})

なお、IFSは以下のコマンドで初期状態になります。

IFS=$'\t\n'

PINGタイムスタンプの取得

ping-Dでタイムスタンプが拾えます。これは2行目から拾えばよさそうです。

$ ping -c1 -D localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
[1511621731.988689] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.063 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.063/0.063/0.063/0.000 ms

文字列の取り出しの前にタイムスタンプ部分の説明をしておきます。-Dオプションで表示される書式は UNIX時間なので、読みやすくするためには変換が必要になります。これは dateコマンドを使います。

$ LC_TIME=C date -d@1511621731.988689
Sat Nov 25 23:55:31 JST 2017

SQLiteの日付型の書式は yyyy-mm-dd HH:MM:SSのようになっているので以下のように変換をします。ただ、SQLiteUNIX時間を整数型か浮動小数点数型で追加してもあとから変換はできるので、ここで無理して日付型に変換する必要はないかもしれません。

$ LC_TIME=C date -d@1511621731.988689 +'%F %T'
2017-11-25 23:55:31

さて、pingコマンドの出力からタイムスタンプ部分を抜き出す必要がありますが、少々余計なものがいくつかあります。

PING localhost (127.0.0.1) 56(84) bytes of data.
[1511621731.988689] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.063 ms
(以下略)

まずは2行目を取り出します。ping-Dオプションを忘れずに。

IFS=$'\n'set -- $(ping -c1 -D localhost)echo${2}

2行目が取り出せました。ここからタイムスタンプ部分だけを取り出したいのですが、[]が邪魔ですね。

[1511622657.836489] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.042 ms

[]を区切り文字として IFSにセットします。位置パラメータがどうなってるかわかりやすくするために途中に set -xを入れます。

IFS=' []'set-xset -- ${2}echo${2}

先頭の [の左には何もないので空になっています。タイムスタンプの右側にあった ]は区切り文字として扱われたので無くなりました。

+ set -- '' 1511622852.338428 64 bytes from localhost '(127.0.0.1):'
+ echo 1511622852.338428

dateコマンドに渡せる書式になったので変換します。

date -d@${2} +$'%F %T'

これで yyyy-mm-dd HH:MM:SS形式で取り出せました。

2017-11-26 00:15:33

ここまでを続けて書くと以下のようになります。

IFS=$'\n'set -- $(ping -c1 -D localhost)IFS=' []'set -- ${2}           # ここの ${2}は「2""目」
date -d@${2} +'%F %T'# ここの ${2} は「2"列"目」

PINGコマンドの2行目からタイムスタンプを取得して最終行から結果を取得する

ここまでで最終行の取り出しとタイムスタンプの取り出しができましたが、実は問題があります。最終行の取り出し、もタイムスタンプの取り出しも、2回目の setで最初に取得した pingコマンドの結果を上書きしてしまっているためどちらかしか取り出せません。

最初に取得した pingコマンドの結果を使い回す方法はいくつかあると思いますが、

  • pingコマンドの結果を変数に格納しておく
  • 関数を作って位置パラメータを渡す
  • サブシェルで処理する

の3つくらいでしょうか。(シェルに詳しい人なら他にも思いつきそうですが)

ここまで位置パラメータだけでやってきて今更 pingコマンドの結果を変数に入れるのはスマートな方法ではないような気がするので関数かサブシェルにします。

まずは関数版から。カレントシェルの IFSが書き換わるのが嫌なのですべてサブシェル内で実行しています。カレントシェルでやる場合は適当な変数に最初の IFSを保存しておくとよいです。

# as = Assignment Statementstime_as(){(IFS=' []'
        set --${2}
        date -d@${2} +'time="%F %T"')}stat_as(){(IFS=' /='eval set --\${${#}}
        echo${2}=${6}${3}=${7}${4}=${8}${5}=${9})}## IF CURRENT SHELL#save_IFS=${IFS} IFS=$'\n'#set -- $(ping -c1 -D localhost)#IFS=${save_IFS}eval$(IFS=$'\n'    set -- $(ping -c1-D localhost)    time_as "${@}"    stat_as "${@}")echo${time}${min}${avg}${max}${mdev}

それぞれの関数に "${@}"で一番最初に取得した位置パラメータ群を渡すと代入分を返してくれるので evalで実行させて代入まで済ませます。

set-xreturn_time_as(){(IFS=' []'
        set --${2}
        date -d@${2} +'time="%F %T"')}return_stat_as(){(IFS=' /='eval set --\${${#}}
        echo${2}=${6}${3}=${7}${4}=${8}${5}=${9})}eval$(IFS=$'\n'    set -- $(ping -c1-D localhost)    return_time_as "${@}"    return_stat_as "${@}")
++ IFS=''
+++ ping -c1-D localhost
++ set -- 'PING localhost (127.0.0.1) 56(84) bytes of data.''[1511627944.923406] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.043 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.043/0.043/0.043/0.000 ms'
++ return_time_as 'PING localhost (127.0.0.1) 56(84) bytes of data.''[1511627944.923406] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.043 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.043/0.043/0.043/0.000 ms'
++ IFS=' []'
++ set -- '' 1511627944.923406 64 bytes from localhost '(127.0.0.1):' icmp_seq=1 ttl=64 time=0.043 ms
++ date -d@1511627944.923406 '+time="%F %T"'
++ return_stat_as 'PING localhost (127.0.0.1) 56(84) bytes of data.''[1511627944.923406] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.043 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.043/0.043/0.043/0.000 ms'
++ IFS=' /='
++ evalset -- '${5}'
+++ set -- rtt min avg max mdev 0.043 0.043 0.043 0.000 ms
++ echo min=0.043 avg=0.043 max=0.043 mdev=0.000
+ eval'time="2017-11-26''01:39:04"'min=0.043 avg=0.043 max=0.043 mdev=0.000
time="2017-11-26 01:39:04"min=0.043 avg=0.043 max=0.043 mdev=0.000
++ time='2017-11-26 01:39:04'
++ min=0.043
++ avg=0.043
++ max=0.043
++ mdev=0.000

echo${time}${min}${avg}${max}${mdev}
+ echo 2017-11-26 01:39:04 0.043 0.043 0.043 0.0002017-11-2601:39:04 0.043 0.043 0.043 0.000

長いですね。

続いてサブシェル版。

## IF CURRENT SHELL#save_IFS=${IFS} IFS=$'\n'#set -- $(ping -c1 -D localhost)#IFS=${save_IFS}eval$(IFS=$'\n'    set -- $(ping -c1-D localhost)(IFS=' []'
        set --${2}
        date -d@${2} +'time="%F %T"')(IFS=' /='eval set --\${${#}}
        echo${2}=${6}${3}=${7}${4}=${8}${5}=${9}))echo${time}${min}${avg}${max}${mdev}

set -vxで実行してみます。

eval$(IFS=$'\n'    set -- $(ping -c1-D localhost)(IFS=' []'
        set --${2}
        date -d@${2} +'time="%F %T"')(IFS=' /='eval set --\${${#}}
        echo${2}=${6}${3}=${7}${4}=${8}${5}=${9}))
++ IFS=''
+++ ping -c1-D localhost
++ set -- 'PING localhost (127.0.0.1) 56(84) bytes of data.''[1511627682.894487] 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.048 ms''--- localhost ping statistics ---''1 packets transmitted, 1 received, 0% packet loss, time 0ms''rtt min/avg/max/mdev = 0.048/0.048/0.048/0.000 ms'
++ IFS=' []'
++ set -- '' 1511627682.894487 64 bytes from localhost '(127.0.0.1):' icmp_seq=1 ttl=64 time=0.048 ms
++ date -d@1511627682.894487 '+time="%F %T"'
++ IFS=' /='
++ evalset -- '${5}'
+++ set -- rtt min avg max mdev 0.048 0.048 0.048 0.000 ms
++ echo min=0.048 avg=0.048 max=0.048 mdev=0.000
+ eval'time="2017-11-26''01:34:42"'min=0.048 avg=0.048 max=0.048 mdev=0.000
time="2017-11-26 01:34:42"min=0.048 avg=0.048 max=0.048 mdev=0.000
++ time='2017-11-26 01:34:42'
++ min=0.048
++ avg=0.048
++ max=0.048
++ mdev=0.000

echo${time}${min}${avg}${max}${mdev}
+ echo 2017-11-26 01:34:42 0.048 0.048 0.048 0.0002017-11-2601:34:42 0.048 0.048 0.048 0.000

わざわざ関数作るまでもないのでサブシェルでよさそうです。

PINGが失敗したときの例外処理

まずは PINGの終了ステータスを確認します。テストは下記の4種類としました。

  1. デフォルトゲートウェイ[0]
  2. 宛先が存在しない[1]
  3. 宛先がネットワークアドレス[2]
  4. 宛先がブロードキャストアドレス[2] ※Linuxでは -bオプションが必要
  5. 宛先が範囲外[2]
$ for i in 1 254 0 255 256; do ping -c1 -W1 192.168.1.$i >/dev/null 2>&1; echo $?; done
0
1
2
2
2

サブシェル内の pingがエラーで終了してもカレントシェルでは setの終了コードで上書きされてしまいます。サブシェル内の pingが異常終了した場合のみ位置パラメータの最後に終了コードを入れるようにして、あとから参照するようにしてみます。

save_IFS=${IFS}IFS=$'\n'set -- $(ping -c${ping_count} -D ${host} || echo$?)case${_}in
0):;;
*)exit1;;esacIFS=${save_IFS}

(あ、なんかめんどくさい…)

もう無難に PINGの出力を変数に入れることにします…。

ping_result=$(ping -c${ping_count} -D ${host}) || exit$?save_IFS=${IFS}IFS=$'\n'set -- ${ping_result}IFS=${save_IFS}

データベースの作成(SQLite

データを格納するデータベースを作成します。ここでは SQLiteを使用しますが、特に貯めておく必要がないのであれば揮発性 KVS を使うのもアリだと思います。

データベースファイル名とテーブル名は下記の通りです。

  • SQLiteファイル(データベース)名:ping.sqlite
  • SQLiteテーブル名:PING

テーブルの構成です。今回は複数ホストのデータを格納するため HOST列を用意しています。TIMESTAMPHOSTは同時に存在しないはずなので Primary key を組みます。

TIMESTAMPHOSTMINAVGMAXMDEV
2017-11-26 13:00:28192.168.1.10359.78995.716128.35124.985
2017-11-26 13:00:30192.168.1.11.3673.4288.8663.145
2017-11-26 13:00:33192.168.1.10344.49987.418122.07129.737
2017-11-26 13:00:35192.168.1.11.4031.491.5370.059
2017-11-26 13:00:38192.168.1.1035.982106.414218.36680.11
2017-11-26 13:00:40192.168.1.11.4381.5211.6710.098

SQLite3 でテーブルを作成する際、DEFAULT CURRENT_TIMESTAMPで現在時刻を自動的に挿入するようにもできるのでテーブルにレコードを追加したときの時間がよいという場合は pingコマンドでタイムスタンプを取得する必要はありません(ただし SQLiteUTCなので日本時間に合わせる場合は datetime()関数などを使う必要があります)。値を格納する列はミリ秒なので REALにしておきます。

データベースファイルを作成します。

$ sqlite3 ping.sqlite

テーブルを作成します。SQLiteの Primary key は nullが許可されているので NOT NULLにしておきます。

createtable
PING
(
    TIMESTAMP   DATENOTNULL
,   HOST        TEXT NOTNULL
,   MIN         REAL
,   AVG         REAL
,   MAX         REAL
,   MDEV        REAL
,   primary key (
        TIMESTAMP
    ,   HOST
    )
);

下記はデータを挿入する場合の例です。

insertinto
PING
values (
    '2017-11-25 18:18:00'
,   '192.168.1.1'
,   0.2
,   0.2
,   0.2
,   0.2
)

DEFAULT CURRENT_TIMESTAMPを使う場合は TIMESTAMP列に何も入れないため、列を指定してデータを挿入します。

createtable
PING
(
    TIMESTAMP   DATE PRIMARY KEY DEFAULT CURRENT_TIMESTAMP
,   HOST        TEXT
,   MIN         REAL
,   AVG         REAL
,   MAX         REAL
,   MDEV        REAL
);
insertinto PING (
    HOST
,   MIN
,   AVG
,   MAX
,   MDEV
) values (
    '192.168.1.1'
,   0.2
,   0.2
,   0.2
,   0.2
);

これでデータベースの作成は完了です。

PING実行から結果をデータベースに追加するまでをスクリプト化する

一通り準備ができたのでスクリプト化していきます。

CREATE TABLEINSERT文は予めシェルの変数に入れておきます。INSERT文は値をあとから evalで更新するようにしています。(SQLiteOracleの引数みたいなのあったかどうか覚えてません)

#!/bin/bashset-eset-u#set -x### ENVIRONMENT ###host=${1:?}ping_count=4sqlite_db_file="ping.sqlite"sqlite_table_name="PING"### SQL Query ##### CREATE TABLEsqlite_sql_create_table="\create table${sqlite_table_name}(    TIMESTAMP   DATE NOT NULL,   HOST        TEXT NOT NULL,   MIN         REAL,   AVG         REAL,   MAX         REAL,   MDEV        REAL,   primary key (        TIMESTAMP    ,   HOST    ));"## INSERT (Shell's delayed expansion)sqlite_sql_insert="\insert into${sqlite_table_name}values ('\${timestamp}',  '\${host}',   \${min},   \${avg},   \${max},   \${mdev});"if !test-e"${sqlite_db_file}"then
    sqlite3 "${sqlite_db_file}"<<!${sqlite_sql_create_table}!fiping_result=$(ping -c${ping_count} -D ${host}) || exit$?save_IFS=${IFS}IFS=$'\n'set -- ${ping_result}IFS=${save_IFS}eval$((IFS=' []'
        set --${2}
        date -d@${2} +'timestamp="%F %T"')(IFS=' /='eval set --\${${#}}
        echo${2}=${6}${3}=${7}${4}=${8}${5}=${9}))echo"\${host} (${timestamp})    MIN : ${min}    AVG : ${avg}    MAX : ${max}    MDEV: ${mdev}"evalsqlite_sql_insert=\""${sqlite_sql_insert}"\"

sqlite3 "${sqlite_db_file}"<<!${sqlite_sql_insert}!

ルータ宛と Raspberry Pi Zero 宛で試してみます。

$ watch -pn 10 './ping.sh 192.168.1.1; ./ping.sh 192.168.1.103'

Every 10.0s: ./ping.sh 192.168.1.1; ./ping.sh 192.168.1.103

192.168.1.1 (2017-11-26 21:57:11)
    MIN : 1.493
    AVG : 1.607
    MAX : 1.904
    MDEV: 0.176

192.168.1.103 (2017-11-26 21:57:14)
    MIN : 47.586
    AVG : 114.384
    MAX : 207.937
    MDEV: 61.446

データの可視化

GNUPLOTを使います。が、なんか色々忘れたのですごく簡素なグラフです。(一時期は毎日やってたのにすっかり忘れてしまいました)

$ sqlite3 -separator , ping.sqlite 'select * from PING where HOST = "192.168.1.103" order by TIMESTAMP;" > data.csv
$ gnuplot graph.gnu

途中、データが無い部分は PINGを止めていたところになりますが、死活監視としても使えそうです。

f:id:mattintosh4:20171127001613p:plain

SQLite-htmlオプションで HTML 出力もしてくれるので表はすぐに作成できます。

$ sqlite3 -html -header ping.sqlite 'select * from (select * from PING where HOST = "192.168.1.103" order by TIMESTAMP desc LIMIT 10) order by TIMESTAMP;'
TIMESTAMPHOSTMINAVGMAXMDEV
2017-11-27 00:21:36192.168.1.1035.973123.851230.96897.036
2017-11-27 00:21:46192.168.1.1037.39875.579211.86880.311
2017-11-27 00:21:56192.168.1.1036.88541.134142.87658.741
2017-11-27 00:22:06192.168.1.10379.394112.944145.74824.741
2017-11-27 00:22:16192.168.1.1033.77878.472137.30851.999
2017-11-27 00:22:26192.168.1.1035.991158.897358.325134.201
2017-11-27 00:22:36192.168.1.10333.446123.946215.25668.784
2017-11-27 00:22:46192.168.1.1035.81569.027137.48259.065
2017-11-27 00:22:56192.168.1.10333.58599.668212.55167.971
2017-11-27 00:23:06192.168.1.10335.1126.315217.0468.714

というわけで今回はここまで。

前に書いた GNUPLOTスクリプト整理しないと…。

PING の結果をひたすら Zabbix に送るだけのスクリプト

$
0
0

前回は SQLiteを使ってやってみたけど、今回は Zabbix にそのまま送る方法。

PINGコマンドの出力の時間部分だけを使う。

$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.094 ms
:

Zabbix 側には予め Zabbix トラッパーでアイテムを作成しておく。今回は「ping_now」という名前。

grepしてすぐ出力したいので stdbufを噛ませる。

#!/bin/bashPING_HOST=192.168.1.1
PING_INTERVAL=5ZABBIX_SENDER_HOST=raspberrypi
ZABBIX_SENDER_KEY=ping_now
ZABBIX_SERVER_HOST=192.168.1.200
ZABBIX_SERVER_PORT=10051

ping -i${PING_INTERVAL}${PING_HOST} | stdbuf -oLgrep-E-o'time=[0-9.]+' | while readdoeval${REPLY}test-n"${time}" || continue
    nc ${ZABBIX_SERVER_HOST}${ZABBIX_SERVER_PORT}<<!{"request": "sender data",   "data:" [        {"host": "${ZABBIX_SENDER_HOST}"        ,    "key": "${ZABBIX_SENDER_KEY}"        ,  "value": "${time}"        }    ]}!done

set -xで見るとこんな感じのが続く。

+ eval time=116
++ time=116
+ test -n 116
+ nc 192.168.1.200 10051
ZBXDZ{"response":"success","info":"processed: 1; failed: 0; total: 1; seconds spent: 0.000077"}+ read

最小/平均/最大の計算は Zabbix 側でやってくれるので楽ちん。

f:id:mattintosh4:20171204001553p:plain

コマンドラインから Chromecast に動画を送りたい

$
0
0

先日、会社用に Chromecast(第2世代)を買ってなかなか便利だなぁと思ったので自宅用にも買ってみた。

YouTubeなんかの動画を再生するには当然便利なんだけど、ローカルの動画とかを再生しようとなると Google ChromeChromium)で file:///にアクセスして Google Chromeの画面をキャスト…みたいなことになるのでプレイリストが使えなくて面倒くさい。普段は mpvを使っているので Chromecast 用のプラグインでも追加されてないかな〜と思ったけど今のところは非対応っぽい。

「じゃあ FFmpegでしょ!」で、探してみると castnowっていうのがあった。

https://github.com/xat/castnow

へぇ〜こいつはすごいぜ!って入れようと思ったら Ubuntuの npm のバージョン低かったのでまず npm の更新からやらされる…orz

環境以下の通り。

Distributor ID:  Ubuntu
Description:    Ubuntu 17.04
Release:    17.04
Codename:   zesty

普通に npm パッケージを入れる。curlwgetが無いとエラーになるので入ってなければ入れておく。

$ sudo apt-get install npm

んで npm で n というパッケージを入れて lts にしとく。n のバージョンは執筆時点では 2.1.7。

$ sudo npm install n -g
$ sudo n lts

npm をアップデートする。5.6.0 になった。

$ sudo npm update npm -g
$ npm -v
5.6.0

最後に castnow をインストールする。

$ sudo npm install castnow -g

そしてメディアファイルを指定するだけ。すばら〜♪

$ castnow video.mp4

FFmpegから FLACに変換しつつ再生とか。

$ ffmpeg -i audio.wav -f flac pipe:1 | castnow --quiet -

youtube-dl との連携もできる。マジ優秀。

$ youtube-dl -o - 'https://www.youtube.com/watch?v=ojM-qvNxgW4' | castnow --quiet -

castnow で再生しているものはスマートフォンからも操作ができる。M4A もそのまま再生できるし、標準入力の場合でも再生・停止などのコントロールできる。

f:id:mattintosh4:20171205001919p:plainf:id:mattintosh4:20171205001936p:plain

オプションはこんな感じ。

Usage: castnow [<media>, <media>, ...] [OPTIONS]

Option                   Meaning
--tomp4                  Convert file to mp4 during playback
--device <name>          The name of the Chromecast device that should be used
--address <ip>           The IP address or hostname of your Chromecast device
--subtitles <path/url>   Path or URL to an SRT or VTT file
--subtitle-scale <scale> Subtitle font scale
--subtitle-color <color> Subtitle font RGBA color
--subtitle-port <port>   Specify the port to be used for serving subtitles
--myip <ip>              Your local IP address
--quiet                  No output
--peerflix-<value>     Pass options to peerflix
--ffmpeg-<value>       Pass options to ffmpeg
--type <type>            Explicitly set the mime-type (e.g. "video/mp4")
--bypass-srt-encoding    Disable automatic UTF-8 encoding of SRT subtitles
--seek <hh:mm:ss>        Seek to the specified time on start using the format hh:mm:ss or mm:ss
--loop                   Loop over playlist, or file, forever
--shuffle                Play in random order
--recursive              List all files in directories recursively
--volume-step <step>     Step at which the volume changes. Helpful for speakers that are softer or louder than normal. Value ranges from 0 to 1 (e.g. ".05")
--localfile-port <port>  Specify the port to be used for serving a local file
--transcode-port <port>  Specify the port to be used for serving a transcoded file
--torrent-port <port>    Specify the port to be used for serving a torrented file
--stdin-port <port>      Specify the port to be used for serving a file read from stdin
--command <key1>,<key2>  Execute key command(s) (where each <key> is one of the keys listed below)
--exit                   Exit when playback begins or --command completes
--help                   This help screen

Player controls

Key                      Action
space                    Toggle between play and pause
m                        Toggle mute
t                        Toggle subtitles
up                       Volume Up
down                     Volume Down
left                     Seek backward
right                    Seek forward
n                        Next in playlist
s                        Stop playback
quit                     Quit

これは捗る!(;゚∀゚)=3ムッハー

Viewing all 878 articles
Browse latest View live