いぇいいぇい

ASP.NET、PHPを中心に書いています

複数のGitHubデプロイキーを同じマシンで使う方法

GitHubでは、デプロイキーは1つのリポジトリにのみ関連付けられます。ですので、通常はリポジトリ毎に異なるSSHキーを作成してデプロイキーとします。

ここで困るのが、同じマシンで複数のリポジトリをデプロイしたい場合です。例えば複数サービスを同じVPSに共存させる場合や、同じサービスだけど複数のリポジトリがある、という場合などです。

GitHubの場合、ホスト名とSSHキーを関連付けるために~/.ssh/configで以下のように指定しますが、単純に複数個指定してもうまくいきません。

Host github.com
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_proj1
Host github.com
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_proj2
> git clone git@github.com:tsu1980/proj2.git
ERROR: Repository not found.
fatal: The remote end hung up unexpectedly

同一マシンで複数デプロイキーを共存させる方法

そこで、以下のようにHostの値を分けて定義し、Git URLも同じ値を指定してやるとうまく動きます。

Host github.com-proj1
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_proj1
Host github.com-proj2
    Hostname github.com
    User git
    IdentityFile ~/.ssh/id_proj2
> git clone git@github.com-proj2:tsu1980/proj2.git
Initialized empty Git repository in /var/projects/proj2/.git/
remote: Counting objects: 833, done.
remote: Compressing objects: 100% (480/480), done.
remote: Total 833 (delta 400), reused 748 (delta 315), pack-reused 0
Receiving objects: 100% (833/833), 800.30 KiB | 523 KiB/s, done.
Resolving deltas: 100% (400/400), done.

Hostの値とGit URLのホスト名部分を一致させることがポイントです。この例ではgithub.com-proj2の部分になります。

cloneではなく既存リポジトリのURLを変更するにはgit remote set-urlを使ってください。

参考

Managing deploy keys | GitHub Developer Guide

superuser.com

Windows10でスタートアップフォルダを一発で開く方法

Windows10になってスタートメニューからスタートアップが消えました。今までスタートメニューから辿っていたのでとても困ります。スタートアップフォルダ自体は以前と同じ場所にあるのですが、それがとても深い階層にあるため、記憶だけではなかなか辿り着けません。スタートアップフォルダがどこにあるのか、簡単に開く方法はないのか、調べてみました。

一発でスタートアップフォルダを開く方法

  1. Windows+Eでエクスプローラーを起動します
  2. アドレスバーにshell:startupと入力してエンターキーを押します

f:id:sumi2:20160420122152p:plain

これでスタートアップフォルダを開けます。

ちなみに、すべてのユーザーのスタートアップフォルダを開くにはshell:common startupと打ちます。

hostsファイルが反映されない問題が解決

hostsファイルに書いたホスト名が反映されない問題で試した方法と原因、解決策についてまとめてみました。

症状

僕の場合はChromeでは名前解決できるのに、IEやpingではダメという状態になりました。

hostsファイルの中身

まずはhostsファイル(C:\Windows\System32\drivers\etc)の中身。

127.0.0.1       localhost abc1.localhost abc2.localhost abc3.localhost abc4.localhost abc5.localhost abc6.localhost abc7.localhost abc8.localhost abc9.localhost

全部で10個のホスト名を127.0.0.1に振り向けています。

このうち、abc9.localhostについてのみ、IEなどで名前解決できない状態になりました。

(本当は15個くらいあったのですが、表記上10個にしています。)

環境

  • Windows 10

名前解決の確認方法

名前解決ができているかどうかは、pingが通るかどうかで確認します。

ping abc.localhost

NGの場合はこうなります。

C:\WINDOWS\system32>ping abc9.localhost
ping 要求ではホスト abc9.localhost が見つかりませんでした。ホスト名を確認してもう一度実行してください。

OKの場合はこうなるはずです。

C:\WINDOWS\system32>ping abc9.localhost
abc9.localhost [127.0.0.1]に ping を送信しています 32 バイトのデータ:
127.0.0.1 からの応答: バイト数 =32 時間 <1ms TTL=128
...

