FFX歌舞伎を見てきましたの感想(ネタバレあり)

FFX歌舞伎を見てきました(なんと初日)。
歌舞伎の教養は全く無いけど(知っているのは中村さんがたくさんいることと、XX屋!という掛け声があることと、おっとっとみたいな動きの決めポーズがあるということくらい)、FFXが好きなので見に行ってみました。
ポスターのビジュアルと、前半のジェクトシュートの演出を見て(事前に公開されていたYouTube動画や特集動画は見ていません)、むむ・・これは・・!?と若干ドキドキしておりました。しかし前半クライマックスのシーモア戦の、特にルールとの舞ではより歌舞伎感(自分にとっての歌舞伎感)が出てちょっと安心しつつ後半はどうなんだろうと引き続きドキドキ・・・。ところが後半は、前半よりもずっと歌舞伎感(自分にとっての。以下同じ。)を感じることができて個人的には満足でした。召喚獣バトルは、歌舞伎を全然知らない自分ですが「おお!歌舞伎!」と感じられるものでとても素敵でした。

召喚獣バトルがとても素敵だったしで、もっと衣装は着物感・歌舞伎のあるデザインでも良かったのではと思いました。ルールー・ユウナレスカ・シーモアの衣装はより着物感があり素敵でした。(歌舞伎を知らなさすぎるため一般的にどういう服装なのかはわかりませんが・・・)
ベベルの結婚式ももはやベールなしで角隠し・綿帽子?和装の結婚式の服装と同じでも良かったのではとも思いましたが、和装すぎると誓いの口付けに違和感が出るかもなのであれで良かったのかもしれません。
アニマを映像ではなくで表現するハードルはとても高いけれども、後半の召喚獣バトルが素敵だった分、あの雰囲気で表現されたアニマも見たかったなあとも思いました。
※後日追記:公演を見た後にYouTubeの特集動画を見始めたのですが、衣装へのこだわりもしっかりあり、またいろんなキャラクターの服装も歌舞伎のXXベースでデザイン等自分の歌舞伎のイメージ・衣装のイメージがかなり限定的だったことによる感想に過ぎなかったようです・・・!特集YouTubeを全体的に目を通し歌舞伎に対する知識を少しでも増やして再度鑑賞するとまた違った感想になりそうです。

後半では、出語りというのでしょうか?三味線や歌でナレーションをされる方もみえるところに時々出てきて、その方達が「スピラの〜」とかFFX用語を歌舞伎の口調で歌われていて、そこも「おお!歌舞伎!」と感じられてよかったです(笑) 好きな言葉は心付けって(笑)
前半でいきなり歌舞伎歌舞伎してしまうと観客は耳も慣れていないしで世界観に入れなくなる可能性があるから、前半で多少慣らした後に後半で歌舞伎らしさをより出してきたのかなと思いました。昔友達に誘われて行った歌舞伎(歌舞伎座で見たのでたぶん歌舞伎です。)は、何を言っているか全くわからずで音声解説を聴きながら若干眠気で記憶が飛んだシーンもあったのですが、この新作歌舞伎はゲーム中のセリフも忠実に再現されていて、歌舞伎独特なセリフの言い方部分もFFXの背景知識があるためかほぼ理解ができ、ストレスなく鑑賞することができました。
こうして振り返ってみると自分は歌舞伎感を求め気味かもしれませんが、異界での人の表現など現代技術を駆使した表現や、左右の映像で臨場感を表現する部分は良いと思いました。
※ネット記事などを読むとXXは歌舞伎のYYの動きで表現している等自分が気づいていなかったところがたくさんあり、自分の歌舞伎への理解度が足りないために深くまで感じ取ることができなかった可能性もかなり大きいです。

配役も素敵で原作のイメージを壊さないようにとても配慮されているなあと思いました。一般オーディションとかではなく歌舞伎役者で人を探すのだから相当大変なのでは・・?役者さんの演技力もすごいなあと思いました。特にユウナの方(中村米吉さん)は男性がこんな声を出せるのか、と驚きました。立ち居振る舞いもユウナを感じました。ルールーはthe女形という感じで声感は本家とは違いはしましたがルールーらしさがひしひしと表現されていて魅力的でした。坂東彌十郎さんのジェクトはぴったりでした。ワッカもワッカ、ブラスカ様もブラスカ様でした。

音楽も和風アレンジがされていて素敵でした。サウンドトラックが出たら欲しいです。いろんな曲もあれこれ使われていて耳でもかなり楽しめました。
公演中に「あれ?これなんの曲だっけ・・?」って思った曲でモンスター訓練場の「勇ましく進め」がありました。まさかこの曲が出てくるとは思わなかったけど、とてもシーンにマッチしていて良かったです。

ストーリはとても上手にまとまっていると感じました。原作だと別のシーンで発生するイベント・セリフもほぼ違和感なく1つのシーンでまとめられていました。そして、いろんな方が言及されていますが原作への愛を感じました。ゲームで印象的だった・重要なセリフだけでなくちょっとしたセリフも丁寧に再現されていて、自分がプレイした時のウン10年前を思い返しつつ(何度シーモア戦・ユウナレスカ戦に挑んだだろうか・・・)FFXの世界にどっぷり浸かることができました。
FFXが未経験だった方にも伝わるように言葉の説明も挟んでおり(何気なく動画を再現してくれるスフィアも、記憶媒体装置と言わないとなんだありゃってなりますよね笑)、未履修の方もストーリーを楽しめる物だったのでは?と思います。
シーモアについても、シーモアの過去の再現が入っていたり最期ユウナにあんなに固執していた原因に気付いたり(確か原作では無いセリフでしたよね・・?)、よりすんなり話を受け入れやすくわかりやすくまとまっているなと感じました。
バトルも、原作を尊重しつつも忠実な再現ではなくより魅力的にみえるような表現をされており見事に舞台化したなあと思いました。

