fish + pecoでdockerコマンドを使いやすくする
記事をzennに移動しました。
Macでテスト用のダミー画像やダミー動画を自動作成する
画像や動画を扱うサービスを開発していると、ダミーのテスト画像や動画が大量に必要になることってありますよね!
巷にはダミー画像を生成するサービスは複数あるのですが、動画の方は見当たりませんでした。 調べてみるとimagemagickで静止画を作成して、それをffmpegで動画にできるようなのでBashスクリプトで作ってみました。
スクリプトの紹介
Generate a dummy video or an image on macOS · GitHub
このスクリプトは動画と画像の両方を作成できます。 実際にスクリプトで作成した画像は以下の通りです。キャプションテキストと画像サイズが書き込まれるので、テスト実施時に画面をキャプチャすればエビデンスとして残せるかと思います。
動画の方は静止画を単純にループするようになっています(オプションで音声ファイルを指定すれば音もつけられます)。 また、動画の右上には残り秒数のカウントダウンも表示されます。
スクリプトを実行するにはimagemagickとffmpegが必要です。Homebrewを入れていれば以下のコマンドでインストールできます。
brew install imagemagick ffmpeg
インストールできたら、以下のコマンドでスクリプトを試してみてください。
curl -Ls https://gist.github.com/ikoba/2852944738431d82ebffe6d9e407cc32/raw | bash -s -- -s 400x300 -t 10 -c テストケース1-1
カレントディレクトリに、横: 300px, 縦: 400pxで長さ10秒の動画が作成されると思います。
使用可能なオプションは以下の通りです。
options: -i, --image generate an image -v, --video generate a video (default) -s, --size <geometry> specify width and height (default: 600x600) -c, --caption <text> specity caption text (default: Test) -f, --font <name> specify font name (default: "ヒラギノ角ゴシック-W3" or "Hiragino-Sans-W3") --list-fonts list available fonts and exit --font-size <number> specify font point size (default: appropriate value depending on the size) --foreground <color> specify caption text color (default: white) --background <color> specify background color (default: gray) examples of color formats: 'lime', '#0f0', '#00ff00', 'rgb(0,255,0)', 'rgb(0,100%,0)' --image-type <type> specify image type (default: png) -a, --audio <file> specify an audio file if you want to merge it with the video -t, --time <second> specify video length in seconds (default: 15) -o, --out <directory> specify output directory (default: working directory) -h, --help show usage and exit
1度に複数のダミー動画を作成する
例えば以下のようにxargsコマンドを組み合わせれば複数の動画を作成できます。
seq 10 | xargs -I SEQ ./dummy -s 400x300 -t 10 -c テストケースSEQ
スクリプトを作ってみた感想
今回はエンジニアでない方も使用するので、RubyやPythonなどがインストールされていない環境でも動作するようにBashスクリプトで作成しました(imagemagick, ffmpegはインストールしてもらう必要がありますが)。
書いてみた感想ですが、正直ちょっと辛いなと思いました。特にコマンドのオプションの取り扱いがRuby, Python, Goのように宣言的に書けず、また特殊な処理を必要とするので可読性が悪いです。他にも実行してみないとわからないような落とし穴がいくつかありました。
非エンジニア向けにも配布するという用途では、Go言語で作成したり、ツールを使ってRubyやPythonをシングルバイナリにまとめたりした方が良いのかなと思いました。あとはCUIというのも非エンジニアにはハードルが高そうです。PythonでGUIアプリを作れるFletを今度試してみたいと思います。
スクリプトを作成する上でVisual Studio Codeの以下の拡張が役に立ちました。未使用の変数や、if
に対するfi
の忘れなどの間違い、また非推奨な書き方をした場合に警告してくれます。
参考にした資料
GoogleのShellのスタイルガイドです。かなり参考になりました。
Bashのgetoptsでロングオプションを扱う方法が詳細に説明されています。
お手軽にRuby Gemのコードを開いて編集し元に戻す
Gemのコードで発生するエラーの原因を調べたり、コードを動かしながら確認したいと思ったりした時にGemのコードを手軽に開いてbinding.b
を仕込んでデバッグしたい。
bundle install --path vendor/bundle
でGemをインストールしてデバッグするのが一般的なやり方なのかもしれないが、ちょっと面倒。
そんな時に簡単にGemを開いてデバッグできる方法があった。
Gemのコードを開く
bundle open <Gem Name>
このコマンドでGemのコードを開くことができる。 以下のどちらかの環境変数にエディタのパスを設定すれば、そのエディタで開くことができる。
EDITOR
BUNDLER_EDITOR
EDITOR
を設定するとGitのコミットメッセージの編集に使用するエディタも変わってしまうので、BUNDLER_EDITOR
に設定するのがおすすめ。
私はVSCodeを使用しているので、fish shellの設定ファイル config.fish に以下を指定している。
set -gx BUNDLER_EDITOR (which code)
bashを使っている人は .bash_profile に以下を指定すれば良さそう。
export BUNDLER_EDITOR=$(which code)
Bundlerで管理していないGemのコードを開きたい場合は?
gemにもサブコマンドopenがある。
gem open <Gem Name>
Gemのコードを元に戻す
Gemの複数の箇所にbinding.b
やbinding.pry
を仕込んだ場合は元に戻すのが大変。
そんな時に便利なコマンドがある。
bundle pristine <Gem Name>
"pristine"は「手付かずの」という意味らしい。
<Gem Name>
を指定しないで実行した場合は、Gemfileに記載のあるすべてのGemを元の状態に戻すことができる。
Bundlerで管理していないGemのコードを元に戻したい場合は?
openと同様にpristineもgemのサブコマンドにある。
gem pristine <Gem Name>
すべてのGemの状態を元に戻す場合は以下のコマンドを実行する。
gem pristine --all
mitmproxyでAndroid Studioのエミュレーター上で動作するアプリの通信内容を確認する
フリーのHTTPSプロキシツールであるmitmproxyでAndroid Studioのエミュレーターの通信内容を確認できるようにする。
確認に使用したAndroid Studioのバージョンは以下の通り。
Android Studio Dolphin | 2021.3.1 Patch 1
1. mitmproxyのインストール
MacでHomebrewが入っている場合は以下のコマンドでインストールできる。
brew install mitmproxy
その他の環境でのインストールはこちら。
インストールしたら以下のコマンドで起動する。
mitmproxy
2. プロキシ設定
Android StudioのPreferencesの Tools > Emulator で下の赤枠のチェックボックスのチェックを外す(これをしないとエミュレーターでプロキシ設定のメニューが表示されないため)。
次にエミュレーターを起動させ、[...] をクリックする。
Settings > Proxy を開いて以下の設定を行う。
- Use Android HTTP proxy settings のチェックを外す。
- Manual proxy configuration を選択して以下の内容を指定する。
項目 | 値 |
---|---|
Host name | PCのIPアドレス |
Port number | 8080 |
3. 証明書のインストール
"If you can see this, traffic is not passing through mitmproxy." のようなメッセージが表示される場合は、プロキシ設定を見直す。
赤枠のAndroidの証明書をクリックする。
クリックすると証明書のインストール画面が表示される。
以下の内容で設定を行い、OKをクリックする(これで証明書がインストールされる)。
項目 | 値 |
---|---|
Certificate name | mitmproxy |
Credential Use | VPN and apps(デフォルトでOK) |
4. コードの変更
Android 7以降はデフォルトではユーザー証明書は使用できない。そのため、アプリ側の設定を変更する。
<network-security-config> <debug-overrides> <trust-anchors> <!-- Additionally trust user added CAs --> <certificates src="user" /> </trust-anchors> </debug-overrides> </network-security-config>
app/manifests/AndroidManifest.xml (debug)
のapplicationタグの中に以下のように属性android:networkSecurityConfig="@xml/network_security_config"
を追加する。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.cookpad.android.storetv"> <application android:networkSecurityConfig="@xml/network_security_config"> <!-- 省略 --> </application> </manifest>
上記の方法だとアプリごとに設定を変更する必要があるが、それを避ける方法もある(ここでは説明しない)。
5. ビルドして確認
ビルドしてエミュレーター上でアプリが立ち上がると、mitmproxyを起動しているターミナルで通信が確認できるようになっている。
サーバーのタイムゾーン設定ではまった話
最近、既存のRailsアプリをカスタマイズして別のインフラに載せ替えるという仕事をしているが、そこでインフラ初心者には解決が困難なタイムゾーン関連の問題が発生した。
なぜか想定より9時間ずれる
APIのレスポンスでdatetime型のカラムのデータが想定より9時間遅れて返ってきた。9時間といえばUTCとJSTの時差に一致するので、どこかでタイムゾーンがおかしくなっていることはピンと来た。
コンソールでDBのデータを確認すると想定通りの時間になっているのでデータの問題ではなさそう。 Railsのタイムゾーンの設定が間違っているかもしれないので調べてみた。
config.time_zone = 'Tokyo' config.active_record.default_timezone = :local
うーん、検索したみたらこの設定で問題なさそう。
そうなるとサーバーの設定があやしそう。ということで
Rails.logger.info "⭐️Time.now: #{Time.now}"
みたいなログを仕込んでみると、案の定2022-11-28 14:43:39.893488 +0000
みたいにUTCになっていた。
TZ=Asia/Tokyoを指定してみる
サーバーのタイムゾーンは、TZ=Asia/Tokyo
のように環境変数TZ
で指定するか、指定がなければ/etc/localtime
の設定が参照されるようだ。
TZ=Asia/Tokyo
の指定がなかったので追加して再度確認したが状況は変わらず。万策尽きた。
原因はDockerイメージの作り方だった
有識者に相談したところ、Dockerfileでtzdata
(タイムゾーンデータ)をインストールする記述がないので、これが原因ではないかということだった。
以下のコードを追加したイメージを作成して動かしたところ無事に解決した。
RUN apt-get update \ && apt-get install -y tzdata
tzdata
がないとTZ=Asia/Tokyo
と指定してもAsia/Tokyo
がUTCから何時間の時差があるかわからないので、指定の意味が無かったというオチだった。
最低限のイメージをベースにサーバーイメージを構築していく場合は、色々と入っていると思ったものが入っていないので注意していきたい。
Kindleで購入した本をブクログにインポートする(Macユーザー向け)
ブクログは仮想的な本棚を作成したり、本のレビューやメモを残したりできるサービスです。 同様のサービスに読書メーターがありますが、こちらは読書メモを非公開にすることができず、また、1つの本に対して残せるメモの文字数が250文字に制限されるため、個人用に読書記録を残す用途としては「ブクログ」の方が適していそうです(ユーザー数は「読書メーター」の方が多いらしい)。
インポート手順
1. ターミナル.appの起動
アプリケーション > ユーティリティー
にあるターミナル.app
を起動します。
別のターミナルアプリを使用している方は、そちらで大丈夫です。
2. Kindle for Macの準備
Kindle for Macがインストール済みでない場合は、こちらからインストールしてください。
3. Kindleのキャッシュデータの生成
Kindle for Macを起動し、🔄をクリックしてライブラリを最新の状態に更新します。更新が完了したらアプリを終了します。
アプリを終了すると、Kindleで購入した本のXML形式のキャッシュデータKindleSyncMetadataCache.xml
が生成されます。
4. インポート用CSVファイルの作成
上の手順で生成されたXMLファイルを解析してインポート用のCSVを作成します。
ターミナルに以下のコマンドを貼り付けてEnterキーを押して実行します。
xmllint --xpath '//purchase_date[string-length(text()) > 0]/../ASIN | //purchase_date[string-length(text()) > 0]/../purchase_date' ~/Library/Application\ Support/Kindle/Cache/KindleSyncMetadataCache.xml | sed -E 's/<ASIN>([^<]+)<\/ASIN><purchase_date>([^<]+)<\/purchase_date>/\1 \2\n/g' | sort -k 2 | awk '{print "1," $1 ",,,,,,,,,"}' > ~/Downloads/import.csv
コマンドを実行すると、ダウンロードフォルダにインポート用のCSVファイルimport.csv
が作成されます。
このファイルを開き、1列目に1
、2列目に10桁のASINコードが出力されていれば正しく作成できています。
1,B009IXLHZ2,,,,,,,,, 1,B009IXKPVY,,,,,,,,, 1,B009IXASIE,,,,,,,,, 1,B009IXJVVO,,,,,,,,, 1,B009KSOWRU,,,,,,,,,
Send to Kindle等でインポートしたAmazonで購入していない書籍は、このCSVには含まれません。 購入した順番に並べ替えているので、インポートすると購入日時が新しいものが本棚の上に並びます。
5. ブクログにインポート
ブクログのインポート画面で、上の手順で作成したCSVファイルimport.csv
を指定してインポートを実行します。
インポート完了後に本棚画面に移動すると... 綺麗にインポートできました。以上で終了です。