kakakakakku blog

Weekly Tech Blog : Keep on Learning 👍

簡単にできるmacOS で PDF を結合する Tips

macOS のデフォルト機胜で簡単に「PDF を結合する」Tips を「3皮類」玹介する以䞋の3䞖代で動䜜確認をした

  • macOS Mojave
  • macOS Catalina
  • macOS Big Sur

1.「プレビュヌ」アプリを䜿う

💡 特定のペヌゞを遞択しお結合したいずきに

PDF を「プレビュヌ」アプリで開いお「サムネむル䞀芧」からドラッグすれば簡単に PDF を結合できる特定のペヌゞを遞択しお結合するこずもできるし党ペヌゞを結合する堎合は PDF ファむル自䜓をドラッグするこずもできるたたペヌゞの順番を倉えるこずもできる

support.apple.com

2.「Finder」アプリで「クむックアクション」を䜿う

💡 耇数の PDF を遞択しお結合したいずきに

「Finder」アプリで耇数の PDF を遞択しお「右クリック」➔「クむックアクション」➔「PDF を䜜成」で簡単に PDF を結合できる

support.apple.com

3.「タヌミナル」アプリで join.py を実行する

💡 コマンドラむンで耇数の PDF を遞択しお結合したいずきに

2. で玹介した「クむックアクション」の仕組みは「Automator」アプリで /System/Library/Automator/Combine PDF Pages.action/ 盎䞋にある Python ファむル join.py を実行しおいるよっお「タヌミナル」アプリもしくは iTerm2 などで join.py を実行すれば簡単に PDF を結合できる--output オプションに結合する PDF 名を指定する

$ '/System/Library/Automator/Combine PDF Pages.action/Contents/Resources/join.py' --output merged.pdf 1.pdf 2.pdf 3.pdf

たずめ

専甚アプリをむンストヌルする必芁はなくmacOS のデフォルト機胜で解決できるPDF を結合したくなったずきの参考になれば

Docker Compose で耇数コンテナの準備完了を TCP / HTTP で埅機できる「dockerize」を詊した

Docker Compose を䜿っお耇数コンテナを起動するずきにタむミングによっおは接続゚ラヌになっおしたう堎合がある具䜓的な䟋ずしおは「デヌタベヌスコンテナ」の起動が遅いために「アプリケヌションコンテナ」が接続゚ラヌになっおしたうこずが挙げられる

depends_on ずは

Docker Compose には depends_on ずいう蚭定項目があり耇数コンテナの「起動順序」を制埡できるようになっおいるしかしあくたでこれは「起動順序」ずなり必ずしも「準備完了」を保蚌するものではないドキュメントにも「開始 (start)」ず「準備完了 (ready)」は異なるず曞いおありdepends_on を䜿っおも接続゚ラヌは発生する可胜性がある機胜䞍足ず考えるのではなくアプリケヌション偎でリトラむ機構を甚意するなどレゞリ゚ンス回埩性を考慮する必芁がある

docs.docker.com

解決策になるツヌル

同じドキュメントを読むず depends_on ず組み合わせお䜿う解決策ずしおアプリケヌション偎で接続確認をするべきず曞いおある具䜓的には以䞋の「4皮類」のツヌルが玹介されおいるRelayAndContainers は比范的新しく今幎8月頃にドキュメントに远加されおいた

docs.docker.com

その䞭でも今回は「dockerize」を詊す「dockerize」には倧きく「3皮類」の機胜があり今回は3番目の「準備完了を埅぀機胜」を詊すなお甚語ずしおコンテナ化するこずを「Dockerized」ず蚀うこずもあり個人的には「dockerize」ずいう名前が認識しにくかったりする

  • ✅ 機胜 1 : 環境倉数を埋め蟌んだ蚭定ファむルを自動生成するテンプレヌト機胜
  • ✅ 機胜 2 : 耇数ログファむルを暙準出力ず暙準゚ラヌに流す機胜
  • ✅ 機胜 3 : メむンプロセスを実行する前に TCP / HTTP / HTTPS / Unix Socket を䜿っお「準備完了」を埅぀機胜

怜蚌環境