1) DNSキャッシュのクリア

まずは定番のDNSキャッシュのクリアです。

ipconfig /flushdns
ipconfig /displaydns

しかし、状態は変わらずでした。

2) hostsファイルのアクセス権限

ファイルのアクセス権限をいじれば治ったという書き込みを見たので、ファイルにEveryoneフルコントロールのアクセス権限を追加してみました。 しかし、これも効果ありません。

セキュリティ上よくないのでアクセス権限は元に戻しておきます。

3) 1行あたりのホスト名制限

なんとWindowsのhostsファイルは1行あたりのホスト名に最大9個までという制限があるそうです。

superuser.com

確認してみると僕のhostsファイルには1行あたり10個以上のホスト名を記載していました。この情報に従って1行あたり9個までとなるようにhostsファイルを修正しました。

127.0.0.1       localhost abc1.localhost abc2.localhost abc3.localhost abc4.localhost abc5.localhost abc6.localhost abc7.localhost abc8.localhost
127.0.0.1       abc9.localhost

ただ、修正してもpingがまだ通りません。。

4) hostsファイルを1回削除してみる

何らかの理由により、hostsファイルの変更が検知できないような状態になっていると考え、一旦hostsファイルを削除してみることにしました。 もちろんファイルは別名のファイルに退避しておきます。具体的には以下の手順です。

cd C:\Windows\System32\drivers\etc
mv hosts hosts.bak
mv hosts.bak hosts

これでhostsファイルが正しく認識し、すべてのホスト名が名前解決できるようになりました。

まとめ

今回のケースでは1行に10個以上のホスト名を書いたことが原因でした。Chromeでは10個以上でも問題なく認識していたのですが、Chromeは独自にhostsファイルを読みに行っているのかもしれませんね。

また、hostsファイルの変更を検知させるためにファイルを一旦削除する方法が有効でした。これも1つの発見でした。

Evernote(Windows版)で書式なしでペーストする方法

Evernoteでコピーした文章をペーストすると、通常はリッチテキスト形式でペーストされます。リンクや色など書式付きになるわけですね。この動作はページ内容を見た目そのままで貼り付けたい場合はいいのですが、テキストだけを貼り付けたい場合は邪魔な動作になってしまいます。

今回はWindows版のEvernoteで、書式なしでペーストする方法と、それを既定の動作にする方法を掲載します。

書式なしでペーストするには

リッチテキスト形式ではなく、書式なしでペーストするには、[テキストとして貼り付け]コマンドを実行する方法があります。こうすることでプレーンテキストのみを貼り付けることができます。

メニューからの場合

Evernoteのメニューから、[編集]-[テキストとして貼り付け]を選びます。

ショートカットの場合

「Ctrl+Shift+V」キーを押します。

けど、貼り付けのショートカットキーといえば通常は「Ctrl+V」。Evernoteだけ異なるキーを押すというのはなんかイヤ。。

書式なしペーストを既定の動作にするには

もし「Ctrl+V」と「Ctrl+Shift+V」を置き換えることができれば、書式なしペーストを既定の動作にすることができます。しかし残念ながらEvernoteではショートカットキーのカスタマイズ機能は用意されていません。

そこで、AutoHotKeyという便利ツールを使います。AutoHotKeyはキー入力をフックして自由にカスタマイズすることができる常駐アプリです。今回のケースのようにアプリケーション側でキーカスタマイズ機能がない場合でもキー入力を置き換えることができます。

ただ導入には多少の手間がかかるのがデメリットですね。OS標準の機能としてくれてもいいような機能なんですけど。Evernoteを常用していて、どうしてもキーを置き換えたい!というひとはこの機会に導入しましょう。

導入方法は長くなるので省略し、スクリプトのみ紹介します。

;Swap Ctrl+V to Ctrl+Shift+V in Evernote
#IfWinActive, ahk_class ENMainFrame
    ^v::Send,^+v