長時間の上演でしたがクッションのおかげかお尻や腰は痛くなく、また自分は席が端で若干足も伸ばせて快適に鑑賞できました。(端ではない席は少し狭そうに感じました)役者さんたちがあの長時間にわたる演技を何日間も連続でされることに衝撃を受けております。

9時間の長丁場でしたが、見に行って良かったです。またFFXをやりたいですねえ。

硝子の塔の殺人を読んだ

おすすめ度:3/3

 

読んだきっかけ

・オーディオブックのサービスで1月中は無料だった&人気らしいと言うので聞いてみました。ミステリーはAmazonプライムで無料だったシャーロックホームズとかを一部読んだくらいで、現代の小説だとだいぶ昔に容疑者Xの献身を読んだくらいで親しみがあるわけではないです。

 

オーディオブックについて

・オーディオブックで読みました。(聞きました)

・本で読むと、登場人物の喋り方も雰囲気も自分の頭の中で作り上げていくことになると思います。一方オーディオブックだとその部分が声優さん達の演技によって外から作り上げられるため、慣れるまでは違和感(自分のイメージと声優さん達の演技の違い)を持ちながらの読書でした。でも慣れてからはより自分が登場人物達の会話をそばで聞いているような気分になれて臨場感がよりあったと思います。

・本で読むならそこまで感じなかったと思うのですが、声で聞くとヒステリックなキャラクターの声がやかましい、いちいち怒鳴るキャラクターもますますうるさいというのを強く感じました。また碧さんも、多分字面で読むよりもより話し出したら夢中になって止まらない感が強くて面倒臭い人だなと何度も思ってしまいました。そこはオーディオブックならではの良さでもありデメリット?特徴?でもあるかなとは思います。
・前オーディオブックで「サピエンス全史」を少しだけ読んだことがあるのですが、恐ろしく頭に入らなかった当時とは違って小説だったからかスムーズに頭に入ってきました。本程には気になる部分を手軽に何度もは読み返せない(巻き戻しはできるけど端末を手提げにしまっているので操作が面倒なだけ)オーディオブックだからこそある程度気楽に読める本がいいのかもしれません。あとは自分の興味のある内容かどうかも大きそうです。

・何より、仕事で疲れた目を休められるのが最強だと思いました。通勤に1時間かかり歩く時間も長いのですが、その時間も楽しみながら過ごすことができて通勤のだるさがだいぶ軽減した気がします。聞く読書中に目の疲れがとれれば本を読んだりと選択肢を増やすことができて良いです。


ストーリーについて

・最初に犯人が明らかになってて、でもその人の動機には十分納得いくものがあったし殺された人は殺されても仕方ないなと正直思ってしまう言動をしておりで、なんとか頑張れうまくことよ運んでくれという気持ちでいっぱいでした。
・全くストーリーが想像できなくてドキドキと驚きの連続で、あっという間にどんどん再生を進めていきました。最後の肝心のネタバレ部分の中で出てきたトリックの一部が思い出せず、どうやって犯行を行ったのかが曖昧な理解という状態なのですが、明らかになった時はうまいことハマってるなあーーと感心したのは覚えています・・・!
・最後はああよかったと安堵しました。幸せに生きて欲しい人が幸せに生きてくれているのは嬉しいです。(かわいそうな方もいましたが・・・)

・読者への挑戦状は全く歯が立ちませんでした・・・。

犯人の動機について

・ネットのコメントを読むと納得いかない人も割といるようですが、自分としては割と納得はいきました。辛い経験から思想やらがおかしくなってしまうのはあり得ると思うし、小説の中での言動を色々振り返っても確かにこの人ならそう言う思想でやりかねないかもしれないと感じました。(最初の人以外までも殺されたのはかわいそうだなあと思いましたが)

 

ミステリー小説について


・仕事で疲れているところで人の死やら駆け引きドギマギやらはちょっと疲れますね・・・。小説の中でいろんな実在の小説に言及されていてそれらも面白そうだなあと思いつつ、しばらくはミステリー以外の小説にチャレンジしたいと思った次第でした。

『技術書の読書術』レビュー

2023年1冊目の本として、『技術書の読書術』を読みました。

Amazon.co.jp: 「技術書」の読書術 達人が教える選び方・読み方・情報発信&共有のコツとテクニック eBook : IPUSIRON, 増井 敏克: Kindleストア

↑※特にアフィリエイトとかはやってません

なぜ読んだか

  • IPUSIRONさんをtwitterでフォローしており(ハッキングラボか何かきっかけでフォローした気がする)、IPUSIRONさんがちょこちょここの本の紹介をしており気になったため
  • 技術書を読んでも頭に残ってない自覚があって、仕事や家庭で時間も限られている中どうにか読書効率を上げられないかと悩んでいたため。

