ひさびさにMakefile書いた
別にC++を書き始めたとかいうことではない。 タスクランナー代わりにMakefileを使っている。
今仕事で、NFSのHA構成を構築するAnsibleスクリプトを組んでいるのだけど、ansible-playbookコマンドってextra-varsとか、tagの指定とか入ってくると横にクソ長くなるし、extra-varsの一部を変更して実行する必要がある場合とか面倒くさいんですよね。
なのでMakefileでタスク定義すればいいじゃん?と思いました。
Macならデフォルトで入ってますしね。(command line toolsかxcode入れる必要あったっけ?)
ていうかデフォルトで入ってるっていうのはツール選択上の強みですよね。
(だったらシェルスクリプトのほうがいいやんけって言われそうだけど)
gulpとかで書いた場合、他の人に渡すときにgulp入れてもらわないといけなくなるし
gulp1つインストールできない人にAnsibleスクリプトを引き継いだりするのは、それはそれで怖いけどね。。。
ここ一年間の進捗
ここ一年間ほどダイエットを敢行していたので、進捗を晒します。
進捗
- 開始時 : 133kg
- なう : 80.75kg
身長174.5cmなので、あと10kgほどは落とす必要がある。
ちなみに体脂肪率は11/7朝時点で12.7%とか出たが、体重が増減してないのに日によって5〜8%ぐらい上下するのであまり信用していない。
きっかけ
去年の健康診断で血圧が上140いったのと、肝臓の数値が悪くて病院での診断をすすめられたため。
「痩せりゃ正常値の範囲に戻るっしょ」という雑な考えのもとダイエットを開始した
(結局医者にはかかっていないので、今月の健康診断で数値が悪いままだったら本当に病院いかないといけないかも)
手法
食事はとりのささみをレンチンしたものにケチャップをかけたのと、豆腐をレンチンしてめんつゆかけたのばっかり食ってた。
あと、毎日エアロバイク15km
厳密には食事制限してなくて、大体1日1500kcal以下を目標としてたんだけど、カロリー計算するのがめんどくさくて同じものばっかり食ってた。
痩せてどうなったか
適当にLサイズの服を選択して普通に着られるっていうのは最高
(キングサイズの衣料はデザインがダサい上に、面積がデカイために高いということが多い)
あと、ズボンにデブ穴ができる心配が減った。
しかし、足のサイズが30cmあるので、靴選びだけは未だに難航する。(靴下もな)
終わりに
もう少しでBMI上の肥満域を脱してしまうのだけど、このブログのタイトルどうしましょうかね。。。
speakerdeckのスライドをpdfで保存するCLIコマンドを作った
pocketに保存したspeakerdeckのスライドをpdfでダウンロードしてローカルに保存するコマンド
won't read it laterの頭文字をとって「wril」です。
なぜ作った?
端的にいうとspeakerdeckが重くてkindle fire HD7と俺の寿命がマッハなので、いったんpdfで保存し、kindleパーソナルライブラリに突っ込もうとしたって話
いや、ほんと、speakerdeckって重くないですか? エアロバイク漕ぎながらpocketに入れた記事を消化するんですが、slideshareは普通に見られるのに、speakerdeckは重くてまともにスライドのページがめくれないんですよね。
めくれないどころか、kindle fire HD7がフリーズして再起動したんですよね。
おかげでspeakerdeckのスライドが全然消化できないので、技術で殴ろうとしたという話
仕組み
- pocketのapiを叩いて、「speakerdeck」という文字列が含まれるエントリを検索
- 上記検索結果からエントリのURLにアクセス
- アクセスしたspeakerdeckのページから、PDFのダウンロードリンクをスクレイピング
- 上記pdfリンクにアクセスしてダウンロード
技術的に特におもしろいところはない。
pdfをkindleパーソナルライブラリにアップロードするところは今のところsento-to-kindleアプリで手動アップロードしている
使い方
以下でコマンドをビルド
npm install npm run build
pocketのコンシューマキー、アクセストークンを環境変数に設定
export POCKET_CONSUMER_KEY=xxxx export POCKET_ACCESS_TOKEN=xxxx
以下のように実行
node dist/main.js -d /tmp/pdf_dl -c 10 -s unread
オプションで指定しているのはそれぞれ
- ダウンロード先ディレクトリ
- ダウンロード数
- pocketのアーティクルのstateの指定
ちなみにpdfのタイトルはURLをスラッシュ区切りにして、末尾のパスを使っている。 これだと同名のスライドがあった場合、上書きされてしまうので、スライド著者のspeakerdeckのアカウント名を先頭に入れて一意性を担保したほうがいいかもしれない。
終わりに
とりあえず、pocketに保存したspeakerdeckのページからスライドをpdfダウンロードして、kindleパーソナルライブラリに保存するという目的は達成できている。
あとはページング対応入れたらいいかなという感じ
というか、当初IFTTTとAWS Lambdaと組み合わせてピタゴラスイッチ化するつもりだったんだけど、途中でめんどくなってやめた。CLIコマンドならnode.jsである必要はないので、golangで書き直すかも。
Goでoshiraseというslackのcliコマンドを作ってみた
最近仕事でバッチやら定期実行してる監視スクリプトやらの結果をslackに通知させることが多いんだけど、シェルスクリプトからcurlでapi叩くのは面倒なので、goで簡単なcliコマンドを作ってみた
今のところ機能は以下の3つだけ
- 指定したチャンネル、グループにメッセージを投稿する (message)
- チャンネルの一覧を表示する (channel)
- グループの一覧を表示する (group)
slackの画面上からチャンネルIDとグループIDを調べるのが地味に面倒だったんだよね。。。
ちなみに、最初はslackerという名前にしようとしていたのだけど、github上で検索してみたら同名のリポジトリが600件ぐらいあった。。。
Thorで作った対話型コマンドをテストする方法
最近ThorでCLIコマンドを自作することが多い。 普通にテストするだけなら以下の記事の方法で問題無い
対話型コマンドの場合、テスト時にどうやって入力を与えればいいのか分からず、ちょいとハマってた。
解決方法:標準入力をモックすればよい
解決法は単純で、標準入力をモックすればよかった。
利用したテストダブルのライブラリはRR
stub($stdin).gets { "hoge" } Hoge.new.invoke :hoge, [] {}
ただ、上記の方法だと何回$stdin.getsしても同じ値が帰ってくるようになるので、ユーザに入力を複数回求める場合は使用できない。 そういった場合は以下のようにする。
stub($stdin).gets.times(1) { "hoge" } stub($stdin).gets.times(1) { "fuga" } Hoge.new.invoke :hoge, [], {}
上記のように指定すると、一回目はhoge、二回目はfugaが返却されるようになる。
欲を言えば、配列で指定した順番に返却してくれたりすると嬉しいんだけど、そういう感じの指定方法ってできないのかな?
初PRをキメた話
標準出力、標準エラー出力をキャプチャするgem、arieteにpull requestを出してマージされました
ariete.rb内にrspecの独自Matcherを定義しているため、arieteはrspec依存しているのだけど、gemspecにはrspecがdevelopment_dependencyで指定されており、かつariete.rb内でrspecがrequireされていなかったために、test-unitで使おうとした際に、require "ariete"するとNameErrorが発生するというもの。
(その前にrequire "rspec"しとくと回避できるけど)
修正箇所は2行。うん。プルリクのコメント書くほうが時間かかったよね。
oracleXEの文字コードをJA16SJISTILDEに変更したDockerfileを作った
何故作ったのか?
ユニットテストとか実行するときに、Dockerで使い捨てDB建てられないかなーと思ってて、通常のoracleXEのDockerイメージはDockerhubにあるんだけど、今の現場は文字コードがJA16SJISTILDEなのでそのまま使えず、しかたないので自作しましたというお話。
ちなみにまだDockerhubには上げてないよ。 (oracleXEってDockerImageで再配布するのって問題ないんすかね?)
ベースイメージは以下
ハマったところ
文字コードの変更自体は上記のページの内容をシェルスクリプト化してDockerfile内でRUNするだけなんだけど、それを実行するためには、ビルド時に一度OracleXEを起動する必要がある。
その際の起動にはベースイメージで使ってるシェルスクリプト*1をそのまま使ってるんだけど、その中で、listener.oraのHOSTの部分にコンテナIDをsedで書き込むようになっている。($HOSTNAMEでコンテナIDを参照できる)
#!/bin/bash LISTENERS_ORA=/u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora cp "${LISTENERS_ORA}.tmpl" "$LISTENERS_ORA" && sed -i "s/%hostname%/$HOSTNAME/g" "${LISTENERS_ORA}" && sed -i "s/%port%/1521/g" "${LISTENERS_ORA}" && service oracle-xe start
ほんじゃあDockerfileのCMDでservice oracle-xe restartするだけじゃん?って思うんだけど、上記で書き込まれるコンテナIDというのが実はワナでして、
このときに書き込まれるコンテナIDは、イメージビルド時のコンテナID なんですね。 (ベースイメージでは上記スクリプトがDocker runしたときに走るので、問題無い)
つまり、そのままCMDでservice oracle-xe restartすると、listener.oraに記載されるコンテナIDと、実際にDocker runでコンテナを起動する際のコンテナIDが齟齬ってしまう。 それで何が発生するかというと、listener.oraで指定している1521ポートについて、ホストとコンテナ間のポートマッピングが正常に動作しなくなってしまう。(ここらへんあんまり仕組み理解してない)
よって、コンテナ外からoracleXEに接続することができず、使い物にならなくなる。
解決方法
解決方法は単純明快で、以下のようにCMD行で再びlistener.oraをsedで書き換えて上げればよい
(sshdについてはベースイメージのやつをそのままパクってる)
CMD sed -i "s/HOST = .*)(/HOST = $HOSTNAME)(/g" /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora && service oracle-xe restart && /usr/sbin/sshd -D
単純明快っつったけど、原因に気づくの時間かかりましたね(´・ω・`)
その他注意点
Docker関係ないんだけど、oracleXEの文字コードを変更すると、DBインスタンスの再作成になります。 その際以下のような問題があります。
k-muratadevdesign.hatenablog.com
はい。DBMS_METADATA.GET_DDLが使えなくなります。
私の場合は上記の影響でDBFluteのreplaceschemaを叩いた際のデータロードがこけるようになりました。(ロードデータリバースは動くみたい)
感想
はー、つらい。