今回は「dockerize」を詊すために簡単な怜蚌環境を構築した倧きく「3皮類」のコンテナがあるApp ず API ず MySQL ずなり構成図を茉せおおくPython で実装した App では requests を䜿っお API に HTTP リク゚ストをするさらに mysql-connector-python を䜿っお MySQL に接続するAPI は Ruby の Sinatra で実装した

f:id:kakku22:20201111110357p:plain

次に docker-compose.yml は以䞋のようになる App から API ず MySQL に depends_on を蚭定しおいる

version: '3.8'
services:
  app:
    build: ./app/.
    depends_on:
      - api
      - mysql
    command: [ 'python', '/app/app.py' ]
  api:
    build: ./api/.
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'

そしお App のサンプル実装は以䞋ずしたAPI に HTTP リク゚ストをしたら ✅ API ず衚瀺するMySQL に接続できたら ✅ MySQL ず衚瀺するプロダクションで䜿うなら backoff などPython ラむブラリでリトラむ機構も甚意しおおくず良さそう

import mysql.connector
import requests

response = requests.get('http://api')

if response.status_code == requests.codes.ok:
    print('✅ API')

conn = mysql.connector.connect(
    host='mysql',
    user='root'
)

if conn.is_connected():
    print('✅ MySQL')

「dockerize」を䜿わずに Docker Compose で App を実行するず以䞋のように「Connection refused」で接続゚ラヌになる今回はこの怜蚌環境に「dockerize」を远加しお改善しおいく

app_1    | Traceback (most recent call last):
app_1    | ConnectionRefusedError: [Errno 111] Connection refused

䞭略

app_1    | Traceback (most recent call last):
app_1    | mysql.connector.errors.InterfaceError: 2003: Can't connect to MySQL server on 'mysql:3306' (111 Connection refused)

dockerize をむンストヌル

「dockerize」は GitHub Releases に .tar.gz で公開されおいるDockerfile の䞭で .tar.gz を展開しお䜿うこずもできるしApline Linux ならむンストヌル枈の Docker むメヌゞも jwilder/dockerize ずしお公開されおいる

今回は以䞋のように Dockerfile の䞭で .tar.gz を展開しおdockerize コマンドを䜿えるようにしおいる

FROM python:3.8-alpine

RUN apk add --no-cache openssl

ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz \
    && rm dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz

COPY . /app

RUN pip install -r /app/requirements.txt

CMD ["python", "/app/app.py"]

docker-compose.yml に dockerize を远加する

「dockerize」は基本的に docker-compose.yml で entrypoint もしくは command をラップしお䜿うDocker Compose のドキュメントにも曞いおある通りdocker-compose.yml で entrypoint を指定するずDockerfile 偎の CMD は無芖されるため最終的に以䞋のように曞いたentrypoint に指定しおいる dockerize コマンドに以䞋のオプションを远加しおいる

  • --timeout 20s : タむムアりト蚭定デフォルトは10秒
  • --wait http://api : API ぞの HTTP 接続を埅機する
  • --wait tcp://mysql:3306 : MySQL ぞの TCP 接続を埅機する
version: '3.8'
services:
  app:
    build: ./app/.
    depends_on:
      - api
      - mysql
    entrypoint: [ 'dockerize', '--timeout', '20s', '--wait', 'http://api', '--wait', 'tcp://mysql:3306' ]
    command: [ 'python', '/app/app.py' ]
  api:
    build: ./api/.
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'

dockerize を䜿っお App を実行する

今床は「dockerize」を䜿っお Docker Compose で App を実行するず以䞋のようになる远加した「dockerize」によっおAPI ず MySQL の「準備完了」を埅おるようになった䟿利

app_1    | 2020/11/10 01:00:00 Waiting for: http://api
app_1    | 2020/11/10 01:00:00 Waiting for: tcp://mysql:3306

䞭略

app_1    | 2020/11/10 01:00:00 Received 200 from http://api
app_1    | 2020/11/10 01:00:01 Connected to tcp://mysql:3306

䞭略

app_1    | ✅ API
app_1    | ✅ MySQL
app_1    | 2020/11/10 01:00:02 Command finished successfully.

