MySQL: テーブルのデータサイズを見るときはinformation_schema.tables

こういうかんじ:

mysql> select table_name, table_rows, avg_row_length, (data_length + index_length) / 1024 / 1024 as total_mb, data_length / 1024 / 1024 as data_mb, 
index_length / 1024 / 1024 as index_mb from information_schema.tables where table_schema = '...';
+---------------------------------+------------+----------------+----------+---------+----------+
| table_name                      | table_rows | avg_row_length | total_mb | data_mb | index_mb |
+---------------------------------+------------+----------------+----------+---------+----------+
| foo                             |      10224 |            350 |        6 |       3 |        3 |
| bar                             |     391760 |            274 |      102 |     102 |        0 |
+---------------------------------+------------+----------------+----------+---------+----------+
2 rows in set (0.01 sec)

builderscon tokyo 2018で『ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ』という話をした

builderscon tokyo 2018で話しました。

2017に続いてスピーカーとしての登壇で光栄です。こういうイベントで何も話さないとどことなく居心地が悪くなる性分なので、スピーカー or die (不参加) となるところだったのでよかったです。

トークについて

speakerdeck.com

資料はすでに公開しています。

Hatena Engineer Seminar #10という社の名前を冠したイベントでもこのシステムについて話したのですが、けっこうおもしろいシステムができたという自負もあったしお待たせしてしまった感は拭えないのでせめて裏側を紹介して「知らなかった、を聞」いてもらえたらな、という思いもありました。
実際にbuildersconで話を聞いてもらえる機会をいただけて本当に嬉しいです。

実は後半の「ぼくのかんがえたさいきょうのピタゴラスイッチ」以降のスライドは直前に追加したものです。
今回初開催となるスピーカーディナーの会でid:devorgachemさん (今回はじめてお会いしました) とid:nkgt_chkonkさんと「設計について話そうとすると実践から離れた表層の話か、逆に応用の利きづらいドメイン特化の話になりがちでむずかしい (けどなんとかやっていきたい)」というような話をして刺激を受けて「もっと一般化された・普遍的な話ができるはずだ、したい」と思い捻り出しました。
実際できあがった話は、普段から考えていたことを咀嚼したものでかなり納得感がありました。ちょっと背伸びするきっかけができてよかったです。

あと「ぼくのかんがえたさいきょうのピタゴラスイッチ」は「ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく」をリスペクトしました。
スピーカーディナーでid:cho45さんとお話しできたのもすごく嬉しくて *1 、これだけでも参加した甲斐がありました。

Q&A

すっかり頭から抜けてしまったので、ツイート検索しました。ありがとうございます。
これまでのキャリアで最も質疑をたくさんいただけたトークで、とても励みになりました。やっぱり反応もらえるとうれしいです。

Q.「StepFunctionsのJSON手書きつらくならないんですか?」A.「つらいです。schemaがないので全体を把握するのがむずかしい。Goのコードを解析してschemaを作るグッズを作ろうとしている」

あともうちょっと質問いただいた気がします。録画見て思い出そうと思います……。

聞いたトーク

正直いうと他のトークほとんど聞けていないのが心残りです。ただでさえ発表前でナイーブになっているところへ関西にものすごい台風が来たり、地元の北海道で大きな地震が起きたりして、けっこう堪えました。
特に北海道の地震は仕事でもプライベートでも大きな打撃があって冷や冷やしました。

また、会場へ出向いても満員御礼だったということが多かったのもやや残念です。SmartHR社のマルチテナンシーの話はおもしろそうだったので生で聞きたかった……!

事前知識なしで理解する、静的検査のいろは - builderscon tokyo 2018

昨年のビルコンで僕も「Goで実装する軽量マークアップ言語パーサー」というトークをして興味のある分野だったので聞きました。
というのと、iOSDC 2018でベストスピーカー賞2位とのことで、プレゼンテーションが上手な方の話を聞いてみたいという興味もありました。

実際、幅広いトピックを密度高く紹介するというプレゼンテーターとしては難易度の高い話だったと思いますが、細かい粒度でまとめを挟んだり、構文木など難しい概念はグラフィカルに説明することを徹底されており、唸りました。

内容自体だけでなくプレゼンテーションそのものが勉強になりました。

JavaCardの世界 - builderscon tokyo 2018

興味の範囲がWebを中心としている限りおよそ出会うこともなかろうトピックだったので聞きました。

AIDなどの払出しがISOだったり、中央集権っぽいのが組み込みっぽいというかWebっぽくなくて新鮮ですね。

