20190507のMacに関する記事は7件です。

【Vim】Macで快適にHJKLする

TL;DR

どうも、最近.vimrcを育て始めたニワカVimmerです。

前からVimでのHJKL移動を速くしたかったのですが、Macの環境設定で簡単にできたので設定方法を晒します。

設定方法

  • 「システム設定 > キーボード」でキーボードの設定画面を開きます
  • 「キーのリピート」を「速い」に振り切ります
  • 「リピート入力認識までの時間」を「短い」に振り切ります

スクリーンショット 2019-05-07 22.23.24.png

設定はこれだけ!

速くて使いづらいなという方は、「キーのリピート」と「リピート入力認識までの時間」を少し遅くしたりして調節するといい感じになるかと思います。

まとめ

高速HJKL移動でVim生活がさらに快適になりそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

一足遅れて Kubernetes を学び始める - 08. discovery&LB その1 -

ストーリー

  1. 一足遅れて Kubernetes を学び始める - 01. 環境選択編 -
  2. 一足遅れて Kubernetes を学び始める - 02. Docker For Mac -
  3. 一足遅れて Kubernetes を学び始める - 03. Raspberry Pi -
  4. 一足遅れて Kubernetes を学び始める - 04. kubectl -
  5. 一足遅れて Kubernetes を学び始める - 05. workloads その1 -
  6. 一足遅れて Kubernetes を学び始める - 06. workloads その2 -
  7. 一足遅れて Kubernetes を学び始める - 07. workloads その3 -
  8. 一足遅れて Kubernetes を学び始める - 08. discovery&LB その1 -

前回

一足遅れて Kubernetes を学び始める - 07. workloads その3 -でようやくworkloadsが終了しました。今回は、discovery&LBを進めようと思います。

discovery&LB

Kubernetesには、下記のようにリソースの種類が存在します。
今回は、discovery&LBを学習します。

リソースの分類 内容
Workloadsリソース コンテナの実行に関するリソース
Discovery&LBリソース コンテナを外部公開するようなエンドポイントを提供するリソース
Config&Storageリソース 設定・機密情報・永続化ボリュームなどに関するリソース
Clusterリソース セキュリティやクォータなどに関するリソース
Metadataリソース リソースを操作する系統のリソース

KubernetesのWorkloadsリソース(その1)

discovery&LBをには、下記8つの種類があります。

  • Service
    • ClusterIP
    • ExternalIP
    • NodePort
    • LoadBalancer
    • Headless (None)
    • ExternalName
    • None-Selector
  • Ingress

Serviceの概要について学びます。

Kubernetesとネットワーク

Kubernetesでは、Pod毎にIPアドレスが割り振られています。
そのため、異なるPod間で通信する際は、PodのIPアドレスが必要になります。逆に同一のPod内ならlocalhostで通信できます。

説明するために、準備します。

sample-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 80
        - name: redis-container
          image: redis:3.2
pi@raspi001:~/tmp $ k apply -f sample-deployment.yaml
pi@raspi001:~/tmp $ k get pods -l app=sample-app -o custom-columns="NAME:{metadata.name}, IP:{status.podIP},NODE:{spec.nodeName}"
NAME                                 IP           NODE
sample-deployment-9dc487867-h7lww   10.244.1.72   raspi002
sample-deployment-9dc487867-n8x5w   10.244.2.66   raspi003
sample-deployment-9dc487867-nxbxc   10.244.2.67   raspi003

Kubernetes_learning-Page-2 (1).png

このような状況下で、sample-deployment-9dc487867-n8x5w:redisを中心に見ていきます。

※ nginxは80ポートで開放されています。

前準備

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# apt-get update && apt-get install curl -y
root@sample-deployment-9dc487867-n8x5w:/data# exit

curlがないのでインストールします。

同一Node,同一Pod内のコンテナへ通信

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl localhost:80
<!DOCTYPE html>
...

OK

同一Node,異なるPodのコンテナへ通信

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.66:80
<!DOCTYPE html>
...
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.2.67:80
<!DOCTYPE html>
...