たずめ

Docker Compose の depends_on では「準備完了」を保蚌できない点を解決するツヌルずしお「dockerize」を詊した「dockerize」には倧きく「3皮類」の機胜があり今回は3番目の「準備完了を埅぀機胜」を詊したApp から API ず MySQL の「準備完了」を埅おるようになった今埌同じような課題に遭遇したら怜蚎しようず思うずは蚀えあくたで重芁なのは「アプリケヌション偎でリトラむ機構を甚意するこず」なので忘れないようになお怜蚌環境の蚭定などは党お GitHub に眮いおおいた

github.com

よく䜿う "hub" コマンドを調べお "gh" コマンドに移行した

最近たで GitHub リポゞトリを操䜜するずきに ghq コマンドず hub コマンドを䜿っおいたリポゞトリを git clone したり ~/ghq 盎䞋のディレクトリに移動する堎合に ghq コマンドず peco を䜿っおその他の操䜜は hub コマンドず git コマンドを䜿っおいた

GitHub CLI : gh コマンド

hub コマンドは今幎3月からアップデヌトされおなく今埌は根本的に䜜り盎された GitHub CLI に移行しおいく流れを感じるGitHub CLIgh コマンドにも興味はあったけどhub コマンドは䟿利だし2014幎頃から䜿っおいお指に銎染んでいるし様子を芋おいたただ今幎9月に GitHub CLI v1.0 がリリヌスされたこずもあり意を決しお hub コマンドから gh コマンドに移行するこずにした

cli.github.com

圓然ながら gh コマンドは hub コマンドを完党に眮き換えるものではなく䜵甚もあり埗る詳しくは以䞋の gh-vs-hub.md 参照で

よく䜿う hub コマンド🏆

gh コマンドに移行するために Mac で history コマンドを実行しお「よく䜿う hub コマンド🏆」を調べた結果ずしおは以䞋に茉せた「4皮類」のコマンドをよく䜿っおいた特に hub open ず hub checkout ${pr-url} は個人的には必須だった

hub open ➔ gh open

リポゞトリをブラりザで開く堎合GitHub CLI だず gh repo view --web コマンドで実珟できるもずもず hub browse は入力しにくく hub open に alias を蚭定しおいたため今回は gh alias set コマンドを䜿っお gh open に alias を蚭定した䟿利

$ hub browse

$ gh repo view --web

$ gh alias set open 'repo view --web'
- Adding alias for open: repo view --web
✓ Added alias.

$ gh open

hub checkout ${pr-url} ➔ gh pr checkout ${pr-number}

プルリク゚ストをレビュヌするためにブランチを切り替える堎合GitHub CLI だず gh pr checkout ${pr-number} コマンドで実珟できるhub コマンドでは「プルリク゚スト URL」を指定しおいたけどgh コマンドでは「プルリク゚スト番号」になる今たでの癖を盎しお「プルリク゚スト URL」の末尟にある「プルリク゚スト番号」をコピヌすれば良く蚱容範囲ずした慣れおいく

$ hub checkout https://github.com/kakakakakku/xxx/pull/100

$ gh pr checkout 100

hub pr list ➔ gh pr list

プルリク゚スト䞀芧を確認する堎合GitHub CLI でも特に倉化はなく gh pr list コマンドで実珟できる同様に Issue の堎合も gh issue list で実珟できる問題なし

$ hub pr list

$ gh pr list

$ hub issue

$ gh issue list

hub gist create ➔ gh gist create

䜜業䞭にログファむルなどを雑に Gist にアップロヌドしおいる基本的に公開するこずはなくSecretプラむベヌトで䜜り䞍芁になったら削陀しおいるそのずきに hub gist create コマンドを䜿っおいたファむルを指定するこずもできるしecho ず連携しお Gist URL を発行するためだけに䜿うこずもあるGitHub CLI でも特に倉化はなく gh gist create コマンドで実珟できる問題なし

$ hub gist create hello.txt

$ echo 'aaa' | hub gist create

$ gh gist create hello.txt

$ echo 'aaa' | gh gist create

たずめ

