あんパン

こしあん派

dunstとsystemdのtimerで端末のバッテリが減ったら通知を出す

昨晩夕飯食べずに寝落ちしてしまい、PCの電源も刺さずにつけっぱなしにしてしまった。それを忘れて朝PCを触っていたところ電源が落ちた。以前からバッテリが減っていることに気づけず困っていたので、バッテリが減っていて充電もしていなかった場合に通知を出すことにした。

f:id:masawada:20200418171950p:plain

通知にはdunstを利用しているのでこれを使う。dunstifyを利用すると任意のテキストで簡単に通知を出すことができる。

まず以下のスクリプトを適当に $PATH に含まれてるディレクトリの中に放り込む。 /sys/class/power_supply/BAT0 とか BAT1 とかでバッテリ情報が入ってるのでこれを使う。 自分の端末はThinkPad T480でフロントバッテリとリアバッテリがあるので BAT0BAT1 があった。これを実行すると、全てのバッテリの残量が10%未満かつ充電していない場合にdunstでアラートを表示できる。

#!/bin/bash

set -eu

urgency=1

for battery in $(ls /sys/class/power_supply/ | grep BAT); do
  battery_path="/sys/class/power_supply/${battery}"
  battery_capacity=$(cat ${battery_path}/capacity);
  battery_status=$(cat ${battery_path}/status);

  if [ ${battery_capacity} -ge 10 ] || [ ${battery_status} = "Charging" ]; then
    urgency=0
  fi
done

[ "${urgency}" = 1 ] && dunstify -u critical 'Low Battery!'

exit 0;

あとはこれを1分おきに実行する。いま使っているディストリビューションはArch Linuxで、デフォルトでcronは入らないしsystemdのタイマー機能を利用する。

まずはsystemdのUnitファイルを $HOME/.config/systemd/user/low-battery-notifier.service みたいな名前で保存する。/path/to/low-battery-notifier は実行ファイルを置いた場所を指定する。これで、 systemd --user start low-battery-notifier.service で通知が動いていれば問題ない。

[Unit]
Description=Notify low battery alert

[Service]
Type=oneshot
ExecStart=/path/to/low-battery-notifier

次にこれを1分おきに実行するよう設定する。以下のtimerファイルを $HOME/.config/systemd/user/low-battery-notifier.timer みたいな名前で保存する。 serviceファイルと名前を対応づけて拡張子を.timerにする必要がある。

[Unit]
Description=Notify low battery alert timer

[Timer]
OnCalendar=*-*-* *:*:00

[Install]
WantedBy=timers.target

これで systemctl --user enable low-battery-notifier.timer && systemctl --user start low-battery-notifier.timer すると1分おきに最初のスクリプトが実行されるようになる。タイマーが正常に動いているかどうかは systemctl list-timers --users --all で確認することができる。

$ systemctl list-timers --user --all
NEXT                        LEFT     LAST                        PASSED  UNIT                       ACTIVATES
Sat 2020-04-18 17:37:00 JST 20s left Sat 2020-04-18 17:36:05 JST 34s ago low-battery-notifier.timer low-battery-notifier.service

という具合。これでバッテリが減ったら1分おきに通知が出る。

(Arch) LinuxでGitHub CLIを利用する

github.com

READMEにある通り

$ yay -S github-cli

でインストールできる。yay はGoで書かれているAURヘルパで、要はナウい yaourt 。他のAURヘルパを利用しても良い。 go-pie が依存になっており、 go がインストールされているとコンフリクトする可能性があるので、コンフリクトした場合は手で解決する必要がある。

gh コマンドを実行すると認可のためにブラウザが開かれる。ここでSSOが有効なorgをauthorizeしようとする際には事前にSSOを突破しておく必要がある(突破していないとアクセス権を取得できない)。間違えてアクセス権がない状態でtokenを発行してしまった場合は、一旦GitHubの Settings > Applications > Authorized OAuth Apps > GitHub CLI (dev) を一旦revokeして、.config/gh/config.ymlを削除すると再度認可が行われる。

$ gh issue list