どのくらいで読んだか

  • 1日で読めました。(簡単にメモを取りながらだけど休み休みで6時間くらいで読めたような気がします)なお、読書記録の取り方や英語論文の読み方などの具体的手順も丁寧に記述されており、その辺りは自分なりにやりやすい方法は身につけていたのでざっと参考程度に読み飛ばしました。(なお1回目からメモを取りつつ読んだのは、今まで自分がそうしてきたからです)

おすすめ具合

  • 会社のLTで紹介したいと思いました。若手も多いので、若いうちから技術書を臆さずにどんどん読むのはやっていくと素敵な糧になりそうです。
  • 現状自分なりに読書術が身についている人には不要かもと思いますが、自分のように読書術迷子の人にはよい参考になると思います。また新年にこの本を読むことで、この一年頑張ってみようかなという信念の決意がみなぎってよかったです。

読んで思ったこと

  • 二人の人がそれぞれの読書術の紹介をする構成になっており、前書きにあった通り確かに異なる意見を出してて、どちらも納得するところ・それは取り入れなくていいかなというところ両方あって面白かったです。一人の人が書いた本ではないからこそでいいとこ取りができてお得です。
  • 自分のレベルに合った本を見つけるのはやはりみんな難しいよねと思って安心しました。とはいえやはり技術書は安くはないので、本で紹介されてたように前書きや目次あたりにしっかり目を通して購入したいなと思いました。Kindleの立ち読みだと本文の方は目を通せないから書店にも足を運んだ方がより自分に適した本を見つけられるのかなとは思います・・・。とはいえ書店に行けないから買わないではなくどんどん買って読んでいきたい次第です。
  • 著者はあまり気にしてなかったので、少しずつ気にして行こうと思いました。まだ著者の好き嫌いをするほど本を読んでいないのが現状なので、参考として。
  • 同じ本を3回読む、というのは、自分の悩みであった技術書の中身が頭に入らない問題の解決策として良さそうだと感じました。確かに、業務上必要になって1年ほど前に読んだ本(自分の読書メモ付き)を最近読み返したのですが、かなりすんなり読み進められたし頭にも残った実感がありました。(業務経験が増えて仕事と本の内容の紐付きを強く感じられたりしたのも大きいかもしれないが) ただし、同じ本を間を空けず連続して3回読むのは多分自分の性質的にますます読み飛ばしてしまって3回読んでも頭に残らない事態を招きそうな気がするので、少し期間を空けて読み返す用にカスタマイズしたいなと思いました。
  • 似た分野で3冊読むのも確かに効果的な読書術だと思います。これも実感としてあります。自分の経験としてはDBスペシャリストの勉強用に参考書及び過去問の解説で論理設計についての文章をあれこれ読んだのち、DBの論理設計に関する本を読みました。並列ではなく直列で読み、さらに冊数も3冊と言っていいのかわからないという中途半端な実施具合ですが、それぞれで言われている内容が相互に通じておりわからない箇所は別の本を参照して理解を深めたり読み終えた本の内容を改めて把握したりと言ったことができて、読書効率を高められたと思っています。また、その後DB設計のアンチパターンの本も2冊直列で読みましたが、相互に参照しながら理解を深めることができたと感じています。
  • 一点突破読書法もいいなと思いました。自分は突破するほどの量ではないのですが、2022年はDB設計に関する本をあれこれ読んで(資格勉強期間が長かったので、過去問解説もたくさん読んだけども本としては読了は4冊です・・(汗))、webのいろんな記事も理解できるようになった気がしますし、仕事で「DB設計やらせてください」と意思を伝えるようになりました。(割と自分は受け身だったりこだわりがなかったので、自分としては大きな進化です!)また今年もテーマを決めて読みたいなと思っています。
  • 読書は正直技術書以外は軽視していた自覚があるので、人生を変える一冊との出会いと言う観点で読書をとらえているのは自分にはない観点でした。(人生を変えるのは、旅行とか人との出会いとかライフイベントとか仕事での経験によるものとしか考えておらず、本で人生が変わると言う考えがそもそもなかったです。読書を見下すとかではなく本当に観点として自分にはありませんでした。)人生を変えたいという思いがあるわけではないですが(でもそんな1冊にであうってワクワクしそうですね)、純粋に自分の視野を広げるためにも、技術書以外の読書にも手を出していきたいなと思いました。IPUSIRONさんのTwitterをフォローしていると面白そうな本の情報がたくさん流れてくるのでおすすめです(笑)
  • 自分の読書時間は通勤時間の合計2hくらい(歩く時間もあるので実質40minくらい)ですが、目が疲れている帰宅時にもオーディオブックや音声読み上げを用いて読書を進めていきたいなと思いました。(時間潰しのためにだらだら過ごすのは避けたい)

2023年の決意

  • 1ヶ月に1冊本を読む(技術書以外も含む)
  • 読んだら短い文章でも良いのでブログにアウトプットする
  • 技術書は1年以内に3回読む

ブログの次の更新タイミングがどうなるか自分でもドキドキしていますが(笑)、まあ無理なら無理で、そこで投げ出すのではなくできる時にやって行こうと思います。