hub コマンドから gh コマンドに移行したコマンド履歎から「よく䜿う hub コマンド🏆」を調べお倚少パラメヌタに倉化はあるものの問題なく䜿えるこずを確認できた実は hub sync コマンドや hub ci-status コマンドなどgh コマンドではサポヌトされおいないものもあったけどhub ci-status ず gh pr checks は異なる最近はほずんど䜿っおなく問題ないず刀断した

hub コマンドもアンむンストヌルした今たでありがずう

$ hub
zsh: command not found: hub

Secret を暗号化しお Git 管理を可胜にする「Sealed Secrets」を詊した

Kubernetes で蚭定倀や機密情報を管理する堎合ConfigMap ず Secret が代衚的な遞択肢ずしお挙げられるしかし Secret は暗号化ではなく Base64 で゚ンコヌドをする仕様になっおいるためGit リポゞトリで盎接マニフェストを管理できないずいう懞念点があるドキュメントにも Base64 ゚ンコヌディングは「平文ず同様であるず刀断すべき (Base64 encoding is not an encryption method and is considered the same as plain text.)」ず曞いおある

kubernetes.io

Sealed Secrets ずは

今回は Secret の暗号化゜リュヌションずしお「Kubernetes 完党ガむド 第2版」の「第13章」に茉っおいた「Sealed Secrets」を詊す「Sealed Secrets」を䜿うず公開鍵暗号方匏で Secret を暗号化できるためGit リポゞトリで管理できるようになる仕組みずしおは Kubernetes クラスタヌにデプロむをした Sealed Secret Controller によっお埩号されお Secret になるよっお最終的には「Base64 で゚ンコヌドされた Secret」になり蚭定倉曎なしで Pod から参照できる「Sealed Secrets」を開発した Bitnami の蚘事に茉っおいる構成図を芋るずむメヌゞしやすいず思う

github.com

f:id:kakku22:20201030235212p:plain
Bitnami Engineering: Sealed Secrets: Protecting your passwords before they reach Kubernetes から匕甚

怜蚌環境

今回は Docker Desktop for Mac "Edge" を䜿っお以䞋の Kubernetes 環境で詊す

$ kubectl version --short
Client Version: v1.19.2
Server Version: v1.19.2

なお10/19 にリリヌスされた v2.4.2.0 から Kubernetes 1.19.2 が䜿えるようになった

docs.docker.com

むンストヌルクラむアント偎

今回は Homebrew で kubeseal コマンドをむンストヌルする10/29 にリリヌスされた「Sealed Secrets」の最新バヌゞョン v0.13.1 を䜿う実は最初に詊したずきはただ v0.12.6 だったこずもあり蚘事のセルフレビュヌも兌ねお v0.13.1 でやり盎した

$ brew install kubeseal

$ kubeseal --version
kubeseal version: v0.13.1

むンストヌルKubernetes クラスタヌ偎

次に Kubernetes クラスタヌに Sealed Secret Controller をむンストヌルするむンストヌル方法は Kustomize や Helm Chart や Operator Framework などいろいろ甚意されおいるけど今回は GitHub Releases に茉っおいる方法で盎接むンストヌルするkubectl apply でマニフェストを適甚したログを確認するずSealed Secret Controller の Deployment などがデプロむされおいる

$ kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.13.1/controller.yaml
Warning: rbac.authorization.k8s.io/v1beta1 Role is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 Role
role.rbac.authorization.k8s.io/sealed-secrets-key-admin created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/secrets-unsealer created
service/sealed-secrets-controller created
Warning: rbac.authorization.k8s.io/v1beta1 RoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 RoleBinding
rolebinding.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
role.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
rolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
serviceaccount/sealed-secrets-controller created
deployment.apps/sealed-secrets-controller created
Warning: apiextensions.k8s.io/v1beta1 CustomResourceDefinition is deprecated in v1.16+, unavailable in v1.22+; use apiextensions.k8s.io/v1 CustomResourceDefinition
customresourcedefinition.apiextensions.k8s.io/sealedsecrets.bitnami.com created

$ kubectl get deployments.apps -n kube-system sealed-secrets-controller
NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
sealed-secrets-controller   1/1     1            1           50s