OK

異なるNode,異なるPodのコンテナへ通信

pi@raspi001:~/tmp $ k exec -it sample-deployment-9dc487867-n8x5w -c redis-container /bin/bash
root@sample-deployment-9dc487867-n8x5w:/data# curl 10.244.1.72:80
<!DOCTYPE html>
...

OK

MasterNodeから各Podへ通信

pi@raspi001:~/tmp $ curl 10.244.1.72:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.66:80
<!DOCTYPE html>
...
pi@raspi001:~/tmp $ curl 10.244.2.67:80
<!DOCTYPE html>
...

OK

ここから分かるように、Pod内部の通信、Pod間の通信、さらにNode間の通信までも、Kubernetesによってネットワークが構築されています。

Service

Serviceは、下記の2つの大きな機能が存在します。

  • pod宛トラフィックのロードバランシング
  • サービスディスカバリとクラスタ内DNS

pod宛トラフィックのロードバランシング

先程の例で、Pod間を通信することは可能です。しかし、podを作り直すたびにIPアドレスが変わってしまうため、
自作すると、少し大変です。そこで、Serviceの出番です。
サービスは、複数存在するPodに対して自動的にロードバランスしてくれるのと、合わせて外向けのIPアドレス(ExternalIP)や、内向けのIPアドレス(ClusterIP)も提供してくれます。

さっそく、試してみます。

sample-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: sample-clusterip
spec:
  type: ClusterIP
  ports:
    - name: "http-port"
      protocol: "TCP"
      port: 8080
      targetPort: 80
  selector:
    app: sample-app

これは、app=sample-appにマッチするPodに対してロードバランスしてくれます。外から8080ポートで待ち受けて、80ポートでコンテナへ通信します。
spec.typeがClusterIPなので、内向けのIPアドレスが提供されています。

pi@raspi001:~/tmp $ k apply -f sample-clusterip.yaml
pi@raspi001:~/tmp $ k get service sample-clusterip
NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
sample-clusterip   ClusterIP   10.111.197.69   <none>        8080/TCP   30s
pi@raspi001:~/tmp $ k describe service sample-clusterip
Name:              sample-clusterip
...
Selector:          app=sample-app
Type:              ClusterIP
IP:                10.111.197.69
Port:              http-port  8080/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.72:80,10.244.2.66:80,10.244.2.67:80
...

内向けに10.111.197.69のIPアドレスが振られました。また、ロードバランスする対象Podは、先にあげたPodのIPアドレスです。
Endpintsに:80とあるように、port毎にサービス(clusterIP)を作ることもできます。(serviceのspec.portsは配列指定)

アクセスできるのか、試します。
せっかくなので、pod毎にindex.htmlの内容を変化させましょう。

pi@raspi001:~/tmp $ for PODNAME in `k get pods -l app=sample-app -o jsonpath='{.items[*].metadata.name}'`; do
> k exec -it ${PODNAME} -- cp /etc/hostname /usr/share/nginx/html/index.html;
> done
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-nxbxc
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-n8x5w
pi@raspi001:~/tmp $ curl 10.111.197.69:8080
sample-deployment-9dc487867-h7lww

確かに、ロードバランシングによってpodに適度なランダム具合でアクセスできています。
もちろん、外からはアクセスできません。

iMacへ移動

~ $ curl 10.111.197.69:8080
# 返答なし

サービスディスカバリとクラスタ内DNS

サービスディスカバリとは、「問題においての解決策」を指しています。
Kubernetesにおける問題とは、動的にサービスが生成され続けていることによるサービスを特定することが難しくなる問題です。
そのサービスディスカバリが、Serviceにあります。
その方法について下記があります。

  • 環境変数を利用したサービスディスカバリ
    • PodにIPアドレスやport,protocolが設定されている。
  • DNS Aレコードを利用したサービスディスカバリ
    • Kubernetes内のクラスタ内DNSによって、ドメイン名によるアクセスができる。(ドメイン名の命名規則に従う)
  • DNS SRVレコードを利用したサービスディスカバリ
    • IPアドレスからドメイン名を取得する逆引きもできる。

