あんパン

こしあん派

iPhoneとRaspberry PiでWOLのパケットを送ってWindows端末を起動する

最近iPhone 14 Pro Maxを購入した。写真を撮るためだとかマンガを読むためだとかいろいろ理由をつけて買ったが実のところRemote DesktopでWindowsに繋いで適度なサイズの画面でノベルゲームをしたかったのだった。

Remote Desktopで接続することはできたが、しばらく放置しているとスリープ状態になってしまい、わざわざ机の下にあるWindows端末の電源ボタンを押さないといけない。布団でぬくぬくゲームをしようというときにわざわざ出るのは面倒なのでiPhoneから起動できるようにした。いまも昔もこういう操作をシュッとやるならWake-on-LANと相場が決まっている。この記事はWake-on-LANをiPhoneからやろうという話。

iOS向けのアプリとしてWOLのマジックパケットを送出できるものはあるけれど、得体の知れないものを入れるのはやや抵抗がある。最近のiOSには純正のショートカットアプリがあり、SSHで任意のコマンドを発行できるので、これを利用してRaspberry Pi上からマジックパケットを送出するのがよかろうと考えた。いまやRaspberry Piはどこにも在庫がないけど、手元にいくつか余っているのでこれを利用した。Raspberry PiでなくてもNano PiやOrange Piとかでもだいたい同じことができるはず。

WOLの設定

Windows上で、まずはIPをDHCPではなく固定にしておく。続いてデバイスマネージャから利用している有線LANのインターフェースのプロパティを開き、WOLを有効にしておく。加えて、UEFIの設定でもWOLを有効にする。このあたりはマザーボードによって違いそう。最後にインターフェースのMACアドレスを控えておく。マジックパケットはこのMACアドレス宛に送ることになる。

この状態で動くかどうかを確認しておくと良い。Arch Linuxであれば wol コマンドでマジックパケットを送出できる。

$ wol MAC_ADDR

スリープや休止状態であれば復帰できたが、完全に止めた状態から起動することはできなかった。そういうものだった気がする。

Raspberry Piの初期設定

masawada.hatenablog.jp

以前書いた通りRaspberry Pi用のSDカードはRaspberry Pi Imagerで作ることができる。最近はSSH用のパスワードの設定などもできて便利。できあがったSDカードの / 直下に touch ssh などでsshという名前の空ファイルを作っておけば立ち上げ時にsshdも起動する。

Raspberry Piは起動するとDHCPでIPを取得しにいくので、 arp-scan でこれを確認してsshする。

$ sudo arp-scan -l
Interface: eno1, type: EN10MB, MAC: **:**:**:**:**:**, IPv4: 192.168.0.101
Starting arp-scan 1.9.8 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.0.1     **:**:**:**:**:**       YAMAHA CORPORATION
192.168.0.10    **:**:**:**:**:**       ASRock Incorporation
192.168.0.102   **:**:**:**:**:**       Raspberry Pi Foundation

こういう調子。このIPにSSHで接続して、さらにIPを固定にする。 /etc/dhcpcd.conf を編集しつつ再起動すればOK。最後にWOLのマジックパケットを送出するアプリケーションを入れておく。

$ sudo apt install wakeonlan

iOSの設定

ショートカットアプリを開いて新規ショートカットを作成し、以下のように設定を行う。

MACアドレスやホストなどは環境に応じた値を入れる

SSH用の鍵はiOS側が生成してくれるので、公開鍵をコピーしてRaspberry Pi側に登録しておく。

あとはこのショートカットを実行すれば、Windowsが起動する。

SSHで任意のコマンドを実行できるので応用の幅が広くて便利そう。

スペース区切りの文字列を2つずつ取って表示

usbhid-dumpでdumpしたUSBのreport descriptorを見るとき、2byteで1セットになることが多い(当然例外はめっちゃあるが…)ので一旦2項目ずつに整理して見てみたい。つまり

003:007:000:DESCRIPTOR         1668742987.009398
 05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
 75 01 95 08 81 02 75 08 95 01 81 01 05 08 19 01
 29 05 75 01 95 05 91 02 75 03 95 01 91 01 05 07
 19 00 2A FF 00 15 00 26 FF 00 75 08 95 06 81 00
 C0

これを

05 01
09 06
A1 01
05 07
...
75 08
95 06
81 00
C0

こうしたい。間違ってるところはあとで修正する前提。Rubyだと近いことを Enumerable#each_slice でできる。

シュッとワンライナー書けないかな〜と思っていたところ、xargsでそれっぽいことができそうだった。05 01 09 ... をクリップボードに入れておいて

$ xsel -ob | sed 's/ /\n/g' | grep -v '^$' | xargs -L2 echo
05 01
09 06
A1 01
05 07
...
75 08
95 06
81 00
C0