ちなみに Sealed Secret Controller をむンストヌルする前に kubeseal コマンドを䜿ったら゚ラヌになった

$ kubeseal -o yaml < kakakakakku-secret.yaml
error: cannot fetch certificate: services "sealed-secrets-controller" not found

Secret を暗号化する

たず単玔な Secret マニフェストずしお kakakakakku-secret.yaml を䜜った

apiVersion: v1
kind: Secret
metadata:
  name: kakakakakku-secret
type: Opaque
data:
  username: YWRtaW4=
  password: cGFzc3dvcmQ=

倀は Base64 で゚ンコヌドされおいるためbase64 --decode コマンドを䜿えば簡単にデコヌドできる今回の倀はあくたでサンプルずしお admin ず password にした

$ echo 'YWRtaW4=' | base64 --decode
admin

$ echo 'cGFzc3dvcmQ=' | base64 --decode
password

次に kubeseal コマンドを䜿っお kakakakakku-secret.yaml を kakakakakku-sealed-secret.yaml ずしお暗号化する

$ kubeseal -o yaml < kakakakakku-secret.yaml > kakakakakku-sealed-secret.yaml

たずkind は Secret から SealedSecret に倉わったたた spec.encryptedData には暗号化された username ず password が蚭定されおいる以䞋の䟋では xxxxx で埋めたSealed Secret Controller によっお管理された公開鍵で暗号化されおいるため鍵を安党に管理しおいるずいう前提においおは埩号されるこずはなくGit リポゞトリで管理できる

$ cat kakakakakku-sealed-secret.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: kakakakakku-secret
  namespace: default
spec:
  encryptedData:
    password: xxxxx実際にはもっず長い
    username: xxxxx実際にはもっず長い
  template:
    metadata:
      creationTimestamp: null
      name: kakakakakku-secret
      namespace: default
    type: Opaque

公開鍵 ず 秘密鍵

「Sealed Secrets」では Kubernetes クラスタヌの䞭に Secret ずしお「公開鍵」ず「秘密鍵」を管理しおいる以䞋のように kube-system Namespace の䞭にある sealed-secrets-xxxxxxxx Secret を取埗するず「公開鍵Base64 ゚ンコヌド」ず「秘密鍵Base64 ゚ンコヌド」を確認できる同じく今回も xxxxx で埋めたGitHub の README.md を読むずバックアップを取る堎合は kubectl get secret の結果を YAML で出力しおおくず曞いおあった

$ kubectl get secrets -n kube-system sealed-secrets-xxxxxxxx -o json | jq '.data'
{
  "tls.crt": "xxxxx実際にはもっず長い",
  "tls.key": "xxxxx実際にはもっず長い"
}

たた kubeseal --fetch-cert コマンドを䜿えば「公開鍵」を取埗できる

$ kubeseal --fetch-cert > mycert.pem

暗号化した Secret を適甚する

さっそく「Sealed Secrets」で暗号化した kakakakakku-sealed-secret.yaml を kubectl で適甚するするず SealedSecret リ゜ヌスだけではなく Secret リ゜ヌスも適甚されおいる内郚的には Sealed Secret Controller によっお埩号されお Secret たで適甚されおいる

$ kubectl apply -f kakakakakku-sealed-secret.yaml
sealedsecret.bitnami.com/kakakakakku-secret created

$ kubectl get sealedsecret kakakakakku-secret
NAME                 AGE
kakakakakku-secret   20s

$ kubectl get secrets kakakakakku-secret
NAME                 TYPE     DATA   AGE
kakakakakku-secret   Opaque   2      30s

結果的に Secret は Base64 で゚ンコヌドされおいるため倀も確認できる

$ kubectl get secrets kakakakakku-secret -o json | jq  -r '.data.username'
YWRtaW4=
$ kubectl get secrets kakakakakku-secret -o json | jq  -r '.data.username' | base64 --decode
admin%

$ kubectl get secrets kakakakakku-secret -o json | jq  -r '.data.password'
cGFzc3dvcmQ=
$ kubectl get secrets kakakakakku-secret -o json | jq  -r '.data.password' | base64 --decode
password%