dnsPolicyによる明示的な設定がない限り、Pod生成時にクラスタ内DNSへレコード追加されます。
クラスタ内DNSで名前解決できなかった場合は、クラスタ外DNSに問い合わせします。

お片付け

pi@raspi001:~/tmp $ k delete -f sample-deployment.yaml -f sample-clusterip.yaml

最後に

今回は、Serviceについての概要を学びました。Kubernetesの世界では、自動的にネットワーク構築されているため、特段意識することはありませんでした。
もう少し理解が進めれば、ネットワークがどのように構築されているのか、クラスタ内DNSがどのように動いているのか知りたいと思います。

※ お絵かきしてアウトプットすると、理解が深まるのでおすすめです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

15年開発してるMac用画像ビューアを3年ぶりにバージョンアップした時にやったこと

こんにちは、絵描き兼開発者の「ゆき」です。
今日は私が学生時代から10年以上、地味に開発・サポートを続けているMac向けの画像ビューアを3年ぶりくらいにバージョンアップしたお話です。
500img.jpg

この記事のモチベーションと対象読者

詳細は後ろに書きますが、Macアプリの個人開発界隈はそろそろ死にます。1
今年リリース予定の次期MacOS(10.15)で32bitアプリのサポートが完全に終了するためです。古くからの個人開発アプリは新しいバージョンが出ない限り新しいOSでは動きません。

もちろんきちんと開発継続しているアプリはもう大体対応済みかとは思いますが、個人開発のフリーウエア・シェアウエアに関しては開発者本人すら忘れていたりすることもある2ので、そんな個人開発者の方向けにこの記事が届けばいいなー...くらいの気持ちで書き残しておこうと思います。

今回の対象アプリ

画像ビューア「絵箱」
http://nekobooks.com/main/ebako/

「絵箱」はMac向けの画像ビューア&ファイラー的なアプリです。フォルダ内の画像ファイルをサムネイル一覧でプレビューして、簡単な整理・編集ができる機能を提供しています。
今でこそFinder上でもそこそこ画像のプレビューができますが、それでもシンプルなUIと直感的な操作性で今でも幾らかのユーザーさんに使っていただいています(完全にフリーなのでMacの方は試してみてください)。

このアプリの前提環境を記載しておきます:

  • 開発環境・言語はXojo(REAL basic) 3
  • プラグインの作成にObjective-C/Xcodeを使用 4
  • App Storeでは配布しない野良アプリ(証明書はあり)5
  • 形態は通常のアプリケーション(カーネル拡張等の特殊な要素はなし)

ちょっと特殊な環境ではあると思いますが、逆に王道のStoreアプリの場合は常に最新の環境に合わせていかないとストアから落とされてしまうので、今この記事が役に立つ方がいるとすれば、ある種似たような環境なのかも、と思います。

3年ぶりのバージョンアップでやったことと躓きポイント

ここからはざっくり、今回のバージョンアップで行なった修正のポイントをメモしたいと思います。一部REALbasic(Xojo)のコードが出てきますが、なんとなく感触で読めると思います。

64bit対応

まず今回一番の山が64bit対応です。
64bit化自体は基本的にはコンパイラがよしなにやってくれるので、簡単なアプリであればほぼ修正なしで動くのですが、絵箱の場合は残念ながら大量の修正が必要でした。

OS API呼び出し部分の修正

Xojoは基本的にOS固有の機能をそれほど提供してくれないので、不足する部分はMacOSのAPIを呼び出して補完します。
絵箱はファイルシステムを操作したりFinder等のOS標準の挙動に合わせたりと、何かとAPI呼び出しが多いアプリなのでまずこの部分の書き換えが必要になりました。