運営スタッフのみなさまへフィードバック

  • スピーカーディナーよかったです
    • お酒入ってたこともあり1分間ピッチの反応が思ったより良くて発表前にちょっと自信がつきました
    • 規模感がちょうどよく、いろんな人と話しやすかったです
  • 満員御礼で見れないトークが多く残念でした><
    • 街頭ディスプレイみたいな、コンサートホールのホワイエで見れるやつみたいな、立ち見席みたいなのもあると嬉しいかも、とおもいました

とはいえ部屋に入れなかったらHUBへ行くことができて、そこはそこでおもしろい話ができました。
僕のトークの裏番組になってしまい聞けなかった遠いようで身近なサウンドエンジニアリング - builderscon tokyo 2018もスピーカーである id:karupanerura さんとイベント後のHUBでゆっくり話ができたのもいい思い出です。

ビルコンも3度目ですが、毎度、これだけの規模のイベント運営されるみなさまには頭が下がります。ありがとうございます……!

*1: ここだけの話、自分がエンジニアを目指すきっかけになったのでたいへん尊敬しているのです

aws-cdk探訪: AppsとStacksの関係

最近、TypeScriptで癒されたさ重視でaws-cdkを見ています。

aws-cdkはCloudFormation (以下CFn) をよりプログラマブルに扱う高級な・抽象的なライブラリと見てよく、概念もほぼ対応しているのですが、Appsという概念はaws-cdkに固有のもので特色たりえるものに見えるので、これについてメモします。

基本的に公式ドキュメントに書いてあることの咀嚼しなおしなので、既に読んで理解している人には新しい情報は無いです。

ざっくりとした捉え方

  • aws-cdk Stacks = CFn stacks
  • aws-cdk Apps = 複数のaws-cdk stacksをまとめたもの
  • 変更のデプロイはappに含まれる特定のstackを指定するとよい

aws-cdk Appsとは

公式ドキュメントによると:

The main artifact of an AWS CDK program is called a CDK App. This is an executable program that can be used to synthesize deployment artifacts that can be deployed by supporting tools like the AWS CDK Toolkit, which are described in AWS CDK Tools.

Apps — AWS Cloud Development Kit

……とのこと。

この説明はランタイムとしてのaws-cdkに寄った説明でどういった概念なのか掴みづらいです。

実はStacksの説明のほうがわかりやすくて、以下のように書いてあります:

Most production apps consist of multiple stacks of resources that are deployed as a single transaction using a resource provisioning service like AWS CloudFormation.

Stacks — AWS Cloud Development Kit

ここでいう Most production appsaws-cdk Appsを指します (恐らく)。
大抵のAppsは複数スタックからなるでしょう、ということです。

さらにAppsのドキュメントにあるコード例がわかりやすいです:

import { App } from '@aws-cdk/cdk'
import { MyStack } from './my-stack'

const app = new App(process.argv);

const dev = new MyStack(app, { name: 'Dev', region: 'us-west-2', dev: true })
const preProd = new MyStack(app, { name: 'PreProd', region: 'us-west-2', preProd: true })
const prod = [
    new MyStack(app, { name: 'NAEast', region: 'us-east-1' }),
    new MyStack(app, { name: 'NAWest', region: 'us-west-2' }),
    new MyStack(app, { name: 'EU', region: 'eu-west-1', encryptedStorage: true })
]

new DeploymentPipeline(app, {
    region: 'us-east-1',
    strategy: DeploymentStrategy.Waved,
    preProdStages: [ preProd ],
    prodStages: prod
});

process.stdout.write(app.run());
Apps — AWS Cloud Development Kit

上記コードは1つのappにdev, preProdといった開発環境用のstackを追加しています。
これらステージごとのstackなどの集合がappであるという捉え方です。

デプロイはどうするか

これもCLIのヘルプを読めばわかりますが、各コマンドは対象となるstackを指定することができます。

cdk deploy Dev
...
Apps — AWS Cloud Development Kit

指定しなければ紐付くすべてのstackが更新されます。

aws-cdkの基礎にCFnが存在し、CFnの基本デプロイ単位はstackであることを思い出すと理解しやすい挙動だと思います。

私の環境ではdev, staging, productionといった環境ごとにデプロイは分けていたので cdk deploy dev-app のように実行するのがよさそうということがわかりました。

aereal.orgをGoogle Cloud Platformに移した w/Cloud DNS, Cloud Storage, Deployment Manager

aereal.org