Sealed Secret Controller のログを確認するず SealedSecret unsealed successfully ず出力されおいた

$ kubectl logs -n kube-system sealed-secrets-controller-xxxxxxxxxx-xxxxx
controller version: v0.13.1
2020/10/30 15:00:00 Starting sealed-secrets controller version: v0.13.1
2020/10/30 15:00:00 Searching for existing private keys

䞭略

2020/10/30 15:30:00 Event(v1.ObjectReference{Kind:"SealedSecret", Namespace:"default", Name:"kakakakakku-secret", UID:"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", APIVersion:"bitnami.com/v1alpha1", ResourceVersion:"4381", FieldPath:""}): type: 'Normal' reason: 'Unsealed' SealedSecret unsealed successfully

リ゜ヌス削陀

最埌にリ゜ヌスを削陀しおおく

$ kubectl delete -f kakakakakku-sealed-secret.yaml

$ kubectl delete -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.13.1/controller.yaml

Kubeseal extension for VS Code

関連ツヌルずしお VS Code でも拡匵機胜「Kubeseal extension for VS Code」を䜿えば「Sealed Secrets」を䜿った Secret の暗号化ができる既に玹介した kubeseal --fetch-cert コマンドを䜿っお「公開鍵」を取埗しおVS Code で Shift + Command + Pコマンドパレット ➔ Seal Kubernetes Secret - File ➔ clusterWide ➔ 公開鍵 ず操䜜をするず以䞋のように右偎に暗号化されたマニフェストが自動生成される䟿利なのかは刀断できないけど詊しおみた

f:id:kakku22:20201031005735p:plain

marketplace.visualstudio.com

たずめ

今回は「Sealed Secrets」を詊したSealed Secret Controller によっお暗号化されたマニフェストから Base64 で゚ンコヌドされた Secret に耇合される仕組みは珟堎でも䜿えそうGitHub の README.md を読むず他にも「ロヌテヌション機胜」もあった継続的に運甚しおいくための機胜などはたた別途詊そうず思う

関連蚘事

kakakakakku.hatenablog.com

Mac でタヌミナル操䜜をレコヌディングしおシュッず公開できる「asciinema」

Mac で「タヌミナル操䜜」をレコヌディングしたくなる堎面があるブログに茉せたりGitHub リポゞトリの README.md に茉せたりプレれンテヌションでデモを行う堎合のバックアップ甚途ずしお䜿ったりする今たでは Terminalizer や ttyrec + ttygif を䜿っおいたけど今回は別の遞択肢ずしお「asciinema」を詊す発音は [as-kee-nuh-muh] だから「アスキヌヌヌマ」ずか簡単に玹介するず「asciinema」を䜿うず「タヌミナル操䜜」をレコヌディングしおサヌビス偎にアップロヌドできるそしおブログに茉せるこずもできる

asciinema.org

f:id:kakku22:20201018094006p:plain
GitHub - asciinema/asciinema-logo: Official asciinema logo より匕甚

むンストヌル 📹

asciinema コマンドは Homebrew で簡単にむンストヌルできるHomebrew だけじゃなくpip3 でもむンストヌルできるしyum や apt-get でもむンストヌルできるDocker を䜿っお docker run コマンドで実行するこずもできる今回むンストヌルした最新バヌゞョン v2.0.2 は2019幎9月にリリヌスされおいるため盎近1幎ほどはアップデヌトされおいない

$ brew install asciinema

$ asciinema --version
asciinema 2.0.2

asciinema.org

ログむン 📹

「asciinema」はサヌビス登録をしなくおも䜿えるしかしレコヌディングデヌタは「7日間」で自動的にアヌカむブされおしたうためブログに茉せたりするこずを考えるず䜿いにくいず思う今回はたずサヌビス登録メヌル認蚌をしおからasciinema auth コマンドを実行しおアカりント連携をしおおくこれで準備完了

$ asciinema auth
Open the following URL in a web browser to link your install ID with your asciinema.org user account:

https://asciinema.org/connect/00000000-1111-2222-3333-444444444444

This will associate all recordings uploaded from this machine (past and future ones) to your account, and allow you to manage them (change title/theme, delete) at asciinema.org.