例えば、CGRect。
image.png
CoreGraphics系の処理を呼ぶためにXojo側にも構造体の定義をしているのですが、64bit環境では当然ながら各要素は8バイトのdoubleにしないと動きません。
残念なことにこのミスマッチはコンパイルはおろか呼び出し時にもチェックされないため、実行してみて初めてクラッシュしたりおかしな値(おそらくxとyの8バイト分をdouble型で読んでしまう)を取り出してしまって後続の処理でエラーになったりします。

これはわかってしまえば対処は簡単で、定義を全部書き換えるだけです。

もうちょっと厄介なのが直接ポインタを操作している場所。
例えば下の例はNSArrayをXojoの配列に変換する関数なのですが、どこが問題かお分かりになるでしょうか?

Function NSArrayToArray (ref as Ptr) as Ptr()
  Soft Declare Function count Lib "Cocoa" Selector "count" (nsArrayRef as Ptr) as Integer
  Soft Declare Sub getObjects Lib "Cocoa" Selector "getObjects:range:" (nsArrayRef as Ptr,objsRef as Ptr,range as CocoaLibMod.NSRange)

  Dim Count as Integer = count(ref)
  Dim ArrContsRef as MemoryBlock = New MemoryBlock(Count * 4)
  getObjects ref,ArrContsRef,NSMakeRange(0, Count)

  Dim ContPtrs(Count - 1) as Ptr
  For I as Integer = 0 to Count - 1
    ContPtrs(I) = ArrContsRef.Ptr(I * 4)
  Next

  Return ContPtrs
End Function

ちゃんとCからネイティブを勉強されてる人であれば(REALbasicは知らなくても)わかると思います。* 4ですね。仕事でやったらレビューで怒られる:scream:ヤツだと思うのですが、きっとこれ書いた時には64bitのことなんて何も考えていなかったんだと思います。。

これも修正は簡単で、4を定数化して64bit環境では8になるように変更するだけです。

Dim SIZE as Integer = 4
#If Target64Bit Then
  SIZE = 8
#Endif

問題はこの地雷が埋め込まれている場所をどうやって探すか・・・
結局4とか8とか怪しい数字で4万行のコードを全検索する羽目になりました。。マジックナンバーはダメ!絶対!:no_good_tone1:

バイナリ読み書きの修正

OSのAPI呼び出し以外で64bitが問題になったのがバイナリの読み書き部です。
絵箱では性能を気にしてバイナリファイルを多用していたのと、データのシリアライズやディープコピーに自作したバイナリ操作クラスを使っていたためにあらゆる箇所でアプリがクラッシュしました。

たとえば下記のメモリーブロックに文字列とその長さ情報を書き込む処理。

Dim M as MemoryBlock = New MemoryBlock(6 + LenB(ValStr))
M.Long(0) = LenB(ValStr) + 6
M.Short(4) = 8
M.StringValue(6,LenB(ValStr)) = ValStr

もともとLongは4バイト符号付整数、Shortは2バイト符号付整数だったのですが、
Xojoコンパイラが64bitに対応した時にこれらはLong == Integer, Short == Int16の別名と定義されています。さらにIntegerは32bit環境ではInt32、64bit環境ではInt64の別名とみなされます。

つまり、上記のコードではShortが常に2バイト固定であることが保証されているのに対し、Longは環境依存で4バイトだったり8バイトだったりするわけです。

修正は基本的に環境依存の型を使用せず、バイト数を明示して読み書きするように修正すればOKです。

修正
Dim TotalLen as Integer = HeaderLen + LenB(ValStr)
M = New MemoryUtil.StreamMemoryBlock(TotalLen)
M.WriteUInt32Value TotalLen
M.WriteUInt16Value Variant.TypeString
M.WriteStringValue ValStr

Objective-Cプラグインの修正と再ビルド

絵箱では基本的に外部のプラグインは利用していないのですが、唯一ファイルのサムネイルを取得するためにプラグインを書いています。6

マイナー言語のさらにマイナーな領域になるので細かくは書きませんが、基本的にはxcode上でターゲットアーキテクチャを64bitに変更すればOKです。
image.png

