Golang ビルド時にコミットハッシュをソースに埋め込む
メモ
// config.go var CommitHash string
以下のコマンドでビルド
go build -ldflags="-X github.com/kohkimakimoto/hoge/config.CommitHash `git log --pretty=format:%H -n 1`"
MacでSSHログインと同時にターミナルの色を変える
いっぱいターミナルを開いていると間違って本番サーバで開発サーバ用のコマンドを実行しそうになってヒヤリとすることがあります。 そんなわけでSSH接続時、接続先ごとに自動的にターミナルの背景を変えるようにしてみました。以下のスクショのようになります。
解説
背景色の選択はAppleScriptでやります。以下のような関数を~/.zshrc
に書いておく
# ~/.zshrc function terminal-color () { /usr/bin/osascript -e "tell application \"Terminal\" to set current settings of first window to settings set \"$1\"" }
これで、terminal-color 'Red Sands'
のようにターミナルのテーマを指定して実行すると、背景色が変わります。
ついでに、踏み台サーバを経由するような場合も自動でそこまでたどり着けるように、コマンドを自動で連続してターミナルに流し込めるようにするAppleScriptも書いた。
# ~/terminal-exec.scpt on run argv tell application "Terminal" to activate tell application "System Events" to tell process "Terminal" to keystroke "t" using command down tell application "Terminal" repeat with x in argv do script x in front window end repeat end tell end run
これをコマンドで呼び出せるようにシェル関数でラップする。
function terminal-exec() { /usr/bin/osascript ~/terminal-exec.scpt $@ }
ここまでで
terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.1"
のようにコマンドを実行すれば、背景色を変えてSSH接続できるようになります。踏み台サーバがあるときはSSHコマンドを並べて書くだけでいいです。
terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.1" "ssh kohkimakimoto@192.168.56.2"
さて、この長ったらしいコマンドを毎回手打ちするわけもなく、pecoを利用したコマンドランチャーを利用します。これは以前のエントリ pecoをランチャーのようにして使う - オープンソースこねこね に書いたが当時のものから少し変わっているので、改めて以下にzshの関数を以下に貼り付けておきます。
# ~/.zshrc function peco-snippets() { local line local snippet local cwd local snippet_file local local_snippet_file local direct_run # Get a snippets file in the current directory if it exists. cwd=`pwd` if [ -e "$cwd/.snippets" ]; then local_snippet_file="$cwd/.snippets" else local_snippet_file="" fi # Do not load home snippets as a local snippets if [ $HOME = $cwd ]; then local_snippet_file="" fi direct_run=0 if [ $# -ge 1 ]; then # Load sub snippets file and selected line will be run directly. direct_run=1 snippet_file=$1 local_snippet_file="" else snippet_file=$ZSH_EXT_ROOT/snippets fi; if [ ! -e "$snippet_file" ]; then echo "$snippet_file is not found." >&2 return 1 fi line=$(cat $local_snippet_file $snippet_file | grep -v "^\s*#" | grep -v '^\s*$' | peco --query "$LBUFFER") if [ -z "$line" ]; then return 1 fi snippet=$(echo "$line" | sed "s/^[ |\*]*\[[^]]*\] *//g") if [ -z "$snippet" ]; then return 1 fi if [ $direct_run -eq 1 ]; then eval $snippet else BUFFER="$snippet" zle clear-screen fi } zle -N peco-snippets bindkey '^x^x' peco-snippets
pecoがインストールされていない環境はインストールしておきます。
そして、以下のようなコマンドを列挙したスニペットファイルを用意します。
# ~/.snippets [ssh connect: hakoniwa-local1] terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.20 -p 22" [ssh connect: hakoniwa-local2] terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.21 -p 22" [ssh connect: hakoniwa-local3] terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.22 -p 22" [ssh connect: hakoniwa-local4] terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.23 -p 22" [ssh connect: hakoniwa-local5] terminal-exec "terminal-color 'Pro remote'" "ssh kohkimakimoto@192.168.56.24 -p 22"
これでcontrol+x control+xのショートカットでスクショにあるようにssh接続先一覧が出て、そこから選べるようになります。 ちなみに本番サーバはレッド、開発サーバやローカルの仮想環境はブルーで表示されるようにしています。
Codeから遷移したUIViewControllerにstoryboard上でナビゲーションバーを表示する
storyboad上のSegueで画面遷移をつないでいった場合、UINavigationControllerに含まれるViewControllerは自動でナビゲーションバーが表示されて、そこにタイトルとかバーボタンをとかを配置することができるのだけど、コードから遷移させた場合storyboad上ではどことも繋がっていないViewControllerとして表現されてしまって、実際はUINavigationControllerの中にいてナビゲーションバーとかがあるのにそれが表示されていない、ということが起こる。
そんなViewControllerの場合以下のようにしてやればstoryboard上にナビゲーションバーを表示でき、IB上でタイトルやボタンを配置することができます。
- storyboard上でViewControllerを選択する。
- Attributes inspectorで
Simulated Metrics
設定のTop Bar
をTranslucent Navigation Bar
に設定する - storyboard上にナビゲーションバーの領域があらわれる
- ナビゲーションバーの領域に
Navigation Item
をドラッグアンドドロップして配置する
以上。
Cocoapodsにあげたライブラリをアップデートする
毎度公式ドキュメントを参照していたのでメモ。以下のコマンドを叩くだけ
pod trunk push NAME.podspec
UILabelを上寄せにする
よく忘れるので、メモ
- AutoLayoutでheight以外のconstraintをつける
- IBでPreferred Widthを0
- IBでLinesを0、または表示させたい最大の行数
Preferred Widthが何の設定なのか調べてない。。。
UITextFieldやUITextViewでキーボードの外をタップしたらキーボードを閉じる
すでにいろいろやり方がネット上に書かれているが、自分の中では以下の方法に落ち着いたのでメモっておく。
まず、以下の記事で紹介されているようなFirstResponderを取得するメソッドをUIViewにカテゴリとして事前に実装しておく。
#import "UIView+UIUtil.h" @implementation UIView (UIUtil) - (UIView *)findFirstResponder { if ([self isFirstResponder]) { return self; } for (UIView *subView in [self subviews]) { if ([subView isFirstResponder]) { return subView; } if ([subView findFirstResponder]) { return [subView findFirstResponder]; } } return nil; } @end
あとはViewController上で以下のように実装する。
# XXHogeViewController.m - (void)viewDidLoad { [super viewDidLoad]; // タップを検知するためのGestureRecognizer。デリゲートで処理するように設定 UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] init]; gestureRecognizer.delegate = self; gestureRecognizer.cancelsTouchesInView = NO; [self.view addGestureRecognizer:gestureRecognizer]; } // タップ時のデリゲートメソッド - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { UIView *touchedView = touch.view; UIView *firstResponderView = [self.view findFirstResponder]; if (touchedView != firstResponderView) { // 現在編集中のViewと違う場所がタップされたときのみキーボードを閉じる [self.view endEditing:YES]; } return YES; }
PHPでcronのように定期実行をするプログラムを書いた
kohkimakimoto/workerphp · GitHub
自分で使う分には最低限、必要な機能を実装できたので紹介します。以下のようなPHPファイルを記述してPHPのコマンドラインから実行するとプロセスが起動しっぱなしになりcront_time
で指定したスケジュールでジョブを定期実行してくれます。
<?php require_once __DIR__.'/vendor/autoload.php'; $worker = new \Kohkimakimoto\Worker\Worker(); // job for every minute. $worker->job("hello", ['cron_time' => '* * * * *', 'command' => function(){ echo "Hello world\n"; }]); // job runs a shell command. $worker->job("uptime", ['cron_time' => '10 * * * *', 'command' => "uptime"]); $worker->start();
ジョブはクロージャでPHPのコードとして書くか、シェルのコマンドを文字列で直接指定することができます。インストールはcomposer install
するだけですが、その他詳しい情報はリポジトリのREADMEを参照してください。内部的にジョブはプロセスをforkして実行させているので、PHPのpcntl
エクステンションがインストールされている必要があります。linuxならyumとかでインストールできると思います。
cronが普通に使える環境ならまあそれを使えばいいんですが、個人の用途でherokuの無料枠dynoを使って定期実行処理をしたかったので、こんなの作りました。
Web API
cronにない拡張機能として、簡易なWeb APIを提供するHTTPサーバを組み込んでいます。
$worker->httpServer->listen();
のように書くと、8080ポートを開きます。ポートを変更したいときは
$worker->httpServer->listen(8888, 'localhost');
のようにもかけます。HTTPサーバが立ち上がったら、
$ curl -XGET http://localhost:8080/{ジョブ名}
でジョブの情報を取得
$ curl -XPOST http://localhost:8080/{ジョブ名}
でジョブを実行することができます。また$worker->httpServer->setAPIKey()
を使えば、文字列一致だけで判定する簡易な認証機能をつけられます。
ちなみに、私は以下の様な設定でherokuのPHPスタック上で動かしています。
<?php require_once __DIR__.'/vendor/autoload.php'; date_default_timezone_set('Asia/Tokyo'); use Kohkimakimoto\Worker\Worker; $worker = new Worker(); // herokuはhttpのportを動的に割り当てるので環境変数から取得する $worker->httpServer->listen(getenv('PORT')); // apiにアクセスするときのキー $worker->httpServer->setAPIKey('vjdioaewdg49q3tg...'); // 5分毎にメモリ使用量などをログに出力する設定 $worker->stats->on(); $worker->job("hoge", ['cron_time' => '* * * * *', 'max_processes' => 1, 'command' => function(){ // ... }]); $worker->job("foo", ['cron_time' => '* * * * *', 'max_processes' => 1, 'command' => function(){ // ... }]); // 30分に一回dynoをwebからアクセスしてスリープさせないようにする。 $worker->job("wakeup_dyno", ['cron_time' => '*/30 * * * *', 'max_processes' => 1, 'command' => function(){ file_get_contents("https://my_worker_xxx.herokuapp.com/?apiKey=vjdioaewdg49q3tg..."); }]); $worker->start();
とりあえず、1日動かしっぱなしにしてみたが問題はなさそうです。