Ubuntu 18.04でLogicool MX Master 3をカスタマイズする

まえがき

HHKBに合わせてLogicool MX Master 3をぽちった。
しかしWindows/Mac以外だとデフォルトではジェスチャーボタンやモードシフト、戻る、進むボタンが使えない。
調べたらlogiopsというOSSで色々とカスタマイズが可能っぽかったので設定したときのメモを残しておく。

github.com

インストール

$ apt install cmake 
$ git clone git@github.com:PixlOne/logiops.git
$ cd logiops/
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install

libconfig.h++が存在しない

$ make
[ 88%] Built target hidpp
[ 89%] Building CXX object src/logid/CMakeFiles/logid.dir/logid.cpp.o
In file included from /home/st1t/github.com/logiops/src/logid/Device.h:6:0,
                 from /home/st1t/github.com/logiops/src/logid/Actions.h:3,
                 from /home/st1t/github.com/logiops/src/logid/util.h:4,
                 from /home/st1t/github.com/logiops/src/logid/logid.cpp:12:
/home/st1t/github.com/logiops/src/logid/Configuration.h:5:10: fatal error: libconfig.h++: そのようなファイルやディレクトリはありません
 #include <libconfig.h++>
          ^~~~~~~~~~~~~~~
compilation terminated.
src/logid/CMakeFiles/logid.dir/build.make:62: recipe for target 'src/logid/CMakeFiles/logid.dir/logid.cpp.o' failed
make[2]: *** [src/logid/CMakeFiles/logid.dir/logid.cpp.o] Error 1
CMakeFiles/Makefile2:87: recipe for target 'src/logid/CMakeFiles/logid.dir/all' failed
make[1]: *** [src/logid/CMakeFiles/logid.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2
$ 

$ sudo apt install libconfig++-dev
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  libconfig++9v5
以下のパッケージが新たにインストールされます:
  libconfig++-dev libconfig++9v5
アップグレード: 0 個、新規インストール: 2 個、削除: 0 個、保留: 0 個。
65.7 kB のアーカイブを取得する必要があります。
この操作後に追加で 304 kB のディスク容量が消費されます。
続行しますか? [Y/n] Y
取得:1 http://jp.archive.ubuntu.com/ubuntu bionic/universe amd64 libconfig++9v5 amd64 1.5-0.4 [31.6 kB]
取得:2 http://jp.archive.ubuntu.com/ubuntu bionic/universe amd64 libconfig++-dev amd64 1.5-0.4 [34.1 kB]
65.7 kB を 0秒 で取得しました (844 kB/s)   
以前に未選択のパッケージ libconfig++9v5:amd64 を選択しています。
(データベースを読み込んでいます ... 現在 389870 個のファイルとディレクトリがインストールされています。)
.../libconfig++9v5_1.5-0.4_amd64.deb を展開する準備をしています ...
libconfig++9v5:amd64 (1.5-0.4) を展開しています...
以前に未選択のパッケージ libconfig++-dev:amd64 を選択しています。
.../libconfig++-dev_1.5-0.4_amd64.deb を展開する準備をしています ...
libconfig++-dev:amd64 (1.5-0.4) を展開しています...
libconfig++9v5:amd64 (1.5-0.4) を設定しています ...
libconfig++-dev:amd64 (1.5-0.4) を設定しています ...
libc-bin (2.27-3ubuntu1) のトリガを処理しています ...
$ 
$ make
$ sudo make install
[ 88%] Built target hidpp
[100%] Built target logid
Install the project...
-- Install configuration: ""
-- Installing: /usr/local/bin/logid
-- Set runtime path of "/usr/local/bin/logid" to ""
-- Installing: /lib/systemd/system/logid.service
-- Installing: /usr/local/include/hidpp
-- Installing: /usr/local/include/hidpp/misc
-- Installing: /usr/local/include/hidpp/misc/CRC.h
-- Installing: /usr/local/include/hidpp/misc/Log.h
-- Installing: /usr/local/include/hidpp/misc/Endian.h
-- Installing: /usr/local/include/hidpp/misc/EventQueue.h
-- Installing: /usr/local/include/hidpp/hid
-- Installing: /usr/local/include/hidpp/hid/RawDevice.h
-- Installing: /usr/local/include/hidpp/hid/UsageStrings.h
-- Installing: /usr/local/include/hidpp/hid/DeviceMonitor.h
-- Installing: /usr/local/include/hidpp/hid/windows
-- Installing: /usr/local/include/hidpp/hid/windows/DeviceData.h
-- Installing: /usr/local/include/hidpp/hid/windows/error_category.h
-- Installing: /usr/local/include/hidpp/hidpp
-- Installing: /usr/local/include/hidpp/hidpp/AbstractProfileDirectoryFormat.h
-- Installing: /usr/local/include/hidpp/hidpp/AbstractMacroFormat.h
-- Installing: /usr/local/include/hidpp/hidpp/DeviceInfo.h
-- Installing: /usr/local/include/hidpp/hidpp/ProfileDirectory.h
-- Installing: /usr/local/include/hidpp/hidpp/Report.h
-- Installing: /usr/local/include/hidpp/hidpp/Dispatcher.h
-- Installing: /usr/local/include/hidpp/hidpp/SettingLookup.h
-- Installing: /usr/local/include/hidpp/hidpp/AbstractProfileFormat.h
-- Installing: /usr/local/include/hidpp/hidpp/AbstractMemoryMapping.h
-- Installing: /usr/local/include/hidpp/hidpp/defs.h
-- Installing: /usr/local/include/hidpp/hidpp/Enum.h
-- Installing: /usr/local/include/hidpp/hidpp/Profile.h
-- Installing: /usr/local/include/hidpp/hidpp/SimpleDispatcher.h
-- Installing: /usr/local/include/hidpp/hidpp/Setting.h
-- Installing: /usr/local/include/hidpp/hidpp/Macro.h
-- Installing: /usr/local/include/hidpp/hidpp/Address.h
-- Installing: /usr/local/include/hidpp/hidpp/DispatcherThread.h
-- Installing: /usr/local/include/hidpp/hidpp/Device.h
-- Installing: /usr/local/include/hidpp/hidpp/ids.h
-- Installing: /usr/local/include/hidpp/hidpp/Field.h
-- Installing: /usr/local/include/hidpp/hidpp10
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileFormatG9.h
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileFormatG500.h
-- Installing: /usr/local/include/hidpp/hidpp10/DeviceInfo.h
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileFormatCommon.h
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileFormat.h
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileDirectoryFormat.h
-- Installing: /usr/local/include/hidpp/hidpp10/RAMMapping.h
-- Installing: /usr/local/include/hidpp/hidpp10/IMemory.h
-- Installing: /usr/local/include/hidpp/hidpp10/MacroFormat.h
-- Installing: /usr/local/include/hidpp/hidpp10/IResolution.h
-- Installing: /usr/local/include/hidpp/hidpp10/IProfile.h
-- Installing: /usr/local/include/hidpp/hidpp10/Sensor.h
-- Installing: /usr/local/include/hidpp/hidpp10/defs.h
-- Installing: /usr/local/include/hidpp/hidpp10/IReceiver.h
-- Installing: /usr/local/include/hidpp/hidpp10/MemoryMapping.h
-- Installing: /usr/local/include/hidpp/hidpp10/ProfileFormatG700.h
-- Installing: /usr/local/include/hidpp/hidpp10/IIndividualFeatures.h
-- Installing: /usr/local/include/hidpp/hidpp10/Device.h
-- Installing: /usr/local/include/hidpp/hidpp10/Error.h
-- Installing: /usr/local/include/hidpp/hidpp10/WriteError.h
-- Installing: /usr/local/include/hidpp/hidpp20
-- Installing: /usr/local/include/hidpp/hidpp20/IBatteryLevelStatus.h
-- Installing: /usr/local/include/hidpp/hidpp20/IReset.h
-- Installing: /usr/local/include/hidpp/hidpp20/ProfileFormat.h
-- Installing: /usr/local/include/hidpp/hidpp20/IWirelessDeviceStatus.h
-- Installing: /usr/local/include/hidpp/hidpp20/ProfileDirectoryFormat.h
-- Installing: /usr/local/include/hidpp/hidpp20/MacroFormat.h
-- Installing: /usr/local/include/hidpp/hidpp20/IReprogControls.h
-- Installing: /usr/local/include/hidpp/hidpp20/UnsupportedFeature.h
-- Installing: /usr/local/include/hidpp/hidpp20/defs.h
-- Installing: /usr/local/include/hidpp/hidpp20/MemoryMapping.h
-- Installing: /usr/local/include/hidpp/hidpp20/IRoot.h
-- Installing: /usr/local/include/hidpp/hidpp20/FeatureInterface.h
-- Installing: /usr/local/include/hidpp/hidpp20/IHiresScroll.h
-- Installing: /usr/local/include/hidpp/hidpp20/IFeatureSet.h
-- Installing: /usr/local/include/hidpp/hidpp20/ISmartShift.h
-- Installing: /usr/local/include/hidpp/hidpp20/ITouchpadRawXY.h
-- Installing: /usr/local/include/hidpp/hidpp20/IAdjustableDPI.h
-- Installing: /usr/local/include/hidpp/hidpp20/Device.h
-- Installing: /usr/local/include/hidpp/hidpp20/Error.h
-- Installing: /usr/local/include/hidpp/hidpp20/IOnboardProfiles.h
-- Installing: /usr/local/include/hidpp/hidpp20/IMouseButtonSpy.h
-- Installing: /usr/local/include/hidpp/hidpp20/ILEDControl.h
-- Installing: /usr/local/lib/libhidpp.so
$
$ sudo systemctl enable logid

libhidpp.soがない

$ /usr/local/bin/logid --help
/usr/local/bin/logid: error while loading shared libraries: libhidpp.so: cannot open shared object file: No such file or directory

github.com

try symlinking /usr/lib/libhidpp.so to /usr/local/lib/libhidpp.so

って書いてあるが、

$ ls -la /usr/local/lib/libhidpp.so
-rw-r--r-- 1 root root 2407952  3月  9 20:14 /usr/local/lib/libhidpp.so
$ 

既にある。 実際どこを見に行ってるか確認すると、/usr/lib/libhidpp.soっぽい

$ strace -e trace=openat logid 2>&1 | grep libhidpp.so
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/tls/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/tls/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/tls/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/tls/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/tls/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/tls/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/tls/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/tls/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/tls/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/haswell/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/haswell/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libhidpp.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
logid: error while loading shared libraries: libhidpp.so: cannot open shared object file: No such file or directory
$ 
$ sudo ln -s /usr/local/lib/libhidpp.so /usr/lib/libhidpp.so
$ logid --help
Usage: logid [options]
Possible options are:
    -v,--verbose [level]       Set log level to debug/info/warn/error (leave blank for debug)
    -c,--config [file path]    Change config file from default at /etc/logid.cfg
    -h,--help                  Print this message.
$ 

設定ファイルを用意する

$ sudo vim /etc/logid.cfg
devices: (
{
    name: "MX Master 3";
    smartshift:
    {
        on: false;
        threshold: 30;
    };
    hiresscroll:
    {
        hires: false;
        invert: false;
        target: false;
    };
    dpi: 1000;

    buttons: (
        {
            # 戻るボタン
            cid: 0x53;
            action =
            {
                type: "Keypress";
                keys: ["KEY_LEFTALT","KEY_LEFT"];
            };
        },
        {
            # 進むボタン
            cid: 0x56;
            action =
            {
                type: "Keypress";
                keys: ["KEY_LEFTALT","KEY_RIGHT"];
            };
        },
        {
            # ジェスチャーボタン
            cid: 0xc3;
            action =
            {
                type: "Gestures";
                gestures: (
                    {
                        direction: "Up";
                        mode: "OnRelease";
                        action =
                        {
                            type: "Keypress";
                            keys: ["KEY_LEFTALT","KEY_LEFTCTRL","KEY_UP"];
                        };
                    },
                    {
                        direction: "Down";
                        mode: "OnRelease";
                        action =
                        {
                            type: "Keypress";
                            keys: ["KEY_LEFTALT","KEY_LEFTCTRL","KEY_DOWN"];
                        };
                    },
                    {
                        direction: "Left";
                        mode: "OnRelease";
                        action =
                        {
                            type: "Keypress";
                            keys: ["KEY_LEFTSHIFT","KEY_LEFTALT","KEY_LEFTCTRL","KEY_DOWN"];
                        };
                    },
                    {
                        direction: "Right";
                        mode: "OnRelease";
                        action =
                        {
                            type: "Keypress";
                            keys: ["KEY_LEFTSHIFT","KEY_LEFTALT","KEY_LEFTCTRL","KEY_UP"];
                        }
                    },
                    {
                        direction: "None";
                        mode: "OnRelease";
                        action =
                        {
                            type: "Keypress";
                            keys: ["KEY_LEFTCTRL","KEY_W"];
                        }
                    }
                );
            };
        },
        {
            # SmartShiftボタン
            cid: 0xc4;
            action =
            {
                type = "ToggleSmartshift";
            };
        }
    );
}
);

転職ドラフトの自己推薦を使って転職しました

まえがき

こちらの記事は転職ドラフト体験談投稿キャンペーンに参加しています。

job-draft.jp

転職してから1年以上経過したのでHHKB買うためにも流石に書いても良いかなーと思って書いています。
転職したばかりだと客観的に書けないことも多いので💦

私の場合は、2018年の年末に転職ドラフトの指名制度ではなく自己推薦を使って転職しました。

転職ドラフトを使った経緯

転職は今回が初めてではなく、現職で5社目になります。

SIer ->ソシャゲ -> ISP -> オンライン英会話 -> 現職

現職でこそDevOpsという位置づけで働いているのですが、今までの職種は一貫してインフラになります。
ソシャゲ、ISPへの転職時には転職エージェント、オンライン英会話はSIer時代の先輩に誘っていただきました🙏

元々転職ドラフトは年収提示でスカウトというのが面白くて初期から(ジンバブエドルのプレゼント企画があったとき)登録していました。
ただ、頂いたメッセージが汎用的なメッセージで辞退させていただくことが多かったです。

逆に、なぜ指名してくださったのか明確にお話を頂いた方には極力会いに行っていました。
今回、自己推薦と合わせて指名を頂いた会社さんは社名こそ出せないのですが、
とてもおもしろい会社さんだったので正直自己推薦のやつがなければ選考を進めていただいていたと思います。

自己推薦を使ったのは、たまたま現職の募集要項が自分にマッチしていそうだったからです。

  • 今までやっていたことの経験を活かせそうだった
    • インフラのコード化
    • CI/CDの環境整備
  • もっとコードを書きたい
    • 今後のキャリアを考えた時にアプリケーションレイヤに近いところももっとやりたかった
  • 自己推薦機能を使った転職キャンペーンをやっていた
  • ぐぐったらCTOが強そうだった

実は話を聞きに行ったときは、CTOと話をしていたのですが本当に話を聞きに行っただけだったので、
今すぐ何がなんでも転職するつもりはなく、話を聞いてみたかっただけです。とその場で伝えていました。
カジュアル面談が本当にカジュアルに出来ていて良いなーと思ったのも一つポイントだったかもしれません。

転職ドラフトを使ってよかったこと

  • 年収について事前に知った上で面接に望むことが出来る
    • 大体どこの会社でも年収の提示は最終面接か、内定後に連絡が来ることが多いのでそこで折り合いがつかないと時間の無駄になってしまう
  • 自分と似た人がどういうオファーをどのくらいの年収でオファーを受けているのか知ることが出来る
  • 企業のルール違反をきちんと調査して公表するので運営に信用感がある

転職ドラフト利用時や転職する時に悩ましいこと

  • 自分に合いそうな企業を見つけることが難しい
    • 直近の転職を考えていなくても常に良さそうな会社があればメモするようにはしてる
    • トリガーは基本的にTwitter
  • 企業ごとの特色がわかりづらいのでラブコールがだしづらい(かも)
  • 自分と同じ職種の方がどんな感じか見ようと思っても職種別の検索機能がない
  • 転職エージェントと違ってキャリアや面接対策の相談とかできないので、転職経験者向け感はある
    • 私は相談したことないですが、周りは相談したいという方も見ます

さいごに

書くこともないので転職を何度かしてきて一緒に働くうえで大事だなーと実感したことを書いておきます。
自分の場合は面接受ける時とかにこの辺に絡んだ質問したりもします。

  • 質の良いレビュー
    • 質の良いレビューはレベルアップの一番の近道。Xさんだからよし!はみんなを不幸にする
  • 人は忘れる生き物。同じ質問をされても嫌な顔せずきちんと答える
  • 障害は必ず発生するもの。大事なのはフールプルーフな再発防止策
    • ダブルチェックをトリプルチェックします!は再発防止策ではない
  • 障害対応、パフォーマンスチューニングでも「仮説」と「検証」は必ずセット。仮説なくして検証にならず
    • なんかよくわからんけど、ググったらこの設定が出てきたので設定して解決しました、よし!は障害対応でも二次障害につながるから極力避ける
  • わからないことははっきりわからないと言う
    • あとからググるのも手ではあるけど、それでもわからなかったとき困るのでなるべくその場で確認する
  • パケットの気持ちになる
  • 転職こわくない
  • 5000兆円ほしい

追記@2020-03-06

Amazonギフト券がもう届いた、めっちゃ仕事早い、ありがとうございます!!!
1,2週間くらいかかるかな〜?と思ってたら1営業日だった!
これでHHKB買える

CodeBuildでDocker imageの作成をするときにDockerfile内の処理へIAM Roleを引き渡す方法

例えば、Dockerfile内のコマンドでS3にファイルをアップロードする処理が挟まっていた場合。
Dockerfile内に ARG AWS_CONTAINER_CREDENTIALS_RELATIVE_URIとして受け取れるようにしてやれば良い。

https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/troubleshooting.html#troubleshooting-versions

ビルド環境で Docker コンテナを実行する必要があり、コンテナが AWS 認証情報を必要とする場合は、ビルド環境からコンテナに資格情報を渡す必要があります。
buildspec ファイルに、次のような Docker run コマンドを含めます。
この例では、aws s3 ls コマンドを使用して使用可能な Amazon S3 バケットを一覧表示しています。-e オプションは、コンテナが AWS 認証情報にアクセスするために必要な環境変数を渡します。

ruby 2.7.0入れようとしてopensslのインストール時にldエラー起きたときのメモ

binutilsを消して解決

anatofuz.hatenablog.com

$ rbenv install 2.7.0
Downloading openssl-1.1.1d.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
Installing openssl-1.1.1d...

BUILD FAILED (OS X 10.14.6 using ruby-build 20191225)

Inspect or clean up the working tree at /var/folders/r5/_282n9zn4lg2gb29mtz39_8r0000gn/T/ruby-build.20191227155826.29602.YeYTvQ
Results logged to /var/folders/r5/_282n9zn4lg2gb29mtz39_8r0000gn/T/ruby-build.20191227155826.29602.log

Last 10 log lines:
      _s_server_main in s_server.o
  "_verify_stateless_cookie_callback", referenced from:
      _s_server_main in s_server.o
  "_wait_for_async", referenced from:
      _s_client_main in s_client.o
      _sv_body in s_server.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [apps/openssl] Error 1
make: *** [all] Error 2
$ 
$ tail -n 100 /var/folders/r5/_282n9zn4lg2gb29mtz39_8r0000gn/T/ruby-build.20191227155826.29602.log 
  "_save_serial", referenced from:
      _ca_main in ca.o
      _x509_main in x509.o
  "_set_cert_ex", referenced from:
      _ca_main in ca.o
      _req_main in req.o
      _x509_main in x509.o
  "_set_cert_key_stuff", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_set_cert_stuff", referenced from:
      _s_time_main in s_time.o
  "_set_cert_times", referenced from:
      _do_body in ca.o
      _req_main in req.o
      _x509_main in x509.o
  "_set_ext_copy", referenced from:
      _ca_main in ca.o
  "_set_keylog_file", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_set_nameopt", referenced from:
      _ca_main in ca.o
      _crl_main in crl.o
      _req_main in req.o
      _s_client_main in s_client.o
      _s_server_main in s_server.o
      _s_time_main in s_time.o
      _verify_main in verify.o
      ...
  "_setup_engine", referenced from:
      _ca_main in ca.o
      _cms_main in cms.o
      _dgst_main in dgst.o
      _dhparam_main in dhparam.o
      _dsa_main in dsa.o
      _dsaparam_main in dsaparam.o
      _ec_main in ec.o
      ...
  "_setup_ui_method", referenced from:
      _main in openssl.o
  "_setup_verify", referenced from:
      _cms_main in cms.o
      _crl_main in crl.o
      _ocsp_main in ocsp.o
      _pkcs12_main in pkcs12.o
      _smime_main in smime.o
      _verify_main in verify.o
  "_ssl_ctx_add_crls", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_ssl_ctx_security_debug", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_ssl_ctx_set_excert", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_ssl_excert_free", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_ssl_load_stores", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_ssl_print_groups", referenced from:
      _www_body in s_server.o
      _print_connection_info in s_server.o
  "_ssl_print_point_formats", referenced from:
      _print_connection_info in s_server.o
  "_ssl_print_sigalgs", referenced from:
      _print_stuff in s_client.o
      _www_body in s_server.o
      _print_connection_info in s_server.o
  "_ssl_print_tmp_key", referenced from:
      _print_stuff in s_client.o
  "_store_setup_crl_download", referenced from:
      _verify_main in verify.o
  "_tlsext_cb", referenced from:
      _s_client_main in s_client.o
      _rev_body in s_server.o
      _www_body in s_server.o
      _sv_body in s_server.o
  "_verify_args", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
      _s_time_main in s_time.o
      _doConnection in s_time.o
  "_verify_callback", referenced from:
      _s_client_main in s_client.o
      _s_server_main in s_server.o
  "_verify_cookie_callback", referenced from:
      _s_server_main in s_server.o
  "_verify_stateless_cookie_callback", referenced from:
      _s_server_main in s_server.o
  "_wait_for_async", referenced from:
      _s_client_main in s_client.o
      _sv_body in s_server.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [apps/openssl] Error 1
make: *** [all] Error 2
$ 
$ brew uninstall binutils
Uninstalling /usr/local/Cellar/binutils/2.32... (134 files, 167.5MB)
$ 
$ rbenv install 2.7.0
Downloading openssl-1.1.1d.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2
Installing openssl-1.1.1d...
Installed openssl-1.1.1d to /Users/st1t/.rbenv/versions/2.7.0

Downloading ruby-2.7.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2
Installing ruby-2.7.0...
ruby-build: using readline from homebrew
Installed ruby-2.7.0 to /Users/st1t/.rbenv/versions/2.7.0

$ 

Elastic Stack 7.1をコンテナで適当に触ってる

Elastic ON Tokyoでセッションを聞きながら手元でコンテナ起ち上げて最近のElastic Stackがどんな感じなのかお試し中。

docker-compose.yml

version: '2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1
    environment:
      - discovery.type=single-node
      - node.name=es01
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - ./mount/es01/usr/share/elasticsearch/data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - esnet
  kibana:
    image: docker.elastic.co/kibana/kibana:7.1.1
    environment:
      ELASTICSEARCH_HOSTS: http://es01:9200
    ports:
      - "5601:5601"
    networks:
      - esnet
    depends_on:
      - es01
networks:
  esnet:

動かす

$ docker-compose up

Machine LearningのImport dataでNginxのテストデータを流す

# Elasticでtestデータが置いてあるから落としとく
$ wget https://raw.githubusercontent.com/elastic/examples/master/Common%20Data%20Formats/nginx_logs/nginx_logs
# ログの日時が古いから2019年にしとく@BSD版(Mac)のsedオプション
$ sed -i '' 's%/2015:%/2019:%g' nginx_logs 

あとはWEBから流すだけ

open http://localhost:5601/app/ml#/filedatavisualizer?_g=()

f:id:st1t:20190530150823p:plain

Mac使いな自分がThinkPad T490にUbuntu 18.04を入れたPCに移行したときにやったこと

まえがき

タイトルの通り、ThinkPad T490が届いたのでWindow10とデュアルブートする形でUbuntu18.04を入れてそっちをメインにしてみました。 今まではMacユーザだったので、なるべく違和感ない操作にするためにも変更したことをメモしておきます。

画面の解像度

解像度を2048 * 1152(16:9)に変更

今回、WQHDを購入したが、そのままだと文字が小さすぎて辛いので、解像度を2048 * 1152(16:9)に変更した。 Windowsロゴキー-> 設定 -> デバイス -> ディスプレイ


起動時トラブル

WaylandEnableをfalseにする

cat /etc/gdm3/custom.conf
WaylandEnable=false

トラックパッド

ブラウザで指でブラウザバックさせる

github.com

基本的にはINSTALLATIONに従ってインストールしていくだけ。 設定は以下の通り。

$ cat ~/.config/libinput-gestures.conf 
# ブラウザの戻る・進む
gesture swipe left      4 xdotool key alt+Right
gesture swipe right     4 xdotool key alt+Left
# ワークスペースの切り替え
gesture swipe up        3 xdotool key super+Page_Up
gesture swipe down      3 xdotool key super+Page_Down
$
$ libinput-getures-setup restart

キーボード

CapsLockをCtrlにする

gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:nocaps']"

Tweaks

キーボードとマウス -> 追加のレイアウトオプション -> Alt/Win キーの動作 -> Meta is mapped to Win

キーバインドをEmacsっぽくする

sudo apt install gnome-tweak-tool

日本語入力モード

Mozcだけにして、Mozc内の入力モードをCtrl+Spaceで切り替えられるようにしていく

do-you-linux.com


マウス

qiita.com

※imwheelの自動起動はsystemdだとDISPLAY変数周りでめんどうなので、OSのアクティビティの検索窓から「自動起動するアプリケーションの設定」からコマンドを登録したらいけた。


ターミナル

ホームディレクトリが日本語表示されるのを英語にする

$ LANG=C xdg-user-dirs-gtk-update

open command

$ sudo unlink /bin/open
$ sudo ln -s /usr/bin/xdg-open /bin/open

Google Chrome

検索結果をvim likeに移動できるようにするやつ

chrome.google.com

Backspaceでブラウザバックできるようにするやつ chrome.google.com

Google Custom Search APIを叩いてみた

まえがき

ふーむ、と思ってちょっと調べてみました。
Googleのことだから多分検索用のAPI用意されてるだろうし、そこにデータ入ってないかな?がスタートです。

Google Custom Search APIについて

調べてみたら、Google Custom Search JSON APIというものがあるみたいです。

qiita.com

手順については上記ブログで記載があるので割愛します。
一箇所だけ、get_search_response.py内の

def getSearchResponse(project_id, keyword_id, keyword):

は呼び出し元がtarget_keywordだけしか使って使っていなさそうだったので、それ以外の引数を消しました。

def getSearchResponse(keyword):

取れたデータについて

target_keywordを自分のブログのURLを指定してみました。

    target_keyword = 'https://www.st1t.com/entry/2018/12/27/174532'
$ jq . data/response/response_20181228.json 
{
  "snapshot_ymd": "20181228",
  "snapshot_timestamp": "2018/12/28 20:34:11",
  "response": [
    {
      "kind": "customsearch#search",
      "url": {
        "type": "application/json",
        "template": "https://www.googleapis.com/customsearch/v1?q={searchTerms}&num={count?}&start={startIndex?}&lr={language?}&safe={safe?}&cx={cx?}&sort={sort?}&filter={filter?}&gl={gl?}&cr={cr?}&googlehost={googleHost?}&c2coff={disableCnTwTranslation?}&hq={hq?}&hl={hl?}&siteSearch={siteSearch?}&siteSearchFilter={siteSearchFilter?}&exactTerms={exactTerms?}&excludeTerms={excludeTerms?}&linkSite={linkSite?}&orTerms={orTerms?}&relatedSite={relatedSite?}&dateRestrict={dateRestrict?}&lowRange={lowRange?}&highRange={highRange?}&searchType={searchType}&fileType={fileType?}&rights={rights?}&imgSize={imgSize?}&imgType={imgType?}&imgColorType={imgColorType?}&imgDominantColor={imgDominantColor?}&alt=json"
      },
      "queries": {
        "request": [
          {
            "title": "Google Custom Search - https://www.st1t.com/entry/2018/12/27/174532",
            "totalResults": "1",
            "searchTerms": "https://www.st1t.com/entry/2018/12/27/174532",
            "count": 1,
            "startIndex": 1,
            "language": "lang_ja",
            "inputEncoding": "utf8",
            "outputEncoding": "utf8",
            "safe": "off",
            "cx": "000541688366129963034:bisdpfb8q-4"
          }
        ]
      },
      "context": {
        "title": "カスタム検索エンジン"
      },
      "searchInformation": {
        "searchTime": 0.142453,
        "formattedSearchTime": "0.14",
        "totalResults": "1",
        "formattedTotalResults": "1"
      },
      "items": [
        {
          "kind": "customsearch#result",
          "title": "検索システムを作る上で役立つ本 - infra.log",
          "htmlTitle": "検索システムを作る上で役立つ本 - infra.log",
          "link": "https://www.st1t.com/entry/2018/12/27/174532",
          "displayLink": "www.st1t.com",
          "snippet": "1 日前 ... ... 初めて見たくらい良書だと思いました。 買うのが不安な方は立ち読みだけでもいい\nのでまずは見てもらうといいのかなーと思います。 https://www.kindaikagaku.co.jp/\nimg/book/ · https://www.kindaikagaku.co.jp/information/kd0577.htm ...",
          "htmlSnippet": "1 日前 <b>...</b> ... 初めて見たくらい良書だと思いました。 買うのが不安な方は立ち読みだけでもいい<br>\nのでまずは見てもらうといいのかなーと思います。 <b>https</b>://www.kindaikagaku.co.jp/<br>\nimg/book/ &middot; <b>https</b>://www.kindaikagaku.co.jp/information/kd0577.htm&nbsp;...",
          "cacheId": "61D4dXdaVo0J",
          "formattedUrl": "https://www.st1t.com/entry/2018/12/27/174532",
          "htmlFormattedUrl": "<b>https</b>://www.<b>st1t.com/entry</b>/<b>2018/12/27/174532</b>",
          "pagemap": {
            "cse_thumbnail": [
              {
                "width": "170",
                "height": "216",
                "src": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcShrcLWXuO7jeYzIprdKhrVSMarpKuAKRZZyzQUgBSu4_Dm_JVH-wAukx8"
              }
            ],
            "metatags": [
              {
                "viewport": "width=device-width, initial-scale=1.0",
                "og:title": "検索システムを作る上で役立つ本 - infra.log",
                "og:type": "article",
                "og:url": "https://www.st1t.com/entry/2018/12/27/174532",
                "og:image": "https://www.kindaikagaku.co.jp/img/book/KD0577-170.jpg",
                "og:description": "まえがき 最近Elasticsearchを触る機会が増えつつあるのですが、 そもそも検索を行う際に何をどうしたら良いのか全くわからんって時のためおすすめの書籍をいくつか紹介したいと思います。 また、達人出版社さんから冬休み合同フェアというのが開催されており、 こちらだと電子書籍が半額で買えるのでオススメです。 tatsu-zine.com 初級編 Elasticsearch実践ガイド book.impress.co.jp 全文検索を行おうと思ったら大体最近の流れはElasticsearchにいきつくパターンが多いかと思います。 ただ、公式のドキュメントは英語だったり、そもそも全文検索の界隈で当…",
                "og:site_name": "infra.log",
                "article:published_time": "1545900332",
                "twitter:card": "summary_large_image",
                "twitter:image": "https://www.kindaikagaku.co.jp/img/book/KD0577-170.jpg",
                "twitter:title": "検索システムを作る上で役立つ本 - infra.log",
                "twitter:description": "まえがき 最近Elasticsearchを触る機会が増えつつあるのですが、 そもそも検索を行う際に何をどうしたら良いのか全くわからんって時のためおすすめの書籍をいくつか紹介したいと思います。 また、達人出版社さんから冬休み合同フェアというのが開催されており、 こちらだと電子書籍が半額で買えるのでオススメです。 tats…",
                "twitter:app:name:iphone": "はてなブログアプリ",
                "twitter:app:id:iphone": "583299321",
                "twitter:app:url:iphone": "hatenablog:///open?uri=https%3A%2F%2Fwww.st1t.com%2Fentry%2F2018%2F12%2F27%2F174532",
                "twitter:site": "@st_1t"
              }
            ],
            "article": [
              {
                "name": "検索システムを作る上で役立つ本 - infra.log",
                "image": "https://www.kindaikagaku.co.jp/img/book/KD0577-170.jpg"
              }
            ],
            "cse_image": [
              {
                "src": "https://www.kindaikagaku.co.jp/img/book/KD0577-170.jpg"
              }
            ]
          }
        }
      ]
    }
  ]
}
$ 

jqで日付とタイトルを抜き出す

article:published_timeはUNIXタイムなので人が見るときは変換したほうが良いかも。

$ jq '.response[].items[].pagemap.metatags[]["og:title","article:published_time"]' data/response/response_20181228.json 
"検索システムを作る上で役立つ本 - infra.log"
"1545900332"

あとがき

というわけでさくっとやってみたのですが、まだ課題があります。
SEOは門外漢すぎて知らなかったのですが、
このarticle:published_timeはOpen Graph Protocol(OGP)というSEO対策のためにホームページ作成者がよしなにいれこむものみたいでした。
(なるほど、ブログにリンク貼ると以下のように画像と説明がでるのもOGPのおかげだったんですね。。。)

www.asahi-net.or.jp

なので、ものによってはやはりmetaタグがなかったり、article:published_time自体がなかったりしました。
Googleが初めてIndexしたタイミングの日時が取得できることを密かに期待していたのですが、残念💧