2024年の追記

  • 本は1ヶ月に1冊もしくはそれ以上のペースで読めたこともありました(技術書じゃなくてぱらっと読める小説も読んだので)
  • アウトプットは、自分用メモにぱらっと残すことが多く、人の目に触れる形でのアウトプットはほぼできていないですね。。。
  • 技術書は3回は読めなかったな・・・資格の勉強で2回読んだのが精一杯です。
  • でも久々に本を読んだ一年という感じがしたのと、X(Twitter)で面白そうな本を紹介するアカウントをフォローして面白そうな本をリストアップしているので今後通勤時に読んだりしていきたいなあと思っています(こういう心構えになっただけでも大きな進歩!笑)

TypeScriptでFirestoreからデータを取り出す(FirebaseSDKv9)

前置き

「実践編:React NativeとFirebaseで作るiOS/Androidアプリ:お店レビューアプリ開発編」 www.udemy.com にトライしております。(Expoおもしろい〜)

Firebaseのバージョンが前のもので解説されており、せっかくなのでV9で書きたいなと思ったのですが思いのほか書き方が過去バージョンとだいぶ異なっており混乱したので整理しました。

※講義内で言及されている通りV9での動作確認はまだのでこの先V9の書き方だと詰まるかもしれないです。
※講義10までしか見ていない段階なので、この先も視聴して内容を適宜修正するかもしれないです。

2022/3/12追記
今のところはExpoでFirebaseSDKV9を動かすのは無理かもしれないです。
stackoverflow.com
github.com
でも修正プルリクが動いているようなのでもうすぐ動くようになりそうです!楽しみ&感謝

環境

node-version:16.13.2
typescript:4.6.2
firebase:9.6.8

Firestoreの状態

f:id:Tiratom:20220310204733p:plain
Firestoreのデータの状態

ドキュメント1つ分のデータ取得の流れ

では、FirestoreからID=1の name="ビストロ品川", place="品川" のデータを取得する方法について整理します。

手順概要

  1. ドキュメントのデータ用の型を用意する
  2. コレクション(ドキュメントを束ねる単位。ここでは写真の一番左列のshops)への参照を取得する
  3. 2の参照をもとにドキュメント(ここでは写真の真ん中列の1)への参照を取得する
  4. 3の参照をもとにドキュメント(ここでは写真の右列の内容が該当)のデータを取得する
  5. 4で取得したデータから必要なものを取り出す(ここでは写真の右列でいうnameやplaceなど)

手順詳細

1. ドキュメントのデータ用の型を用意する

最終的に取り出すデータの内容に合わせて型を用意します。取り出したデータを扱っていく上で型があると安心便利なので用意します。

export type Shop = {
  name: string,
  place: string
}

2. コレクション(ドキュメントを束ねる単位)への参照を取得する

先ほどのスクリーンショットでいうと左列の中のshopsへの参照を取得します。ここで先ほど用意した型でアサーションすることで、最終的なデータ取得時にShop型で扱えます。

const shopsColRef = collection(
  firestore,
 "shops"
) as CollectionReference<Shop>;   

3. 2の参照をもとにドキュメントへの参照を取得する

ここではIDが1であるドキュメントへの参照を取得しています。

const shopsDocRefId1 = doc(shopsColRef, "1");

4. 3の参照をもとにドキュメントのデータを取得する

非同期処理です。

const shopsDocId1 = await getDoc(shopsDocRefId1);

5. 4で取得したデータから必要なものを取り出す

data()で一般的に想像するいわゆるデータを取得できます。(他にはid()でIDを取得したりもできます)

const shopsDataId1 = shopsDocId1.data();
console.log(shopsDataId1);

上記の出力は、Object { place: "品川", name: "ビストロしながわ" } といった感じとなります。

コレクション1つ分(複数ドキュメント)のデータ取得の流れ

次に、Firestoreからshopsのコレクションに含まれるすべてのドキュメントのデータを取得する方法について整理します。

手順概要

  1. ドキュメントのデータ用の型を用意する
  2. コレクション(ここでは写真の左の列のShops)への参照を取得する
  3. 2の参照をもとにコレクションのデータ(ここでは真ん中の列で言う1, 2, 3のドキュメント)を取得する
  4. 3で取得したデータから必要なものを取り出す

手順詳細

1. ドキュメントのデータ用の型を用意する

「ドキュメント1つ分のデータ取得方法」の1. と同じ内容ですが再掲。

export type Shop = {
  name: string,
  place: string
}

2. コレクション(ドキュメントを束ねる単位)への参照を取得する

先ほどのスクリーンショットで言うshopsの項目への参照を取得します。

const shopsColRef = collection(
  firestore,
 "shops"
) as CollectionReference<Shop>;

3. 2の参照をもとにコレクションのデータを取得する(複数ドキュメントを持つ)

const shopsDocs = await getDocs(shopsColRef);

4. 3で取得したデータから必要なものを取り出す

const shopsAllData = shopsDocs.docs.map((doc) => doc.data());
console.log(shopsAllData);

出力内容は、以下の感じ(抜粋)になります。

Array(3) [ {…}, {…}, {…} ]
0: Object { place: "品川", name: "ビストロしながわ" }
1: Object { name: "タマチピザ", place: "田町" }
2: Object { place: "有楽町", name: "Yurakucho Cafe" }
length: 3

shopsColRef作成時にShopsで型を指定しているおかげで、shopsAllDataを扱う際の .name呼び出し時にタイプミスや存在しないプロパティアクセスをしてしまう心配がありません。