長らくさくらのVPSホスティングしていたのだけれども運用がめんどうになったのでこれを機にGCPへ移行した。

登場人物は:

……の4つ。

Google Cloud Storage

GCP版S3みたいなオブジェクトストレージ。使い勝手はかなり似ていて、S3同様にウェブサイトとして公開する設定もある。

ここにindex.htmlとか画像を置いて後述するGoogle Cloud CDNのoriginにする。

Google Cloud Load Balancing

AWSでいうALB/NLBにあたるもの。ALB相当がHTTP(S) Load Balancingになる。
余談だけど日本語ドキュメントでは「HTTP負荷分散」と訳されていて、動名詞なのかプロダクト名なのかわかりにくい。

パスやホストに対してルールベースでbackendへリクエストを送ることができる。
使い込んでいないけれどALB/NLBと機能の差異はそんなにないようにみえる。

Google Cloud CDN

GCPが提供するCDNサービス。AWSでいうCloudFront.

invalidation APIがあったり、普通なかんじ。

Cloud CDNに限らないけれど全体的にGCPは安めな気がする。

Google Cloud Deployment Manager

AWSでいうCloud Formationみたいな構成管理するグッズ。

YAMLを使うのはCFnと同じだけれども、変数展開などはJinja2というAnsibleでも使われているテンプレートエンジンを採用している。
既存のよくできた技術を再利用する筋のよさは後発のGCPならではってかんじ。