数少ない情報源としてはGREIF Software - 64bit対応についてがとても参考になりました。
以前Xojoに同梱されていたサンプルでは、なぜかデフォルトでQuickTime.libがリンクされているのでこの辺り不要なリンクも外さないとエラーになると思います。

廃止APIの置き換え

これも吐き気してくるヤツですね。数年ぶりにビルド通そうとするといろんなAPIが廃止されていて悲しみにくれることになります。特に初期のCarbon時代のAPIは単純な移行パスがないものも多いです。

例えばファイルのラベル一覧の定義を取得する処理。
image.png
(↑この一覧を作るのに必要)

ラベルの一覧を取得する
Public Function GetLabelColorAtIndex (Index as Integer) as Color
  #If TargetCarbon or TargetCocoa Then
    Soft Declare Function GetLabel Lib "Carbon" (LabelNumber as Integer,LabelColor as Ptr,LabelString as Ptr) as Integer
  #Else
    Soft Declare Function GetLabel Lib "InterfaceLib" (LabelNumber as Integer,LabelColor as Ptr,LabelString as Ptr) as Integer
  #EndIf

  Dim LabelColor, LabelString as MemoryBlock
  Dim Re as Integer

  LabelColor = New MemoryBlock(6)
  LabelString = New MemoryBlock(256)
  Re = GetLabel(index,LabelColor, LabelString)
  Return RGB(LabelColor.UShort(0)/257,LabelColor.UShort(2)/257,LabelColor.UShort(4)/257)
End Function

InterfaceLibとか出てくる時点でどれだけ古いんだこのコード...7

ここで呼び出しているGetLabel関数はもはやドキュメントからも削除されていて、何に置き換えたら良いのかもわからず。。結局同等と思われる機能を持つAPIを探して実装し直しています。CarbonLib時代のAPIは大体消えてしまったのでこの辺りは単純な書き換えができないのが辛いところ。。

NSWorkSpace.class
Public Function fileLabelColors() as Color()
  Declare Function getFileLabelColors Lib "AppKit.framework" Selector "fileLabelColors" (ws as Ptr) as Ptr

  Dim ArrPtr as Ptr = getFileLabelColors(Me.Ref)
  Dim ColPtrs() as Ptr = NSArrayToArray(ArrPtr) // NSArrayXojoの配列に変換
  Dim LabelColors(-1) as Color
  For each ColPtr as Ptr in ColPtrs
    Dim Col as Color = NSColorToColor(ColPtr) // NSColorXojoColorに変換
    LabelColors.Append Col
  Next

  Return LabelColors
End Function

Retinaディスプレイに対応

ここまでで大体、アプリとしては動く状態になりました。ここからは「最近のアプリっぽく」するために必要な機能を追加していきます。

まずはRetina対応から。
image.png

上が対応後。下が対応前です。
メインマシン(iMac)がいまだにRetinaではないので気がつかなかったのですが、Retina環境で並べてみると歴然です。
Retina対応自体はInfo.plistを書き換えるだけの簡単なお仕事で、文字も画像も(画像データのピクセル数さえ足りていれば)勝手に×2で描画してくれます。
問題なのは描画性能向上のためにオフスクリーンバッファ(メモリ上で一旦画像を生成してから画面に描画する方法)を使っている場合。
×2になるのはあくまでRetinaディスプレイ上に描画するコンテキストを使う場合だけなので、オフスクリーンで描いてしまうとRetinaになりません。
対処法としてはオフスクリーン上では(出力先がRetinaであれば)2倍で描画するのが基本になります。同様に、アイコン等サイズを指定してOSから引っ張ってくるものも2倍にする必要があります。
ただ、昔は性能向上やチラツキ回避に多用されたオフスクリーンバッファですが、今では不要になっているケースも多いはずです。絵箱でもこの機会に細かい描画は直接行うように見直しました。

MacOSX MojaveのDark Modeに対応

もう一つの新機能対応がDark Modeです。これ対応するだけで今っぽくなりますね。
これも基本的には何もしなくてもOSのコントロール部分はOS側がよしなにやってくれるのですが...
image.png