console.log(shopsAllData[0].name);

出力内容は、ビストロしながわ となります。

ソースをまとめたもの

import { getFirestore, collection } from "firebase/firestore";
import { initializeApp } from "firebase/app";
import { CollectionReference, doc, getDoc, getDocs } from "@firebase/firestore";

const firebaseApp = initializeApp({ /* config */ });

const firestore = getFirestore(firebaseApp);

type Shop = {
  name: string,
  place: string
}

const shopsColRef = collection(
  firestore,
  "shops"
) as CollectionReference<Shop>;

export const getDocumentByIdExample = async(id: string) => {
  const shopsDocRefId1 = doc(shopsColRef, id);
  const shopsDocId1 = await getDoc(shopsDocRefId1);
  const shopsDataId1 = shopsDocId1.data();
  console.log(`id=${id}のデータ`) 
  console.log(shopsDataId1);  // → Object { place: "品川", name: "ビストロしながわ" }
}

export const getDocumentsExample = async () => {
  const shopsDocs = await getDocs(shopsColRef);
  const shopsAllData = shopsDocs.docs.map((doc) => doc.data());
  console.log("Shopsコレクションの全データ")
  console.log(shopsAllData)  // → Array(3) [ {…}, {…}, {…} ]
  console.log("Shopsコレクションの1番目の項目のnameの値")
  console.log(shopsAllData[0].name); // → ビストロしながわ
};

参考

javascript.plainenglish.io

こちらのサイトではコレクションへの参照取得時用メソッドを用意しているなど、実プロジェクトで使う際に良いお手本になりそうです。

qiita.com

こちらの説明のおかげでFirestoreの処理内容が把握できました。

qiita.com

冒頭で言及したUdemyのExpoの講座の講師の記事です

limaを使ってDockerDesktopなしでmacのdocker環境構築。sshfsのエラー対処も実施。

前置き

Docker Desktopの有料化にあたり、別の手段でのDocker環境の構築をする必要に追われている方もいらっしゃるかもしれません。 and-engineer.com

いろんな代替手段があると思いますが、以下のサイトを参考にさせていただきlima利用でのDocker環境構築を行いました。 korosuke613.hatenablog.com その際に、自分の環境だとうまくいかない箇所があったのでその対処法を記録しておきたいと思います。

環境

発生したエラーについて

いつ

:前述のサイトの手順「仮想マシンの構築」のlimactl start実行時
Docker Desktop 無しで Docker を使う with lima on Mac - cangoxina

どんな

:sshfsのインストールが完了せず、仮想マシンがrunningの状態になりませんでした。

INFO[0003] [hostagent] Waiting for the essential requirement 1 of 5: "ssh" 
INFO[0013] [hostagent] Waiting for the essential requirement 1 of 5: "ssh" 
INFO[0042] [hostagent] Waiting for the essential requirement 1 of 5: "ssh" 
INFO[0043] [hostagent] The essential requirement 1 of 5 is satisfied 
INFO[0043] [hostagent] Waiting for the essential requirement 2 of 5: "user session is ready for ssh" 
INFO[0043] [hostagent] The essential requirement 2 of 5 is satisfied 
INFO[0043] [hostagent] Waiting for the essential requirement 3 of 5: "sshfs binary to be installed" 
(中略。同じ行が何度も出てきました。)
INFO[0523] [hostagent] Waiting for the essential requirement 3 of 5: "sshfs binary to be installed" 
INFO[0563] [hostagent] Waiting for the essential requirement 3 of 5: "sshfs binary to be installed" 
FATA[0602] did not receive an event with the "running" status 

ログファイルによると

※~/.lima/docker配下のserial.logを参照します。
以下のようにfailure resolving等のメッセージが出力されており、名前解決ができていないようです。

[   22.532871] cloud-init[1461]: + apt-get update
[   42.628075] cloud-init[1461]: Ign:1 http://archive.ubuntu.com/ubuntu impish I
nRelease
[   52.629718] cloud-init[1461]: Ign:2 http://security.ubuntu.com/ubuntu impish-
security InRelease
[   72.672838] cloud-init[1461]: Ign:3 http://archive.ubuntu.com/ubuntu impish-u
pdates InRelease
[   83.676650] cloud-init[1461]: Ign:2 http://security.ubuntu.com/ubuntu impish-
security InRelease
[  102.719015] cloud-init[1461]: Ign:4 http://archive.ubuntu.com/ubuntu impish-backports InRelease
[  115.730931] cloud-init[1461]: Ign:2 http://security.ubuntu.com/ubuntu impish-security InRelease
[  132.765184] cloud-init[1461]: Ign:1 http://archive.ubuntu.com/ubuntu impish InRelease
[  149.782665] cloud-init[1461]: Err:2 http://security.ubuntu.com/ubuntu impish-security InRelease
[  149.783151] cloud-init[1461]:   Temporary failure resolving 'security.ubuntu.com'
[  162.811690] cloud-init[1461]: Ign:3 http://archive.ubuntu.com/ubuntu impish-updates InRelease

その結果、

[  373.584434] cloud-init[1461]: E: Package 'sshfs' has no installation candidat
e

となりsshfsがインストールできていないため、仮想環境の起動が成功となっていないようでした。

docker環境構築手順について

通常のインストール手順