リソースのプロパティ定義は既存のREST APIのリクエストパラメータと同じ名前・同じスキーマなのでそちらを参照せよというドキュメントになっており親切。
(例: REST Resource: targetHttpsProxies  |  Compute Engine  |  Google Cloud

gcloud deployment-manager types list で使えるリソース定義の一覧が得られるので、これでDeployment Managerで対応しているか確認できる。
前述の通りプロパティ定義はREST APIと一致しているので、このリソース定義名からREST APIのドキュメントを引けばよくて便利。

aereal.orgのデプロイ設定は GitHub - aereal/gcp-deployment-aereal.org に置いたのでご覧ください。

感想

GCPはぼちぼち触っていたけれどDeployment Managerはよく出来ているし筋がいい印象を持った。

会社ではAWSを使っているのでおもしろさ重視でGCPでもっと遊んでいきたい。

aws-cdkを見ている: policyの変換がすごい

aws-cdkを見ている。TypeScriptもしくはJavaAWSの構成管理ができる。CloudFormationのプログラマブルなやつと考えるとよい。

TypeScriptは癒しなので癒されました。今日は感動ポイントをご紹介。

policyの変換がすごい

CFnのなかでもS3のbucket policyを書くのは最もダルい作業のうちのひとつに数えられると思いますが、aws-cdkだとこう書ける:

    const bucket = new Bucket(...);
    const policy = new PolicyStatement(PolicyStatementEffect.Allow);
    policy.addAction("s3:GetObject");
    policy.addResource(this.arnForObjects("*"));
    policy.addPrincipal(new Anyone());
    bucket.addToResourcePolicy(policy);

これが cdk synth でこうなる:

    XxxBucketPolicy81AF88BF:
        Type: 'AWS::S3::BucketPolicy'
        Properties:
            Bucket:
                Ref: XxxBucketEDCC903C
            PolicyDocument:
                Statement:
                    -
                        Action: 's3:GetObject'
                        Effect: Allow
                        Principal: '*'
                        Resource:
                            'Fn::Join':
                                - ""
                                -
                                    -
                                        'Fn::GetAtt':
                                            - XxxBucketEDCC903C
                                            - Arn
                                    - /
                                    - '*'
                Version: '2012-10-17'

すごい!

JavaScriptのtemplate literalでよいかんじに変換されていそう。

よくあるワンソースで適当に変換エンジン作りましたというかんじではなく、ちゃんとTypeScript (ECMAScript) でネイティブにいいかんじに実装していこうという気概が感じられて、今後に期待が持てますね。

その他

cdk synth で出力するYAMLが、既存のCFnのYAMLと完全に互換を保てたら脱出も楽になるからいいな〜とおもっているのだけれど、そういうオプションはざっと見たかんじなさそう。

migration pathみたいなissueはあるのでなにも計画がないわけではなさそうだけど、あれだったらP-Rを送っていきたい。

tslintで有効になっているruleをpreset由来も含めて一覧する

const { resolve } = require('path');
const { Linter, Configuration: { findConfiguration } } = require('tslint');

const tslintJsonPath = resolve(__dirname, '../tslint.json');
const { results: config } = findConfiguration(tslintJsonPath);

const formatRule = (rule) => `${rule.ruleName}:${rule.ruleSeverity}`;

const linter = new Linter({ fix: false });
const rules = linter.getEnabledRules(config, false);
rules.map(r => formatRule(r)).sort().forEach(r => console.log(r));

presetをextendsするのが主流だけど、このpresetってデフォルトでどういう設定を提供するんだっけ? と調べはじめたりしてまあまあ不毛だし、そういうのとってくるAPIあるでしょと思い調べたらやはりあった。

内部向けっぽいAPIを無理矢理使っているわけでもないので、まあまあ安定しそう。

BPMと音価を入れるとディレイタイムを計算してくれるやつをReactで作った

Reactでちょっとした計算機を作ろうと思い、せっかくなのでStorybookを試してみることにした。

できたもの

GitHub - aereal/delay-time-calc

f:id:aereal:20180521112626p:plain

BPMとフィードバックさせたい音の音価を入れるとディレイタイムがミリ秒で出力される。

BPM 120で8分ディレイをかけたかったら250msec.にすればいい、みたいなことが手軽に計算できる。

いま触って気付いたけど付点8分のときの計算まちがっている気がする……。

使ったもの

create-react-appで雛形を作り、Storybookのドキュメントを読んでセットアップをした。
TypeScriptでstoryを書くのに一手間必要だったが、ものはできた。

変更内容は以下の通り。自動生成するコマンドの実行結果と手作業で加えた変更はコミットを分けているので、わりとわかりやすいのではないかと思う:
https://github.com/aereal/delay-time-calc/compare/94b844e12a73fd91b52d21a542b3566e19ab9151...eb106a6dda7e606a40de1453a56d4e642554ae14

TypeScriptでstoryを書くためのあれこれは typescriptでReact Storybookを試す。 - Qiita が参考になった。

感想

  • storybookは便利
    • コンポーネントがたくさんある・たくさん作っていくプロジェクトではカタログとして十分便利そう
    • storybookがあることで、ここで触るのに過不足ない
    • addonを入れるとMaterial-UIのスタイリイングをstorybook上でプレビューできるのめちゃくちゃ便利
  • とりあえずはじめるときはcreate-react-appを使うとよさそう
    • `npm run eject` できるしWebpackの設定をだいたいいいかんじにしてくれるし
    • まあこの先メンテしていけるかっていう話はあると思うが、少なくとも初速は出る・差分アップデートで習得できる、というところをよしとできるなら
    • scripts/test.jsとか、テスト実行をいじりたいと思ったときにメンテできるのかは既に不安ではあるが……

HTTP::Message#content($bytes)を呼んでもcontent-lengthは計算されない

HTTP::Request#content($bytes) もしくは HTTP::Request#add_content($bytes) を呼んでもcontent-lengthは自動で計算されず、0になる。

なのでそのままリクエストを送ると、ちゃんとcontent-lengthだけbodyを読む実装はボディが空だとみなすのでちゃんとcontent-lengthを計算しなければいけない。

Plackの実装に慣れていたのでびっくりした。

    my $req = HTTP::Request::Common::POST($url);
    my $json = JSON::XS::encode_json($payload);
    $req->content($json);
    $req->as_string;

HTTP::Request#as_string した結果:

POST http://example.com/api/issuance
Content-Length: 0
Content-Type: application/json

{"status":"success","expires_at":"2018-04-09T12:19:26+09:00"}

Content-Length: 0 になっていることが確認できる。

AWS CloudFormationメモ

  • aws cloudformation package はS3にfunctionとかいいかんじにアップロードして、そのARNが埋められてそのまま aws cloudformation deploy 実行可能なテンプレートを出力してくれる
    • そのパスを指定する引数が --output-template-path
  • cloudformation自体はS3になにをアップロードするのは不可欠ではない、lambda functionとか追加のファイル (local artifacts) が必要なときはpackageするとよい
  • lambdaとかつかわない場合はいきなりdeployできる

id:dekokun ++

参考:

Go: 外部ライブラリを使ったコードをいいかんじにDIしてテストする話

結論

  • 実装ではなくインターフェースに依存させる
  • Goのinterfaceは実装の明示が必要ないので便利

aws-sdk-goのスタブ

外部ライブラリの例としてaws-sdk-goを使ったこういったコード例を考える:

type CertificateFetcher struct {
  client *dynamodb.Client
}

func New(client *dynamodb.Client) *CertificateFetcher {
  return &CertificateFetcher{client: client}
}

func (f *CertificateFetcher) GetCertificate(domain string) (string, error) {
  resp, err := f.client.GetItem(...)
  if err != nil {
    return "", fmt.Errorf("...")
  }
  key := resp.Item["key"]
  if key == nli {
    return "", fmt.Errof("...")
  }
}

DynamoDBと通信させずにエラーのハンドリングや *dynamodb.GetItemOutput から値を取り出す処理などについてテストしたいが、そのためには *dynamodb.Client を差し替える必要がある。

実装を差し替える範囲が広すぎると実際に実行されるコードに対するカバレッジが低くなりテストの意味がなくなるので、適切な境界を見つけてそこで差し替えられるとよさそう。

実際にどうやるか、結論としては CertificateFetcher*dynamodb.Client ではなく必要なメソッドが定義されたinterfaceに依存させるとよい。

例:

type DynamoDBClient interface {
  GetItem(item *dynamodb.GetItemInput) (*dynamodb.GetItemOutput, error)
}

type CertificateFetcher struct {
  client DynamoDBClient
}

func New(client DynamoDBClient) *CertificateFetcher {
  return &CertificateFetcher{client: client}
}

func (f *CertificateFetcher) GetCertificate(domain string) (string, error) {
  resp, err := f.client.GetItem(...)
  if err != nil {
    return "", fmt.Errorf("...")
  }
  key := resp.Item["key"]
  if key == nli {
    return "", fmt.Errof("...")
  }
}

テストコード例:

func TestGetCertificate(t *testing.T) {
  stubClient := &StubDynamoDBClient{}
  fetcher := New(stubClient)
  // ...
}

type StubDynamoDBClient struct {}

func (c *StubDynamoDBClient) GetItem(item *dynamodb.GetItemInput) (*dynamodb.GetItemOuput, error) {
  // ...
}

Goのinterfaceは所与のメソッドを実装していれば特別なアノテーションをつけずとも構造体がinterfaceを実装しているとみなされるので、実装を変更できない外部ライブラリに対してアドホックにinterfaceを定義できるので便利。

このようにインターフェースに依存させてDIしやすくするというのは、たとえばScalaにおけるcake patternなど他にも例があります。

吉祥寺.pm mini #012 に参加した

kichijojipm.connpass.com

 

参加した。酔った勢いで参加登録し、新幹線と宿を予約をし、東京は吉祥寺に舞い降りました。

ライブと仕事でしか東京に行かないので西のほうに行くのは新鮮。

 

設計というテーマもさることながらしんぺいさん (id:nkgt_chkonk) を見に行くチャンスなので京都から参加登録した。

 

設計という抽象的な話題についてうまく他人とコミュニケートできる・それだけのプレゼンテーションができるというのはすごいことだと思っている。

参加して設計についてもちろん深い考察が得られたらいいと思っていたけれど、それ以上に自分が感じる「設計についていいかんじに他人にプレゼンテーションするために必要な能力は何なのか」について手掛かりが得たいと思っていた。

 

結論から言うと、それは得られた。簡単にまとめてみると:

  • 議論に参加する人間が解決できる (結論を出せる) 単位まで問題を分解する
  • 分解された子孫テーマ間の繋りを補強・説明する知識を持っている

……という能力およびそれの効果的な発揮に裏打ちされているのだと理解した。

具体的には:

  • 「良い設計とは何か」というテーマを、たとえば「DRY原則をいいかんじに適用する例とはなにか」くらいに分解する
  • さらに「DRY原則を適用していいかんじになっている」状態を「他の設計原則に違反せず達成されているか」くらいにさらに分解する

……という風に表れている。

「今あえてDRY原則に向き合う」というスライドはよかったです。

speakerdeck.com

こうして考えてみるとティーチングに対しても問題解決の原則を持ち込んでいるということであって、目新しさはない。ないが、当たり前のことを当たり前にやるということを実践できることは非凡ではないと思う。

 

京都からいきなりやってきたけど非常に楽しく参加させてもらえてありがたかったですし、個人的にはインターネットで見かけたおもしろそうな人を見に行くために出かけるのはインターネット原体験っぽさがあってよかった。

終電がなくなって吉祥寺から宿をとった京橋までタクシーに乗ったら「京橋? (舌打ち)」って言われたり「京橋ってどこですか?」って言われたり、深夜の急カーブ高速道路を120km/hで駆け抜けて恐怖を感じたり久しぶりにメチャクチャな目にあったけどそれもよかった、また吉祥寺いきます。

GoのデバッグはdelveとVisual Studio Codeが便利

delveとは

Go向けのデバッガで、ステップ実行とかブレイクした行のレキシカル変数が見えたりといった基本的な機能を提供しつつ、dlv debugコンパイルしつつ実行 (go run) したりgo(1)とほどよく統合されている。

後述するheadlessモードがあっていわゆるリモートデバッグが可能。

delveをmacOSにインストールする

公式のドキュメントではbrew install go-delve/delve/delve一発で済むように書かれているが実際はうまくいかなかった (´°̥̥̥̥̥̥̥̥ω°̥̥̥̥̥̥̥̥`)

==> Installing go-delve/delve/delve
==> Downloading https://github.com/derekparker/delve/archive/v1.0.0.tar.gz
==> Downloading from https://codeload.github.com/derekparker/delve/tar.gz/v1.0.0
######################################################################## 100.0%
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.
==> Generating dlv-cert
==> openssl req -new -newkey rsa:2048 -x509 -days 3650 -nodes -config dlv-cert.cfg -extensions codesign_reqext -batch -out dlv-cert.cer -keyout dlv-cert.key
==> [SUDO] Installing dlv-cert as root
==> sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain dlv-cert.cer
Last 15 lines from /Users/aereal/Library/Logs/Homebrew/delve/02.sudo:
2018-02-28 11:11:35 +0900

sudo
security
add-trusted-cert
-d
-r
trustRoot
-k
/Library/Keychains/System.keychain
dlv-cert.cer


If reporting this issue please do so at (not Homebrew/brew or Homebrew/core):
https://github.com/go-delve/homebrew-delve/issues

These open issues may also help:
Upgrade to delve fails https://github.com/go-delve/homebrew-delve/issues/20

紹介されているissueを見てみると証明書を生成してインポートするスクリプトを手で実行したらうまくいったと書いてある。

実際に実行した手順はこういうかんじ:

✘>﹏<✘ < cd $(brew --cache)/
✘╹◡╹✘ < tar xzf delve-1.0.0.tar.gz
✘╹◡╹✘ < cd delve-1.0.0
✘╹◡╹✘ < bash ./scripts/gencert.sh
✘╹◡╹✘ < brew install go-delve/delve/delve

delveをインストールしたら sudo pkill taskgated を実行してtaskgatedを再起動する。
プロセス間通信を監視するデーモンらしく、bash ./scripts/gencert.shで生成・インポートした証明書を読み込みしなおす必要がある。

Visual Studio Codeとvscode-go

Visual Studio Codeは便利、GoやTypeScriptを書くとき最近はもっぱらこれ。

vscode-goというGoを書くときの各種便利サポートを追加してくれる拡張を入れる。

Debugging Go code using VS Code · Microsoft/vscode-go Wiki · GitHubが詳しい。

Visual Studio Codeでデバッグ

Visual Studio Codeでリポジトリを開きつつ Debug → Open Configurations でデバッガの設定 (JSON) を開く。

設定中の moderemote にする。remoteにすると別プロセスで既に起動しているデバッガーに接続する。

Debugging Go code using VS Codeにあるように、シェルで dlv --listen=:2345 --headless -- などと実行してデバッガーを起動する。

あとはVisual Studio Codeの Debug → Start Debuggingを押すとデバッガー開始できる。

gyazo.com

行頭を押すとブレイクポイントを設定できまるでIDEのよう〜。

ステップ実行もできるしレキシカル変数も見れて便利!!!!

Dockerのコンテナ内でapt-cache searchしてパッケージが見つからないとき

rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* してないか確認する。

コンテナのプロビジョニングを試行錯誤しているときに docker-compose run --rm app bash とかやりがちだけど、最初の方に apt-get update && apt-get install && rm -rf /var/cache/apt/archives/* /var/lib/apt/lists/* しているとaptのキャッシュもリポジトリも消えるので、あるべきリポジトリが見つからないように見えることがある。

探すときはpackages.debian.orgを見るとかするとよい。

unzipは展開先のディレクトリ・ファイルが存在したら上書きしていいか聞いてくる

スクリプトで自動化したいときは困る。

そういうときは unzip -o /path/to/kure.zip のように -o オプションを使うとよい。

       -o     overwrite existing files without prompting.  This is a dangerous option, so use it with care.  (It is often used with  -f,  how-
              ever, and is the only way to overwrite directory EAs under OS/2.)