Issues for masawada/housekeeping

#312  2020年2月目標
#311  2020/02/01-2020/02/29献立計画
#310  2月購買計画
#306  2020年旅行候補
#304  2019大掃除落穂拾い
#300  2020年欲しいもの
#299  2020年コンテンツ消費リスト
#298  2020年やりたいこと
#297  2020年上半期計画
#284  引っ越し

個人の計画repoのIssue一覧が見られて便利になった。いまのところIssue/P-Rを作るかリストするかブラウザで開くかくらいしかないけど、端末上で自由に編集したりレビューできるようになったりしたらめちゃくちゃ便利だと思う。

git addするときにerror: 's/' does not have a commit checked outというエラーが出て困ったので原因を追う

小ネタです。

$ git add -A
error: 's/' does not have a commit checked out
fatal: adding files failed

addできない。困った。

何が起きているのか

$ ls
README.md  s/
$ ls -la s
total 12
drwxr-xr-x 3 masawada masawada 4096 Jan  7 16:46 ./
drwxr-xr-x 4 masawada masawada 4096 Jan  7 16:46 ../
drwxr-xr-x 7 masawada masawada 4096 Jan  7 16:46 .git/

どうやら s というディレクトリが作られていて、中に .git ディレクトリが作られている状態。しかしこんなディレクトリを作った記憶はない… 一体何故…

ディレクトリが作られた原因を探る

ひとまずhistoryを眺めたところ、いつもと様子がおかしいコマンドを発見しました。

$ git git s

自分はgitconfigのaliasで git sgit status -sb に指定しています。

[alias]
    s = status -sb

しかし git を重ねてしまっているのがおかしそう。実行してみましょう。

$ git git s
WARNING: You called a Git command named 'git', which does not exist.
Continuing in 0.1 seconds, assuming that you meant 'init'.
Initialized empty Git repository in /home/masawada/sandbox/git/s/.git/

やはりこれが原因でディレクトリが作られていた!! しかし平時は git git と重ねても単にエラーが出て終了するだけです。

assuming that you meant 'init'

これはgitconfigでautocorrectを有効にしているから。git git と重ねると git init に補完されてリポジトリのディレクトリが作られてしまう、というオチでした。

[help]
    autocorrect = 1

autocorrectについてはこちら

git-scm.com

年始にLinuxデスクトップを使い始めて1年が経とうとしている

これは はてなエンジニア Advent Calendar 2019 2日目の記事です。

こんにちは、 id:masawada です。2ヶ月前まではブログチームのエンジニアでしたが、最近はマンガビューアを開発するチームに在籍しています。

弊社では開発に利用する端末を決められた上限額の範囲内で自由に選ぶことができます。多くのエンジニアがmacOS上で仕事をしており、WindowsやLinuxをデスクトップ環境として利用しているエンジニアはどちらかというと少数です(少なからずいます)。近年では多くのプロダクトのローカル開発環境でDockerを利用できるようになっており、OSの差異によってセットアップに躓くことがなくなった結果Linuxデスクトップへの移行のハードルが下がる傾向にあります。

自分も去年まではmacOS上で仕事をしていましたが、今年の頭にLinuxデスクトップに切り替えてようやく1年が経とうとしています。この記事では具体的にmacOSからどうやってマイグレーションしたのか、Linuxにして良かった点・困った点などを紹介します。

どういう環境を利用しているか

まず普段自分がどういう環境で仕事しているかをご紹介します。

  • 端末: ThinkPad T480
    • フロントバッテリあり
    • オプション品: ThinkPad バッテリー 61++, ThinkPad Thunderbolt3 ドック
  • OS: Arch Linux

購入当時最新だったThinkPadのうち、ArchWikiで動作確認が取れているものを選択しました。Xシリーズはいつのまにかバッテリの取り外しができず、RJ45も廃止されていたので検討から外しました。オプションでフロントバッテリを選択しており、リアバッテリのホットスワップが可能なようにしています。実際、6セルのリアバッテリもあわせて購入しており、会社に居るときと自宅に持って帰るときで付け替えられて便利です。ThinkPad Thunderbolt3 ドックはネット上で動作するか確認できませんでしたが、まあ問題ないであろうということで購入しています。ThinkPadだと全部あわせて予算に収まるのでお財布にも優しいですね。