という調子。xargsの -L オプションを指定すると一回で複数の引数を取って展開してくれるので、単純にこれをechoする。普段便利に使ってるコマンドでも意外と知らないオプションがある。


そしてこの記事を書き終えた後に

$ sudo usbhid-dump -e descriptor -a ***:*** | grep -v : | xxd -r -p | hidrd-convert -o code
0x05, 0x01,         /*  Usage Page (Desktop),               */
0x09, 0x02,         /*  Usage (Mouse),                      */
0xA1, 0x01,         /*  Collection (Application),           */
0x09, 0x01,         /*      Usage (Pointer),                */

で一番やりたかったことができるのを知るのであった……

ちょっとした計算をしてクリップボードに入れたいとき

どうやってますか?

案A: Google検索して結果をコピー

このフォームからコピー。ずっとChrome開いてるので導線としては近いけどやや手間。

案B: ランチャーを利用

macOSにおいてはAlfredであれば計算してreturnを押せばコピーできたはず。

Linuxにおいてはrofiを使ってるならrofi-calcを使うとよさそう。

github.com

The following example copies the result to the clipboard upon pressing the key combination defined by -kb-accept-custom (by default Control+Return). NOTE: {result} should be quoted since it may contain characters that your shell would otherwise interpret: rofi -show calc -modi calc -no-show-match -no-sort -calc-command "echo -n '{result}' | xclip" https://github.com/svenstaro/rofi-calc#advanced-usage

が、combiで起動するとうまくいかなかったりしてややムズい。calc単体で立ち上げるショートカットを作るのはやや大仰すぎる。

Windowsはあんまり使ってないのでよく分からない。

案C: 適当なワンライナーを利用する

$ perl -e 'print 100 * 200' | tee >(pbcopy); echo

Linuxならクリップボードに入れる部分は >(xsel -ib) とかかな。

自分の場合はこれをさらにラップして

#!/bin/bash

EXPR="$@"; perl -e "print $EXPR" | tee >(xsel -ib); echo;

こういう感じで p みたいな名前で保存して実行権限をつけておいて

$ p '100 * 200'
20000

みたいにできている(が、あんまり使ってない……)。* は素のまま書いてしまうとシェル側で展開されてしまうので '' で囲う必要がありやや面倒。


  • 導線が近い
  • ツールとして使いやすい
    • とにかく計算式だけ入れてreturn押したらなんとかなる

くらいが求められていそうだけど、現状の手札はどれも一長一短でもうすこしいい感じになりたい。オススメ手法を募集しています。

YAMAHAルータの設定をAnsibleで管理する

新しめのYAMAHA製ルータはAnsibleで設定を管理することができる。

www.rtpro.yamaha.co.jp

手順に書いてある通り

  • SSH用のユーザを用意する
  • SSH機能を有効にする
  • Ansibleのコードを書いて適用する

の順序で適用できる。

素朴な構成であればサンプルと同じ形で実現可能だけれど、複数環境や複数拠点のconfigを共通化したいとなると階層化して管理したくなる。実際、自分は自宅と実家でRTX830を運用していてやや困った。なので、具体的にどのような構成にしたのかを記しておく。ほとんどAnsibleの話なのでAnsibleに慣れている人にはいまさらな話題だと思う*1

ディレクトリ構成とinventories

サンプルだと各ファイルをフラットに配置しているけど、環境や拠点が複数ある場合はもうすこし複雑な構成をとりたくなるはず。自分はAnsible公式ドキュメントのベストプラクティス*2に則ってディレクトリ構成を組むことにした。

$ tree
.
├── inventories
│   └── test
│       ├── group_vars
│       │   ├── network_noop.yml
│       │   └── network_test.yml
│       ├── hosts.yml
│       └── host_vars
│           └── hostname.yml.example
├── README.md
├── roles
│   ├── router
│   │   └── tasks
│   │       ├── general.yml
│   │       ├── lan.yml
│   │       ├── main.yml
│   │       ├── ntp.yml
│   │       └── upstream.yml
│   └── save_configuration
│       └── tasks
│           └── main.yml
└── router.yml

inventories/ 以下に環境ごとのディレクトリを用意し、 hosts.yml にホストの情報と拠点の情報を書いておく。hosts.yml の中身は以下のような雰囲気。

---
# roles
router:
  hosts:
    router_test:
      ansible_host: 192.168.0.1
      ansible_network_os: yamaha_network.rtx.rtx
    router_noop:
      ansible_host: 192.168.16.1
      ansible_network_os: yamaha_network.rtx.rtx
 
# network groups
network_test:
  hosts:
    router_test:

network_noop:
  hosts:
    router_noop:

こうすることで、どの環境のどの拠点に対して構成を適用するかを選択できる。たとえば test 環境の network_test 拠点に対して適用するのであれば以下のコマンドを発行する。