$ brew install lima
$ brew install docker
$ cd ~/Desktop
$ mkdir lima
$ cd lima
$ vi docker.yaml
※ <https://github.com/lima-vm/lima/blob/master/examples/docker.yaml>の内容をペーストします。     
※ 公式がdocker環境構築用のyamlファイルを用意してくださっています・・・!  

$ limactl start ./docker.yaml
※ ここでsshfsのインストール待ちのままfailureになるなら環境構築作業は以下に続きます。ならないなら多分成功です!以下のエラー対処1・2を飛ばして「エラーなく起動できた後」に進んでください。

エラー対処その1

DNSサーバーのアドレス設定を修正します。
なお、再度sshfsのインストール等必要なライブラリのインストールを行なってほしいので、DNS設定修正後はサービスの再起動ではなくlimaのインスタンス自体を再起動させています。

$ limactl shell docker
$ sudo vi /etc/systemd/resolved.conf
※ #DNS=となっている行を、DNS=8.8.8.8 8.8.4.4 に書き換えて保存します。(GoogleのPublicDNS以外を使用している人は適宜各自の環境におけるDNSのアドレスにしてください。例えば僕の家では192.168.10.1でした。(ちなみに、僕はmac自体のDNSサーバーのipアドレスは8.8.8.8にしていたのですが、スマホのwi-fi設定詳細から本来のDNSサーバーのアドレスがわかりました))

$ exit
$ limactl stop docker
$ limactl start docker
※ ここでまだ同様のエラーが出るなら以下に続く。ならないなら多分成功!

エラー対処その2

もともと/etc/resolv.conf/run/systemd/resolve/stub-resolv.conf へのシンボリックリンクになっていると思いますが、いったんそのリンクを解除して/run/systemd/resolve/resolv.conf へのリンクに変更します。
これにより、ローカルDNSゾルバには任せず外部のDNSゾルバを見に行かせるようにします。

$ limactl shell docker
$ ls -l /etc/resolv.conf
$ sudo rm -f /etc/resolv.conf
$ sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf
※ sudo: unable to resolve host lima-docker: Temporary failure in name resolution と出るかもしれませんがここではスルーします。

$ exit
$ limactl stop docker
$ limactl start docker

スルーしたエラーは、limactl起動のエラーとはまた別のエラー(ホストネームの設定がきちんとできていない模様?)なのでいったんここではスルーしていますが、以下サイトを参考に対処を行えばこのエラーは発生しなくなると思います。

qiita.com

エラーなく起動できた後

起動が成功すれば以下のような感じの文言が出力されると思います。

  To run `docker` on the host (assumes docker-cli is installed), run the following commands:
  ------
  docker context create lima --docker "host=unix:///Users/【xxx】/.lima/docker/sock/docker.sock"
  docker context use lima
  docker run hello-world
  ------

出力されたコマンド通り実行しても良いのですが、docker contextをいちいち設定するのは手間なので別の方法を取ります。
(limactl startで指定したdocker.yamlの5、6行目にTo run 'docker' on the host で記載してある件です。)