こんな感じですね。。自力で描画している領域が多いアプリの場合、Dark Modeを検知して描画も変えてあげないといけません。
絵箱は幸い以前からテーマの切り替え機能を作り込んでいるので、今回はDark Modeを検知した時点で専用のテーマに自動切り替えすることで対処しました。
image.png

絵箱はたまたまテーマ切り替え機能を作り込んでいたからよかったのですが、そのあたりの機能がない状態だとこの対応はかなり面倒かもしれません。

証明書の更新とアプリの署名

作ったアプリを配布するにはAppleに発行してもらった自分の証明書を使ってアプリを署名する必要があります。署名がないアプリはダブルクリックで起動できないので、配布するなら実質的に署名は必須です。作業は簡単だけど有償の開発者登録(年間1万弱)が必要です。8
証明書の取得方法自体は(iOSアプリでも同様に必要なので)巷にたくさん情報があると思います。iOS, Certificate 証明書を作ってみるあたりが分かりやすかったです。
基本的にはiOSと同じ手順ですが、証明書の発行はMacアプリ用をリクエストしてください。
https://developer.apple.com/account/mac/certificate/create

Xcodeを使った開発の場合はXcode側に証明書を登録してビルドするのかと思いますが、Xojoの場合には自分でコードサインの作業が必要です。下のようなスクリプトを作っておいて、ビルド時に呼ばれるようにしておくと良いかと思います。

doCodeSign.sh
#!/bin/sh
xattr -cr $1
codesign -f --deep -s  "Developer ID Application: XXXX(証明書の名前)" $1

まとめ

  • 古いMacアプリは64bit化しないと次のMacOSでは動かない
  • 古いアプリもRetinaやDark Modeに対応させると今風に(なるかも)
  • 昔作ったフリーウエアをHDDの奥に寝かせている方はこの機会にバージョンアップしてみるのもいいかも

あと、よかったら絵箱使ってみてくださいませ


  1. もちろん私見ですし異論も多々あるかと思いますが、Webやクロスプラットフォームな実行環境の選択肢が色々出てきている時代です。Macのネイティブアプリを個人がわざわざ作る時代ではないのかな...と。そして、過去の遺産も次のMacOSで清算されるので、その意味で「死」と表現しました。 

  2. 私です 

  3. 昔むかしにCrossBasic/REALbasicという名前でMacアプリの個人開発を流行らせた言語/開発環境。日本市場からは完全に消えたけど、アメリカではまだちゃんとバージョンアップしてる。クロスプラットフォームアプリが作れるVBA、みたいな立ち位置で小規模ビジネス用途にシフトして生き残っている感じ。これから開発を始める人には正直オススメしないけど、10年変わらずにサポートしてくれるのは素晴らしいことだと思う。 

  4. Xojoには不足する機能をプラグインとして組み込める機能がある。Macの場合はObjective-CやSwiftで記述可能 

  5. 正確にはStoreに置きたいけど置けない。Storeアプリはシステム内のファイルに直接アクセスできない(デスクトップやPictures等特定フォルダのみ可)ので、フォルダ階層をルートからツリーで表示するようなアプリは基本的に作れない。個人的にはこの辺りの制限もMacのAppStoreがイマイチ面白くならなかった理由だと思っている 

  6. サムネイルの読み込み自体は通常のAPIコールで対応できるのですが、Xojoでは言語仕様上マルチコア・マルチスレッドで処理を実行する方法がないため、性能を重視する場面ではプラグインを組む必要が出てきます。 

  7. 多分もともとはREALbasicとFutureBASICで使おうToolbox最新活用テクニック (MAC POWER BOOKS)に載ってたコードだと思う 

  8. 有償メンバシップが切れても、一度取得した証明書の有効期限内(4年くらい)であれば取得済みの証明書で署名できる。また、一度署名したアプリは証明書の有効期限が切れても問題なく起動できるはず。 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

macでターミナルからタイマーを簡単にセット出来るようにする