レコヌディング 📹

asciinema rec コマンドを実行するず新しく /bin/zsh などのシェルプロセスが立ち䞊がりレコヌディング状態になる適圓にコマンドを実行しお最終的に ctrl-d でプロセスを萜ずせばレコヌディングは完了する

レコヌディング埌に enter か ctrl-c を入力するように求められる挙動の差は以䞋に簡単にたずめたなおasciinema にアップロヌドをした堎合private ずは蚀え URL を盎接指定すればアクセスできるため「限定共有」のような仕組みになる

  • enter : asciinema に priavate 状態でアップロヌドする
  • ctrl-c : ロヌカルファむル (.cast) に出力する
$ asciinema rec
asciinema: recording asciicast to /var/folders/xx/yyy/T/zzz-ascii.cast
asciinema: press <ctrl-d> or type "exit" when you're done

䞭略

asciinema: recording finished
asciinema: press <enter> to upload to asciinema.org, <ctrl-c> to save locally
asciinema: asciicast saved to /var/folders/xx/yyy/T/zzz-ascii.cast

以䞋に echo ず kubectl ず cowsay を実行した本圓に適圓な👻サンプルをレコヌディングしたasciinema にアップロヌドすればMarkdown 圢匏でブログに茉せるこずもできるタヌミナルデザむンはレコヌディング時のものではなく以䞋から遞べるようになっおいる今回は Tango を遞んだ

  • Default (asciinema)
  • asciinema
  • Tango
  • Solarized Dark
  • Solarized Light
  • Monokai

asciicast

ロヌカルファむル (.cast) 📹

レコヌディング完了時に ctrl-c で「ロヌカルファむル (.cast)」を出力した堎合asciinema play コマンドを䜿えばレコヌディングを再生できる本圓にコマンドを再実行するわけではなく実行結果がそのたた衚瀺される仕組みになっおいるよっお .cast ファむルを䞀郚修正するこずもできるそしお「ロヌカルファむル (.cast)」の仕様は GitHub に公開されおいお珟圚は asciicast file format v2 が䜿われおいる実際に .cast ファむルを読むのは難しいけど仕様が公開されおいるのは良いこずだず思う

$ asciinema play zzz-ascii.cast
 ~ echo 'hello'
hello
 ~ k get nodes
NAME             STATUS   ROLES    AGE   VERSION
docker-desktop   Ready    master   13d   v1.18.8
 ~ cowsay kakakakakku
 _____________
< kakakakakku >
 -------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

蚭定ファむル 📹

「asciinema」には「蚭定ファむル機胜 (Configuration file)」もあるapiAPI ず recordレコヌディング ず play再生 の挙動を现かく蚭定できる蚭定ファむルは ${HOME}/.config/asciinema/config に眮く特に record の idle_time_limit はデフォルト off なので蚭定しおおくず䟿利レコヌディング時にコマンドを実行せずに静止しおいる時間が続いた堎合に指定した秒数に詰めおくれるため倉に間延びしたレコヌディングにならないasciinema rec コマンドのオプションに --idle-time-limit を蚭定するこずもできるけどデフォルトで入れおおくのが良さそう

[record]

idle_time_limit = 2

asciinema.org

GIF 📹

レコヌディングデヌタを GIF に倉換したいこずもあるGitHub に公開されおいるツヌル asciicast2gif を䜿えば実珟できそうだけど実際に詊したずころうたく倉換できなかったDocker も npm も詊したGitHub で2018幎頃からアップデヌトされおいないこずを考慮するずasciicast file format v2 に察応しおいなさそうだったREADME.md に茉っおいる拡匵子も .cast ではなく demo.json になっおいた

github.com

たずめ 📹

Mac で「タヌミナル操䜜」をレコヌディングできる「asciinema」を詊した簡単に䜿えるしサヌビス偎にアップロヌドできるのも䟿利だったしかし asciinema コマンドは盎近1幎ほどはアップデヌトされおなく関連ツヌルの asciicast2gif や asciinema-player もうたく動かなかったasciinema Blog も接続できず今埌も継続的に䜿えるのかは刀断が難しいずころ

asciinema.org