#IfWinActive, ahk_class ENMainFrame
    ^+v::Send,^v

このスクリプトを追加することで、「Ctrl+V」と「Ctrl+Shift+V」を置き換えることができました。長く使うものだからこそストレスなく使えるようにしたいですよね。

autohotkey.com

(LINQ)SkipWhileの使い方、間違えていませんか?

はい!僕、間違えていました!

SkipWhile、単純に「条件に一致する要素をスキップする」ものだと思っていました。まったくの勘違い。アホですねー。

正しくは「条件に一致する限り要素をスキップする」ということみたいです。

以下サンプルです。

void Main()
{
    var names = new string[] { "太郎", "花子", "太郎", "花子" };
    var namesExclude = new string[] { "太郎" };

    // namesから"太郎"を除外したいとします。
    // まずはSkipWhileの場合
    var nameFiltered1 = names.SkipWhile(s => s == "太郎");
    Console.WriteLine("SkipWhile:");
    foreach (var name in nameFiltered1) {
        Console.WriteLine(name);
    }

    // Whereの場合は全要素フィルタリングできます
    var nameFiltered2 = names.Where(s => s != "太郎");
    Console.WriteLine("Where:");
    foreach (var name in nameFiltered2) {
        Console.WriteLine(name);
    }
}

出力結果

SkipWhile:
花子
太郎
花子
Where:
花子
花子

多分勘違いしたのはWhileの逆バージョンがほしくて、SkipWhileを見た時に「ああ、あるじゃん、これこれ」みたいな感じで勝手に自分の都合よく解釈しちゃったんだろうと思います。怖い怖い。

Realtek HD Audioの音飛び問題が解決

去年にPCをアップグレードしたときから悩まされてきた問題が解決しました。非常にうれしい。

現象

現象としては数分から数十分の頻度で音飛びが発生。具体的には突然音が「プツッ」っと止まって、1秒くらいでまた音が再開するというもの。

原因は音飛びじゃなかった

最初は音飛び問題ということでエフェクトとか、コーデックが悪さをしているんじゃないかと思っていろいろ探していたのですが原因わからず一旦諦めていました。

先日OSをWindows10にアップグレードしてからも同じ現象が発生して落ち込んでいました。ところが現象発生時に「デバイスが切断されました」、「デバイスが接続されました」的なバルーン通知が出るではないですか。

これは音飛びじゃなくてデバイスの切断が発生する問題じゃないかと思い再度ネット検索したところ、以下のページを見つけました。Realtek HD Audioにジャックなどのコネクタの切断/接続が発生する問題があることがわかりました。

www.sevenforums.com

www.youtube.com

解決

リンク動画を参考にオーディオマネージャという常駐プログラムを停止し、exeもリネームしました。今のところ問題は発生していません。よかった。

具体的な手順は以下です。

  1. タスクマネージャからRAVCpl64.exeを停止
  2. "C:\Program Files\Realtek\Audio\HDA"のRAVCpl64.exeをRAVCpl64_renamed.exeなどにリネーム

(RtkNGUI64.exeも同様にリネームしたほうがいいかもしれません)

参考までに環境は以下です。

  • Windows 10(64bit)
  • Realtek High Definition Audio(driver 6.0.1.7535)
  • H97-PRO

(2016/02/10 追記)

Windowsの自動更新などでドライバが再インストールされた場合は、exeが復活してしまうようです。その際は、再度リネームすればOKです。

ASP.NET MVC + Entity framework Code Firstのプロジェクト構成を紹介します

自分の今のプロジェクトで採用しているプロジェクト構成を紹介してみようと思います。何が正解とかはないと思いますが1つの例として参考になるかと。こういう情報が少ないので他の人はどうやってるのかすごい興味があります。オープンソースのものをたまに見ることはあるけどブログとかでってのはあまり見る機会ないですからね。変なとこありましたらツッコミなどよろしくお願いします!

前提

自分の場合はWebアプリだけでなくバックグラウンド処理サービスがあり、複数プロセスからDBアクセスしたいという要件がありました。