エイリアスの設定をする際にちょっとつまづいたので備忘録。

背景

とある案件でデプロイからサーバー反映まで10分〜50分程時間がかかるものがあった。
確認するのに毎度時計を見るのは面倒だったのでタイマーを仕掛けたかったが、macの通知センターにタイマーがなかった。
わざわざアプリを入れるのは嫌だったので、あるもの(ターミナル)でどうにかしようと思った。

環境

  • MacOS Mojave 10.14.4
  • Bash

設定

.bashrc
function timer() {
  sleep $1; osascript -e 'on run argv
    display notification item 1 of argv
  end run' -- "$2"
}

これでターミナルでtimer 5 xxxと打てば5秒後に以下のような通知が出る。
スクリーンショット 2019-05-07 20.03.36.png
途中で止める場合はCtr+C

課題

  • 進捗状況が見えない
  • タイマーが出るまでターミナル動きっぱなし

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

真っさらな状態のMACにAWSCLIをインストールするまで

まっさらなMacPCにAWSCLIをインストールするまでの構築手順を記載します。

環境

macOS Mojave 10.14.4

Homebrewのインストール

参考: Homebrew のインストールと基本的な使い方

XcodeのCommand Line Toolsが必要です。事前にxcodeをインストールしてください。

$ xcode-select --install
xcode-select: note: install requested for command line developer tools

$ xcode-select -v
xcode-select version 2354.

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

pyenvのインストール

バージョン切り替えをしやすくするためにpyenvを利用します。
参考: pyenvのインストール、使い方、pythonのバージョン切り替えできない時の対処法

$ git clone git://github.com/yyuu/pyenv.git ~/.pyenv
Cloning into '/Users/t-yasukawa/.pyenv'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 17306 (delta 0), reused 2 (delta 0), pack-reused 17300
Receiving objects: 100% (17306/17306), 3.34 MiB | 2.39 MiB/s, done.
Resolving deltas: 100% (11791/11791), done.
Checking out files: 100% (645/645), done.

pyenvのパスを設定します。

$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile

MacOS Mojaveのpyenvでpythonのインストールに失敗する時の対応

これをやらないとmojaveではpythonのインストールに失敗します。
参考: [MacOS Mojave]pyenvでpythonのインストールがzlibエラーで失敗した時の対応

$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
Password:
installer: Package name is macOS_SDK_headers_for_macOS_10.14
installer: Installing at base path /
installer: The install was successful.

python3.7のインストール

$ pyenv install 3.7.3
Downloading openssl-1.1.0j.tar.gz...
-> https://www.openssl.org/source/openssl-1.1.0j.tar.gz
Installing openssl-1.1.0j...
Installed openssl-1.1.0j to /Users/t-yasukawa/.pyenv/versions/3.7.3

Downloading readline-8.0.tar.gz...
-> https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz
Installing readline-8.0...
Installed readline-8.0 to /Users/t-yasukawa/.pyenv/versions/3.7.3

Downloading Python-3.7.3.tar.xz...
-> https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz
Installing Python-3.7.3...
Installed Python-3.7.3 to /Users/t-yasukawa/.pyenv/versions/3.7.3

pythonのバージョン確認

プリインストールで2系のpythonが既に入っていると思います。

$ python --version
Python 2.7.10

pyenvに新しくインストールしたversionがあるか確認します。

$ pyenv versions
* system (set by /Users/t-yasukawa/.pyenv/version)
  3.7.3

3.7.3を適用します。

$ pyenv global 3.7.3
$ python --version
Python 3.7.3

pipのインストール

pyenvでインストールされたバージョンであればpipが既に使える状態になっています。

$ pip -V
pip 19.0.3 from /Users/t-yasukawa/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip (python 3.7)

ついでにpipのアップグレードを行います。

$ pip install --upgrade pip
Collecting pip
  Downloading https://files.pythonhosted.org/packages/5c/e0/be401c003291b56efc55aeba6a80ab790d3d4cece2778288d65323009420/pip-19.1.1-py2.py3-none-any.whl (1.4MB)
    100% |████████████████████████████████| 1.4MB 6.5MB/s 