基本的にオフィスツール系がG Suiteで完結しておりMacやWindowsでしか開けないものはエンジニアはほぼ扱わないので、その点で困ることはありません。強いていうならiOSアプリエンジニアへの転向ができないくらいです。

なぜLinuxデスクトップにしたのか

丁度PCの更新時期が近づいたためリプレース先を検討し、Linuxデスクトップにしました。具体的には以下のような課題を解決したいという意図がありました。

  • ソフトウェア的な課題
    • Docker for Macのオーバーヘッドが大きいように感じる
    • LinuxとmacOSではGNUとBSDのツールでオプションが違って難しい
  • ハードウェア的な課題
    • バタフライキーボードよりはストロークの深いキーボードが好み
    • Vimを使っているので物理Escが欲しい
      • ctrl-[ もあるけどネ
    • RJ45が欲しいときがある
      • ないですか? ぼくはあります

どのようにマイグレーションしたのか

macOS上でLinux環境をプロビジョニングする仕組みをdotfilesに整備して移行しました。突然移行したとしても仕事ができないのは容易に想像がつくので、まずは業務の傍ら環境をせっせと作って、最後に一気に移行するというモデルです。

まずはmacOS上のVirtualBoxにArch Linuxの環境を用意してデスクトップ環境を用意しました。OSのインストールはスクリプト化しており、スクラップアンドビルドが容易な状態にしています。netinstのイメージを立ち上げて以下を実行するだけでインストールできるようになっています。最近は実行してませんが多分動くはず。

$ NEW_USERNAME=masawada bash -c "$(curl -fsSL https://dot.masawada.me/scripts/os_install)"

ちなみにこのスクリプト、 /dev/sda があることを想定して書いているのでThinkPad上では動きませんでした。なぜならディスクが /dev/nvme0n1 にマウントされていたため。その場で適当に書き換えて利用しました。

次にGitHubに公開鍵を登録します。プロビジョニング走行時には git clone をするので公開鍵が登録されていてほしいですが、当然デスクトップ環境がないので登録が困難です。そこで公開鍵を登録するスクリプトを用意しました。以下のコマンドで公開鍵をGitHubに登録できます。

$ bash -c "$(curl -fsSL https://dot.masawada.me/scripts/setup_github)"

以前書いたこの記事は、今回のための伏線でした。

masawada.hatenablog.jp

ここまでを終えた状態で、ちまちまプロビジョニングファイルを書いていきます。プロビジョニングにはmitamaeを利用しています。Itamaeのmruby実装で、バイナリをGitHub Releasesから引っぱってくるだけで実行することができます。これにより、プロビジョニングする環境を整える手間を省いています。ディレクトリ構造などは k0kubun/dotfiles を参考にさせていただいています。

roles/arch/default.rb を見ると具体的にどのようなソフトウェアをインストールしているかを確認することができます。あまり凝ったことはしていませんが、 polybar のビルドに時間がかかりsudoがタイムアウトしてしまうので、一時的にこれを防ぐ処理をしています。この実装は cookbooks/functions/default.rb にあります。

また、今回の過程で masawada/mitamae-plugin-recipe-plenvmasawada/itamae-plugin-recipe-nodenv を作ったのでよければご利用ください。

プロビジョニング自体は

$ bash -c "$(curl -fsSL https://dot.masawada.me/install)"

で実行できるようにしています。適当なドメインを取って自分のdotfilesのrepoへリダイレクトするように設定しておくと便利です。自分はドメイン( dot.masawada.me )をAWSのCloudFrontに向けておいて、OriginをS3のバケットに設定し、S3のStatic web hostingの設定で全てのリクエストをGitHubのファイル配信URLにリダイレクトしています。

よかったこと

最初に挙げた課題については全て解決しました。特にDockerについては、babelによるトランスパイルがだいたい3,4倍くらい高速化しました。マシンスペックの差による部分もあるはずで、実際には2倍ちょっとくらいには高速化してるんじゃないかなーと思っています。少なくとも docker-compose up してファンが高速回転することはなくなりました*1。この効果は結構大きくて、以前よりも快適に開発ができるようになったと感じています。

その他特筆すべきことはありませんが、特筆すべきことがないくらいには手に馴染んでおり満足しています。

困ったこと

マルチディスプレイ周りの挙動が怪しい

予想はしていましたが、マルチディスプレイ周りの挙動が怪しいです。ディスプレイの設定には xrandr を使うことになるのですが、ThinkPad Thunderbolt3 ドックを利用している場合、1コマンドで複数オプションを付けてマルチモニタ設定を行うと、抜き刺ししたときに xrandr 上では認識されているにも関わらずサブディスプレイの画面が表示されなくなります。xrandr をモニタの回数分発行することでこの現象を回避できます。

自分はディスプレイの設定を自動化するスクリプトを作っていて、F7を押下することでこれが実行されるようになっています。上記の問題については、このスクリプトの以下の修正で解決しました。

Bluetooth周りが微妙に不安定

接続時にうまく掴まえられなかったり、繋いだままサスペンドしたときの挙動などが微妙に不安定で、BluetoothキーボードやBluetoothイヤフォンを使わなくなりました。キーボードについては、最近はHelix Picoを利用しています。イヤフォンについては、もともとSpotifyで音楽を聴いていたのでイヤフォンの接続先がスマートフォンになっただけで、操作はSpotifyのWebプレイヤーからするようにしています。Hangout等は直接有線のイヤフォンを刺すことにしています。

FAQ

LTSじゃないんですか?

はい。まあデスクトップだし、LTSじゃなくても派手に壊れることはないであろうというマインドでやっています。ほぼ毎日 pacman -Syu していますが、1年を通して派手に壊れたことはありません。せいぜいシャットダウン時にハングすることがあった、放置してサスペンド状態になると復帰しないことがあった、くらいでした。派手に壊れたら代替機(空き状況によるけどおそらくmacOS)を借りられるので、そのときはそのときと割り切っています。

次のPCもLinuxにしたいですか?

はい。先にも書いたとおり現状は特に致命的な不満はないです。指紋認証がなくて毎度パスワードを打っているのが若干大変くらいです。もともと使ってたMacBook Proにもなかったのでそんなに苦ではないです。

他のエンジニアにもLinuxデスクトップを勧めたいですか?

いいえ。自分は好きでLinuxデスクトップを使っているので壊れたら直すし使いづらかったら改善するので良いのですが、他のエンジニアがそうとは限らないし仮にも毎日使う端末なので直すのが苦痛というひとには全く合わないため強く勧めたりはしません。移行自体も準備するのは一苦労なので、やはり好きでなければ難しいでしょう。会話の流れで提案することはあります。


以上Linuxデスクトップに移行した話でした。細かい話題は書ききれなかったのでまたどこかで記事にしようと思います。

明日は id:yigarashi です。

*1:自分はこの現象を離陸と呼んでいます

Vim + aleで保存時にperltidyを実行してコードを整形する

aleはこちら。非同期でLinterを実行したり、autofixしたりといった作業をやってくれるいつものやつ。

github.com

$ cpanm Perl::Tidy

して Perl::Tidy をインストールしつつ、aleが入っている状態で .vimrc

let g:ale_fixers = { 'perl': ['perltidy'] }
let g:ale_fix_on_save = 1
let g:ale_perl_perltidy_options = '-pro=.../.perltidyrc'

すると完成します。

によると

A pathname begins with three dots, e.g. ".../.perltidyrc", indicates that the file should be searched for starting in the current directory and working upwards. This makes it easier to have multiple projects each with their own .perltidyrc in their root directories.

とのことで、この指定をしておくとcwdから親のディレクトリに向けて.perltidyrcを探しにいってくれます。これでホームディレクトリの設定に優先してプロジェクト毎の設定を反映してfixできますね。