出力されているhost=の内容(unix:///....の部分 )をコピーします。
ターミナルでzshを使っている場合は、~/.zshrc内にexport DOCKER_HOST='unix:///Users/【xxx】/.lima/docker/sock/docker.sock' という感じでコピーした値で行を追記します。
~/.zshrcの保存後、$source ~/.zshrcを実行します。
$docker run hello-world$ docker ps などが問題なく動かせることを確認します。

PCを再起動した後

再起動後はlimaのインスタンスは停止しているため、再起動前のようにdockerコマンドを使いたいという場合はdocker用のlimaのインスタンスを起動する必要があります。

$ limactl start docker

起動が確認できたら、$ docker psなどを実行して動作確認を行います。
なお、前述の.zshrcへのDOCKER_HOSTの設定は実施済みの前提です。(未実施の場合はdockerコマンド実行時に、Dockerのデーモンが動いていますか?といったエラーメッセージが出てくると思います。)

再起動後も常にdockerコマンドを使う場合

mac起動時に自動でlimaのdockerのインスタンスを起動させるコマンドを実行させると良いかと思います。
こちらのサイトの手順に従って設定を行います。
renoji.com

まずは、起動用のシェルスクリプトを用意します。
(僕は、limactl startで指定するdocker.yamlと同じフォルダに起動用のファイルを用意することにしました。)

$ cd ~/Desktop/lima
$ vi runLima.sh

runLima.shの中身は以下の通りにしました。

#!/bin/bash

limactl start docker

続いて、シェルスクリプトを起動するcommandファイルを作成します。

$ vi runLima.command

中身は、runLima.shのフルパスを記述した1行だけです。 以下の感じです。

/Users/【ユーザー名】/Desktop/lima/runLima.sh

続いて、実行権限エラーが出ないように権限設定をしておきます。
(自分がログインした時に実行させるものだからかchmod 700でも動作に問題はないのですが、macのサポートサイト https://support.apple.com/ja-jp/guide/terminal/apdd100908f-06b3-4e63-8a87-32e71241bab4/mac に755と書いてあるので755にしておきます)

$ chmod 755 runLima.command

いったんlimaのインスタンスを停止させ、起動用ファイルに問題がないか動作確認を行います。

$ limactl stop docker
$ ./runLima.command
※ limactl start dockerを実行した時と同じような出力になればOK

動作確認に問題がなければ、「システム環境設定」→「ユーザとグループ」→「ユーザを選択」→「ログイン項目」→「+」ボタンを押し、先ほど作成したrunLima.commandを指定します。
その後PCを再起動して動作確認を行います。
ターミナルが自動起動してスクリプトが実行され、「プロセスが完了しました」と出て来ればOKです。ターミナルを閉じてあげます。

以上で環境構築終了です。
以下は余談かな。

resolv.confについて

いろんなresolv.confが出てきて混乱しました・・・。仕組みがきちんと理解できていないです・・・。

/etc/resolv.conf

ただのリンクなので実態としては存在しない。

/run/systemd/resolve/resolv.conf

systemd-resolvedに管理されているファイルなので、直接編集しても再起動時にリセットされる。外部DNSゾルバ用の設定?

/run/systemd/resolve/stub-resolv.conf

systemd-resolvedに管理されているファイルなので、直接編集しても再起動時にリセットされる。内部DNSゾルバ用の設定?

/etc/systemd/resolved.conf

これを編集すればサービス再起動時、/run/systemd/resolve/resolv.confに反映されるっぽいです。

エラー対処及びresolv.confについての参考サイト

askubuntu.com

qiita.com

ararabo.com

hawksnowlog.blogspot.com

blog.jicoman.info

1人で赤ちゃん(4ヶ月)をお風呂に入れる時のタイムライン

ワンオペお風呂というのでしょうか。
自分1人で生後4ヶ月の赤ちゃんをお風呂に入れなくてはいけなくなったときに「どうやれば良いのだろう??」と不安になっていたので、どなたかの参考になればと記述します。

環境

  • 赤ちゃん:生後4ヶ月
  • 自動湯沸かし器あり
  • 湯船の保温機能あり
  • シャワーの温度がいまいち安定しない
  • 浴室・脱衣所に暖房器具なし

タイムライン

16:20

  • 居間から廊下(およびその先の脱衣所)につながる扉を開き、居間のエアコンの力で廊下経由で脱衣所を少しでも温める
  • お風呂の換気扇を止める
  • お風呂を沸かし始める。

16:20~16:55

  • 赤ちゃんをあやす
  • 赤ちゃんの着替えを居間に準備しておく(着せやすいように広げておいておく)
  • 脱衣所に自分の着替えおよび赤ちゃん用のバスタオル・おむつ・ボディクリーム・ガーゼハンカチを持っていく
  • 居間のカーテンを閉めておく

16:55

  • 赤ちゃんの機嫌が良さそうなら、赤ちゃんに先にお風呂に入ってくる旨を伝えて急ぎ風呂に入る
  • 赤ちゃんの機嫌が悪い場合は多少あやしつつ時には諦めて風呂に入る
    ※赤ちゃんはベビーベッド内

16:55~

  • 急いでお風呂に入る。脱衣所の扉および浴室の扉は少し開けておいて、一応赤ちゃんの声が耳に入るようにする
  • 浴室にタオルも持って入る
  • 自分の体を洗う
  • 洗い終わったら浴室の床を一通り流して床が滑らないようにする
  • 持って入ったタオルで頭を乾かしつつ浴槽に1分程度浸かったら、浴室内で体を拭きつつ、赤ちゃんのお風呂用にボディソープや手桶を準備する
  • 浴室から出る前に、お風呂の椅子を拭いておく(後で座った時にひんやりしないように)
  • 浴室から出たら、赤ちゃん用のバスタオルをマントのように羽織り(洗濯バサミで首元でタオルを止める)、顔にクリームや髪の毛用クリームを塗る
  • ドライヤーで髪を乾かす
  • ガーゼハンカチを浴室の手桶の中に突っ込んでおく
  • 浴室の扉は閉めずに半ドアにしておく
  • 脱衣所にお風呂マット(我が家は、アイリスオーヤマ IRISOHYAMA BM-6085E ベージュ バスマット を使用。を敷き、自分が羽織っていたバスタオルを広げ、おむつやボディソープを並べておく)

17:05くらい〜

  • 脱衣所からベビーベットのある位置に向かう
  • ベビーベッドで赤ちゃんの衣服を脱がせ、おむつも脱がせる。おむつはゴミ箱に捨てる。
  • 赤ちゃんを抱えて浴室に向かう。
  • 赤ちゃんを膝の上に横向きに横たえ、頭の位置が右なら右腕で頭を支えて左手で赤ちゃんを洗う
  • 顔→頭→手→胴体→足・背中・お尻 の順でガーゼハンカチ・ボディソープ・手桶を使って洗っていく
  • 赤ちゃんの体を一通り洗ったら、手桶で浴室の床を一通り流した後、湯船に入る(泡の流し残しも湯船で落とし切る)
  • お風呂の自動温度調節機能を切る(赤ちゃんが入っている時に熱めのお湯が出てくる事態を防ぐ)
  • 湯船の中でガーゼハンカチを使って顔と耳・おへそを軽く拭く
  • 30秒数えて湯船から上がる

17:15くらい〜

  • 脱衣所に敷いておいたマットの上のバスタオルの上に赤ちゃんを横たえる
  • タオルで赤ちゃんの全身の水気をさっと拭き取る
  • バスタオル&タオルで赤ちゃんが寒くないように包む
  • 声をかけながら自分の体を拭く&服を着る
  • 服を着終わったら、赤ちゃんの全身の保湿を行う
  • おむつを履かせる

17:20くらい〜

  • 赤ちゃんを抱えて(タオル類は脱衣所に放置)、 居間に広げておいた赤ちゃんの服の元に連れていく
  • 赤ちゃんに服を着せる
  • 赤ちゃんの頭を布で乾かす

17:25くらい〜

  • 赤ちゃんと多少戯れる
  • ベビーベッドに放置していた赤ちゃんの脱いだ服を退け、必要に応じてシーツを交換した上で赤ちゃんをベビーベッドに戻す
  • 脱いだ服やシーツ・脱衣所のタオルなどの後片付けをしにいく

といったところでお風呂完了!

補足1:断念したやり方について

  • 大人がお風呂に入っている最中に脱衣所で待たせる
    → 赤ちゃんが不安がって大泣きしてしまったので断念しました。また脱衣所がそんなに暖かくないのでやめました。

  • 大人が風呂に入っている最中に浴室内で待たせる
    → 水や泡の飛沫が飛んでしまうのも気が気じゃないし、浴室もそこまで暖かくないのでやめました。

補足2:大人がお風呂に入っている間に赤ちゃんが泣き出した場合について

  • 浴室から赤ちゃんに向かって呼びかける
  • が、諦めることも多いです。
  • 泣き出すととても焦りますが、安全なベビーベッドの中にいるはずなのでゆったりとした心構えでいるようにしたら良いかと思います。

補足3:大人がお風呂に入っている際に赤ちゃんをベビーベットに置いておくことについて

  • ベビーベッドなら危険なものもないし少々目を離していても大丈夫ではと思い(夜はベビーベッドに寝かして大人は寝ますし・・・)、もちろん泣かれてもすぐには反応できないし一人ぼっちにするのは申し訳ないとは思いつつ、寒いよりかはいいかなと思っています。

補足4:赤ちゃんを床から持ち上げる時について

  • 重い荷物の持ち上げ方を参考に、自分の体を赤ちゃんになるべく近づけ、しっかりと腰を落として赤ちゃんを抱き、膝を伸ばして立ち上がる、ということを意識すると良いかと思います。
  • 日頃からスクワット等で足腰を鍛えておいた方が良いかと思います。YouTubeのスクワット動画等で日々スクワットをするようになってから格段に持ち上げが楽になりました。
  • 自分は立ち上がった瞬間にほんの少し頭がくらくらすることがあるので、立ち上がってすぐ歩き出すのではなく、少し立ち止まって頭がしゃんとしてから歩くようにしています。

goのmock使用中に「panic: reflect: NumIn of non-func type...」が起きた

環境

状況 ※ダメなコード例は面倒なので省略

  • mockを使ったテスト実施中に以下のようなエラーに遭遇する
panic: reflect: NumIn of non-func type *hoge.Huga [recovered]
    panic: reflect: NumIn of non-func type *hoge.Huga
  • stacktrace
goroutine 7 [running]:
testing.tRunner.func1.2(0x17e99c0, 0xc0002648c0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/testing/testing.go:1143 +0x585
testing.tRunner.func1(0xc000224a80)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/testing/testing.go:1146 +0x3c8
panic(0x17e99c0, 0xc0002648c0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/runtime/panic.go:971 +0x4c7
reflect.(*rtype).NumIn(0x18054e0, 0x0)
    /Users/piyo/.anyenv/envs/goenv/versions/1.16.6/src/reflect/type.go:984 +0x109
github.com/golang/mock/gomock.(*Call).DoAndReturn.func1(0xc000264840, 0x1, 0x1, 0x0, 0x0, 0x0)
    /Users/piyo/go/pkg/mod/github.com/golang/mock@v1.6.0/gomock/call.go:119 +0x166
(後略)

NumInとは?

  • reflect/type.goに記述あり。
NumIn returns a function type's input parameter count.
It panics if the type's Kind is not Func.

(関数の引数の個数を返す。関数じゃないものに対してこのメソッドが呼ばれるとpanicが起きる)

つまるところの原因

DoAndReturnのメソッドの使い方が誤っていた(構造体(*hoge.Huga)を渡していました)

  • DoAndReturnの使い方
DoAndReturn declares the action to run when the call is matched. The return values from this function are returned by the mocked function. It takes an interface{} argument to support n-arity functions.

(要約:モック対象の処理が呼ばれた時に実行してほしい関数を書く。モック対象の処理はその関数の戻り値を返却してくれる)

DoAndReturnメソッドは、n-arity functionのサポートのため、つまり関数の引数の個数が何個でも大丈夫なようにinterface型を引数として受け取れるようになっています。そのため、関数ではないものを渡したとしてもコンパイルエラーにはならず実行時にpanicが起こるようになっています。

参考

zenn.dev

感想(自戒)

  • 改めてエラーメッセージを読むと、初めから分かりやすく書いてあったんだなあと反省・・・(「NumInって何者!?」ってなって思考停止しておりました)
  • panicが発生した時はスタックトレースにきちんと目を通すのが大事
  • スタックトレースよくわからん、ってなったら(僕)デバッグを活用してどこで起きているのかを突き止めるのが大事
  • メソッドの使い方の説明文が英語だとしてもせいぜい数行、丁寧に読もう