Installing collected packages: pip
  Found existing installation: pip 19.0.3
    Uninstalling pip-19.0.3:
      Successfully uninstalled pip-19.0.3
Successfully installed pip-19.1.1

更新できました。

$ pip -V
pip 19.1.1 from /Users/t-yasukawa/.pyenv/versions/3.7.3/lib/python3.7/site-packages/pip (python 3.7)

AWSCLIのインストール

やっとAWSCLIをインストールできるようになりました。

$ pip install awscli --upgrade --user

パスを追加します。

$ echo 'export PATH="~/.local/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

awsのバージョンを確認します。

$ aws --version
aws-cli/1.16.153 Python/3.7.3 Darwin/18.5.0 botocore/1.12.143
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

brewのrequirements.txt的なやつ

pythonでいうところのrequirements.txt的なのはbrewではないのでしょうか?

brew listだと横になっちゃう... > brew leaves コマンドがあるよ。

brew leavesを使えばOKそうです。

## 書き出し
brew leaves > my_formula.txt
## インストール
xargs brew install < my_formula.txt

caskは?? > brew cask list -1 で。

brew leavesではbrew-caskものは表示されません。brew cask leavesというコマンドはありませんでした。

これはbrew cask list -1で表示できました。
ちなみにbrew leavesではなくbrew list -1でインストールしたコマンド一覧を出力できますが、依存する為にインストールされたformulaもごっそりでちゃうようです。

## 書き出し
brew cask list -1 > my_cask_formula.txt
## インストール
xargs brew cask install < my_cask_formula.txt

ですかね。

これで別マシンでも環境構築が楽になりそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

install nodebrew, node and yarn

今さらですが、nodebrew, node (npm), yarn のインストール手順をまとめておきます。

mac で zsh が前提です。
bash の人は .zshrc => .bashrc に読み換えるなどお願いします。

その前に

私の環境がちょっと汚れていたので掃除から始めます。

まず、インストールされていた yarn, node をアンインストール。

$ brew uninstall yarn
$ brew uninstall node

以前にインストールした nodebrew も、一旦、アンインストール。

$ brew uninstall nodebrew

.zshrc から nodebrew に関する環境変数の設定も消しておきました。

export PATH=$HOME/.nodebrew/current/bin:$PATH
export NODEBREW_ROOT=...

環境変数を削除したら source しておきます。

$ source ~/.zshrc

/usr/local/var/nodebrew ディレクトリも残っていたら消します。

$ rm -rf /usr/local/var/nodebrew

brew update もしておきます。

$ brew update

インストール

nodebrew のインストール

node は homebrew ではなく nodebrew で管理することにしました。

$ brew install nodebrew

nodebrew ディレクトリのセットアップをします。

$ nodebrew setup

環境変数に NODEBREW_ROOT が設定されていなければ、$HOME/.nodebrew がセットアップされるはずです。

.zshrc に PATH の設定を追記しておきます。

export PATH=$HOME/.nodebrew/current/bin:$PATH

パスを通すために source しておきます。

$ source ~/.zshrc

node のインストール

続いて Node.js をインストールします。

$ nodebrew install-binary stable
$ nodebrew use stable
use v12.1.0
$ nodebrew list
v12.1.0

current: v12.1.0

$ node -v
v12.1.0

npm や npx もインストールされているはず。

$ npm -v
6.9.0

$ npx -v
6.9.0

yarn のインストール

Yarn は homebrew でインストールします。

$ brew install yarn --ignore-dependencies

yarn は node に依存しているため homebrew で node がインストールされていないと依存関係のエラーになります。

しかし node は nodebrew で管理しているので homebrew ではインストールしません。

そこで --ignore-dependencies オプションを指定します。

以前は --without-node オプションを指定していたようですが、現在は無効になっているみたいです。

$ yarn -v
1.15.2

以上でインストール完了です。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む