そういう要件がなくて単純なWebアプリの場合は1つのプロジェクトだけでもいいと思います。

その場合はフォルダ(名前空間)として分類することになります。ただフォルダだけだと本当にクラス同士が依存していないかコンパイラチェックではわかりません。なので依存関係がないことを確実にチェックしたい人は別プロジェクトにするといいですよ。

プロジェクト分けは、各プロセスが何に依存するかということ基準に決めます。

概要

f:id:sumi2:20150630173156p:plain

VSで依存関係マップを生成してみました。7つのプロジェクトがありますね。この他にSiteToolというプロジェクトがありますが別slnになっているので見えません。矢印が参照を表すようですね。

プロジェクト名 種別 説明
AppName.Core ライブラリ アプリ共通コード
AppName.Models ライブラリ POCOモデルクラス
AppName.DAL ライブラリ データアクセス関連コード(DB/Blob/File/Redis)
AppName.Web Web Webアプリ
AppName.Jobs ライブラリ バックグラウンド処理のinterface定義
AppName.Sites ライブラリ バックグラウンド処理実装
AppName.Hangfire コンソール バックグラウンド処理用のWindowsサービス
AppName.SiteTool WinForms バックグラウンド処理の開発用GUIツール

では順に説明していきます。

AppName.Core

Coreにはアプリ共通のクラスを格納します。余計な依存関係はありません。クリーンです。Jsonくらいあってもいいかも。僕のプロジェクトにはアプリ例外クラス、エラーコード定義、ユーティリティ拡張メソッドなどがあります。小さいです。

もしアプリ共通で使うけど依存DLLが必要な場合は、こう考えます。

  1. 将来も含めてすべてのプロセスで必要になるなら追加する。
  2. そうでないなら別プロジェクトにする。

依存関係:

なし

AppName.Models

ModelsにはPOCOのモデルクラス「だけ」を格納します。DB関係ないモデルクラスも入ってもいいですが、こちらも余計な依存関係は持ち込まないようにします。

依存関係:

AppName.Core

AppName.DAL

DALにはデータアクセス関連のコードを格納します。ApplicationDbContext、DbMigrationsConfiguration、Redis、BlobStorageなどですね。接続文字列などは各プロセスプロジェクトのWeb.config(App.config)で定義したものを参照します。

依存関係:

AppName.Core
AppName.Models

AppName.Web

Webアプリ本体ですね。フロント側の処理になります。ポイントはAppName.Hangfireに依存していないことです。バックグラウンド処理のジョブを実行する場合はAppName.Jobsで定義したinterfaceでHangfireジョブをキックします。

依存関係:

AppName.Core
AppName.Models
AppName.DAL
AppName.Jobs

AppName.Jobs

バックグラウンドジョブのinterface定義のみを含みます。AppName.Webから依存関係を取り除くために必要になります。Hangfireのジョブクラスをinterfaceにすることで依存関係を取り除くことができます。

依存関係:

なし

AppName.Sites

バックグラウンド処理をここで実装します。Blobを事前にローカルにDLしたりして、今のところDALには依存せずに済んでいますね。

依存関係:

AppName.Core
AppName.Models

AppName.Hangfire

バックグラウンド処理用のWindowsサービスです。デバッグ用にコンソールでも動作するようになっています。運用時にはこいつを複数個起動します。モジュール更新時はプロセス停止が必要なので複数個必要です。

依存関係:

AppName.Core
AppName.Models
AppName.DAL
AppName.Jobs
AppName.Sites

AppName.SiteTool

バックグラウンド処理(AppName.Sites)を簡単に呼び出すために作った開発用のGUIツールです。Hangfire経由ではなくボタンクリックでジョブを実行できます。

依存関係:

AppName.Core
AppName.Models
AppName.Sites

まとめ

いかがでしたでしょうか。後半疲れて尻すぼみになりました。。

ぜひみなさんのプロジェクト構成も晒してみてください!