$ ansible-playbook -i ./inventories/test/hosts.yml router.yml --limit network_test --ask-vault-pass

なお router.yml はこういう調子。

- hosts: router
  connection: network_cli
  roles:
    - router
    - save_configuration

VLANのIDやIPの範囲、DHCPのスコープ範囲などは group_vars 以下に書いておくと良い。 host_vars/HOSTNAME.yml にはルータへの接続情報を書く。

---
ansible_user: SSH_USER
ansible_ssh_pass: SSH_PASSWORD
ansible_become: true
ansible_become_password: ADMINISTRATOR_PASSWORD

接続情報は暗号化して保存する

接続情報を平文で置くのはかなり抵抗がある。Ansibleには変数ファイルを暗号化する機能があるのでこれを利用する。host_vars/HOSTNAME.yml を丸ごと暗号化するには

$ ansible-vault encrypt host_vars/HOSTNAME.yml

を実行すれば良い。 ansible-playbook コマンドの実行時に --ask-vault-pass オプションを付けることで復号しつつ適用することができる。

ルータ初期化時の手順に ip lan1 addressdhcp scope の設定を含める

ip interface address ip_address/mask でinterfaceのIPアドレスを指定することができる*3ip lan1 address 192.168.0.1/24 のような要領。

YAMAHAルータはコマンドを実行すると逐次挙動が変化するので、SSHにIPv4を利用して接続していた場合 ip lan1 address でlan1のIPアドレスを変更するとその後の設定を適用できなくなる。 こればかりはどうしようもないので、SSHユーザを準備するなどの初期化時の手順内でlan1のIPアドレス設定とDHCPの設定を行うようにした。

Web UIから設定すれば同時に変更することができるし、コンソールケーブルで接続して設定するでも良い。自分はコンソールケーブルを用意して接続している。


素朴に1台だけ管理するならconfigファイルを持っておいて適用すれば良いけれど、拠点が複数あったり他の機材をAnsibleで管理している場合は便利そうなので検討しても良さそう。

*1:自分は普段Ansibleを使っておらずmitamaeかTerraformかCDKという感じなので公式ドキュメントを読み込みながら検討した

*2:https://docs.ansible.com/ansible/2.8/user_guide/playbooks_best_practices.html#alternative-directory-layout

*3:http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/ip/ip_interface_address.html

自分を必要以上に過小評価しないように、相対感を養うべき

soudai.hatenablog.com

この記事を読んで、新卒のころに同僚から掲題のようなことを言われたのを思い出した*1。そーだいさんの記事を読んだ自分の理解をおおまかにまとめると「自己の能力に自覚的になった上で、卑下するのはやめよう」という被評価者としてのスタンスの話だと思う。

同僚から言われた話も似ているけど、どう自己の能力に自覚的になるかという意味でやや違う。具体的には以下のような内容だった。

  • masawadaは相対感の勘が弱いので圧倒的に自己評価が低い
  • もっと周り(同期、同じグレード*2のエンジニア、チームのエンジニア)を見て自分がどういう位置にいるのか知るべき
  • 自己評価が不当に低かったり不当に高いということは自分の立ち位置が見えていないので不健全

元の記事では自己の能力に自覚的になれている前提があるように感じる。でも、当然みんながそうではないとも思う。自分に自信がなかったり、自己の能力に自覚的になれていないというケースは多いのではないか。このような状態だと、当然自己評価が不当に低くなる。

どうこの状態を脱出するかというと、同僚からの言葉にまとめられている通り周囲を見て自分の立ち位置を把握するに限る。集団の中での評価は、点数が付くような試験をしているわけでもなければ相対的なものになる。自分を周りと比較したときに相対的にどの立ち位置にいるのかを把握しておけば、過小評価することも過大評価することもなくなる。また、この課程で周りの立ち居振る舞いを観察することになるので、自分の伸びしろに気付くことができるかもしれない。

自信がない人のパターンとして、周囲と比べた結果逆に弱気になってしまうということがある。具体的には以下の記事に書いてあるような、複数の属性が架空の人格にバインドされてしまうパターン。

blog.sushi.money

これについては避けるべきと自覚的になれていれば必要以上に弱気になることもないかなと思う。メンターがいて定期的に1on1できる関係があるなら自分の立ち位置について会話してキャリブレーションすると良いかもしれない。

もし自分の評価について自信がなかったり悩んでいるのであれば、この考え方は頭の片隅に置いておくとよさそう。

*1:酒を飲みながらだったのでその同僚はもう忘れているかもしれないけど、言われたことは本当にその通りだなと思って以来その同僚をずっと尊敬している

*2:はてなではエンジニアに対する活躍の期待をグレードごとに分類して半期ごとに目標を立てている