unisonでディレクトリを双方向同期する
この記事は、Infocom Advent Calendar 2022 4日目の記事です。
PCをオフライン環境で使いたいときには必要なファイルをコピーして持っていくことになり、作業中に何らかの更新が発生したら作業後はコピー元に戻しますね。
gitで管理すればいいものもあるしソースはそうしてますけど、パワポやExcelとかまあいろんな雑多なファイルをgitに全部入れるわけにもいきません。
とはいえ毎回手動でコピーして戻すとなるとミスもするし、毎回毎回手作業でやるのはうんざりするので自動化を考えました。
- シェルスクリプト/バッチファイルでコピーコマンドを使う
- 全部コピーするので単純に遅い
- 戻すのは手作業
- rsync
- 一方向しかできない
- 両方に修正があると詰む
- 結局、戻すのは手作業
- unison
- 両方の修正を検出してそれなりにいい感じにやってくれる。これだ!
unison
どうやら結構古くからあるUnix系のOSSツールのようです。
私は1995年頃からUnix系OSを使っているのですが知りませんでした。
LinuxやMacだけじゃなくWindows用のバイナリもあったのはうれしい。
コンフリクトを検出できる。
SSHでも同期できる。
rsyncのような部分転送になっているということでコピーが高速。ファイル数が多ければそれなりに時間はかかりますが、普段使いの感じだと十分早いなと思います。
お手軽。これだいじ。
- インストール
$ brew install unison Warning: Treating unison as a formula. For the cask, use homebrew/cask/unison 🍺 /usr/local/Cellar/unison/2.53.0: 9 files, 3.9MB
Windowsはscoopで入れてます。
> scoop install unison Installing 'unison' (2.53.0) [64bit] from main bucket unison-v2.53.0+ocaml-4.12.1+x86_64.windows.zip (29.8 MB) [====================================================] 100% Checking hash of unison-v2.53.0+ocaml-4.12.1+x86_64.windows.zip ... ok. Extracting unison-v2.53.0+ocaml-4.12.1+x86_64.windows.zip ... done. Linking ~\scoop\apps\unison\current => ~\scoop\apps\unison\2.53.0 Creating shim for 'unison'. Creating shim for 'unison-fsmonitor'. 'unison' (2.53.0) was installed successfully! Notes ----- Compiled with same OCaml compiler version 4.12.1
main bucketにあったのでbucket追加しなくても普通に入ると思います。
使ってみる
ということで使ってみます。
- コマンドで実行
unison root1 root2
で起動します。
$ tree foo bar foo ├── aaa │ └── hogehoge.pptx └── hoge.txt bar [error opening dir] $ unison foo bar Unison 2.52.1 (ocaml 4.12.0): Contacting server... Looking for changes Warning: No archive files were found for these roots, whose canonical names are: /Users/gozu/Documents/foo /Users/gozu/Documents/bar Reconciling changes foo bar dir ----> [f] Proceed with propagating updates? [] y Propagating updates [BGN] Copying from /Users/gozu/Documents/foo to /Users/gozu/Documents/bar [END] Copying $ tree foo bar foo ├── aaa │ └── hogehoge.pptx └── hoge.txt bar ├── aaa │ └── hogehoge.pptx └── hoge.txt
初回なのでまるっとコピーされました。
相手のディレクトリが無ければ単純に複製ができます。
bar/hoge.txt
を修正して、同期してみる
$ unison foo bar foo bar <---- new file .hoge.txt.un~ [f] <---- changed hoge.txt [f] <---- new file hoge.txt~ [f] Proceed with propagating updates? [] y Propagating updates [BGN] Copying .hoge.txt.un~ from /Users/gozu/Documents/bar to /Users/gozu/Documents/foo [END] Copying .hoge.txt.un~ [BGN] Updating file hoge.txt from /Users/gozu/Documents/bar to /Users/gozu/Documents/foo [END] Updating file hoge.txt [BGN] Copying hoge.txt~ from /Users/gozu/Documents/bar to /Users/gozu/Documents/foo [END] Copying hoge.txt~
barのファイルがfooへ同期されています。
が、vimの管理ファイルまで同期されてますね。これは設定で除外できます。
- 双方で同じファイルを更新してみる
$ unison foo bar foo bar changed <-?-> changed hoge.txt [] d diff -u '/Users/gozu/Documents/bar/hoge.txt' '/Users/gozu/Documents/foo/hoge.txt' --- /Users/gozu/Documents/bar/hoge.txt 2022-12-02 20:07:40.000000000 +0900 +++ /Users/gozu/Documents/foo/hoge.txt 2022-12-02 20:07:45.000000000 +0900 @@ -1,3 +1 @@ hello unison. -hello unison. -hello unison. changed <-?-> changed hoge.txt [] x foo : changed file modified on 2022-12-02 at 20:07:45 size 14 rw-r--r-- bar : changed file modified on 2022-12-02 at 20:07:40 size 42 rw-r--r-- changed ====> changed hoge.txt [] > Proceed with propagating updates? [] y Propagating updates [BGN] Updating file hoge.txt from /Users/gozu/Documents/foo to /Users/gozu/Documents/bar [END] Updating file hoge.txt
修正したファイルがテキストファイルなのでdiffを取ることができました。
あとはファイルの日付やサイズを確認したり。
どちらを採用するか >
で指定しています。
インタラクティブなコマンドは
このくらいでなんとかなるかな。
よく使う設定を定義できる
確かにいいんですが、これだとあんまり便利になってませんね。
いらないファイルを除外したり、新しいファイルを採用して欲しいし、いちいち指定せずとも全部自動でやって欲しい。
なので、設定ファイルを書いて自動実行できるようにします。
Macだと ~/.unison
ディレクトリを作って、拡張子がprfのファイルを作ります。
(Windowsでは C:\Users\アカウント名\.unison
です)
default.prf
は定義名を指定せずにunisonを実行したときに使われます。
unison 定義名
とすると ~/.unison/定義名.prf
が使われます。
私の設定ファイルは以下のようになっています。
includeで読み込むための基本的な設定(common.prf
)をしておくと、コピーする対象ごとに設定ファイルを作ることができ、最小の設定ファイルにできます。
$ cat ~/.unison/default.prf # Unison preferences file # https://88171.net/unison-manual-ja # https://www.seas.upenn.edu/~bcpierce/unison/download/releases/stable/unison-manual.html # 自動実行 batch = true # ownerも同期する owner = true # タイムスタンプをコピーする(ディレクトリはできない) times = true # permissionを設定しない perms = 0 # chmodしない perms=0と組み合わせる dontchmod = true # 新しいファイルを優先 prefer = newer # 新規作成ファイルはユーザに同期如何を問わない auto = true # ファイル更新日時による更新有無の判定(Windowsでは更新日時が変わらないことがあるのでたまにfalseにするとよいらしい) fastcheck = true # エラー以外の出力停止をしない silent = false # 無視するディレクトリやファイル名を指定する ignore = Name .DS_Store ignore = Name Icon? ignore = Name {.*.swp,*.*~} ignore = Name {*.gsheet,*.gslides,*.gdoc}
$ cat ~/.unison/foo.prf # Include the contents of the file common include common # 同期する対象のルートパスの定義 root = /Users/gozu/Documents/foo/ root = /Volumes/bar/foo/ # バックアップ backup = Name * maxbackups = 5 backupprefix = $VERSION. backupdir = /Volumes/nas/backup/unison/foo
実行は、 unison foo
と打つだけです。
こうして設定を分けておく事で、重要性に応じてバックアップの世代数や取るファイルの種類、ディレクトリを変えることができます。
設定のオプションやサンプルが色々載っているので、
https://www.seas.upenn.edu/~bcpierce/unison/download/releases/stable/unison-manual.html
を、見てやってます。DeepLを使うと驚くほどわかりやすく訳してくれます。
使い道
MacやWindows、NASなどプラットフォームを越えて個人的なディレクトリを同期するのにはとても便利です。
ファイルを消すときはやっぱり注意が必要。どっちを消しても消える事になるので、rsyncの--deleteオプションより危険な事もあると思う。
更新する人が不特定多数なところで使うのちょっと躊躇しますね。
でも、ログやバックアップがいい感じに取れるので運用次第で使えるのかも?
双方向で同期出来て普通のコピーより早いし差分更新でマルチプラットフォームとなればもっと使われてもいいのになーと思ってこのブログを書きながら何となくググっていたらdocker-syncというツールで使われているというのが分かった。コンテナの中のファイルとホスト側のファイルを同期させるもののようです。
なるほど。いかにもなユースケースですね。
VMWare FusionのWin10をWin11へ上げる
まだ無料アップグレードができるのでやってみる。
Windows 11のシステム要件として64GB以上のシステムDISKとTPMが引っかかったのでまずはこちらを解決しよう。
以下のサイトを参考に実施してみます。
パーティション拡張する
仮想マシンだから簡単簡単、と思った意外と面倒だった。
VMWare側で拡張は簡単。
設定 > ハードディスク > ディスクサイズ を64GBにするだけ。
ところが起動したら、ブート領域/Cドライブ/回復パーティション/追加領域 になっていて拡張できない…
回復パーティションは設定画面からは消せないので以下のサイトを見ながらやってみる。
C:\WINDOWS\system32>diskpart DISKPART> list disk ディスク 状態 サイズ 空き ダイナ GPT ### ミック ------------ ------------- ------- ------- --- --- ディスク 0 オンライン 64 GB 14 GB ディスク 1 オンライン 50 GB 1024 KB * DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 579 MB 1024 KB Partition 2 プライマリ 48 GB 580 MB Partition 3 回復 553 MB 49 GB DISKPART> select partition 3 パーティション 3 が選択されました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 579 MB 1024 KB Partition 2 プライマリ 48 GB 580 MB * Partition 3 回復 553 MB 49 GB DISKPART> delete partition override DiskPart は選択されたパーティションを正常に削除しました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 579 MB 1024 KB Partition 2 プライマリ 48 GB 580 MB DISKPART>
これで消えました。(Windows 11を入れたら復活させるかな)
システムパーティションを拡張できるようになったので全部まとめてしまう。
仮想マシンにTPMを追加する
DISKは無事拡張できたので残りはTPMです。 手順としては、
- 起動ディスクをMBRからUEFIブートへ変更
- VMWareの設定でファームウエアをUEFIへ変更
- VMWareの設定でUEFIセキュアブートを有効化にチェック
- VMWareの設定で暗号化を有効にするをチェック
- Windows 11 インストール
という感じです。
起動ディスクをレガシーBIOSからUEFIへ変更する
VMWareの設定ではレガシーBIOSと出ていますがいわゆる昔ながらのMBRレコードから起動するように仮想マシンを作っていたのでこれをUEFIにするにはディスクをGPTへ変更しなければなりません。
この辺の操作は危険なのでスナップショットを取ってから作業を行います。
仮想マシンを起動したら管理者モードでコマンドプロンプトを起動して、mbr2gptコマンドで実施します。
まず確認ですが早速エラー。
C:\WINDOWS\system32>mbr2gpt /validate /disk:0 ERROR: MBR2GPT can only be used from the Windows Preinstallation Environment. Use /allowFullOS to override. C:\WINDOWS\system32>mbr2gpt /validate /disk:0 /allowFullOS MBR2GPT: Attempting to validate disk 0 MBR2GPT: Retrieving layout of disk MBR2GPT: Validating layout, disk sector size is: 512 bytes Cannot find OS partition(s) for disk 0
ググってみるとどうやらWindowsのバージョンアップを行った際に残ったBCD構成ファイル内のゴミがいけないとのこと。消してみましょう。
まず不可視のブートパーティションをいじれるようにします。
C:\WINDOWS\system32>diskpart DISKPART> select disk 0 ディスク 0 が選択されました。 DISKPART> list partition Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 プライマリ 579 MB 1024 KB Partition 2 プライマリ 63 GB 580 MB DISKPART> select partition 2 パーティション 2 が選択されました。 DISKPART> assign letter=w: 仮想ディスク サービス エラー: 現在のブート ボリュームまたはページ ファイル ボリュームに対して、 ドライブ文字を割り当てたり、割り当てを解除することはできません。 DISKPART> select partition 1 パーティション 1 が選択されました。 DISKPART> assign letter=b: DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。 DISKPART> exit DiskPart を終了しています...
元記事ではシステムパーティションをWドライブに退避して作業を行なっていましたが、Cドライブから変えられませんでした。
ブートパーティションはBドライブに変えられたのでこのまま作業を続行します。
C:\WINDOWS\system32>dir /a b: ドライブ B のボリューム ラベルは システムで予約済み です ボリューム シリアル番号は 3CA5-6110 です B:\ のディレクトリ 2022/03/21 22:26 <DIR> Boot 2022/03/21 21:42 413,880 bootmgr 2019/12/07 18:08 1 BOOTNXT 2021/06/02 14:50 8,192 BOOTSECT.BAK 2020/12/25 11:02 <DIR> System Volume Information 3 個のファイル 422,073 バイト 2 個のディレクトリ 572,878,848 バイトの空き領域
ブートパーティション見えてますね。
bcdeditコマンドでunknownになっているidentifierを探します。
今回は {1cea4e0a-4655-11eb-b8e8-86cd67d75de6}
ですね。
C:\WINDOWS\system32>bcdedit /store B:\boot\bcd /enum all Windows ブート マネージャー -------------------------------- identifier {bootmgr} device partition=B: description Windows Boot Manager locale ja-JP inherit {globalsettings} default {default} resumeobject {1cea4e07-4655-11eb-b8e8-86cd67d75de6} displayorder {default} toolsdisplayorder {memdiag} timeout 30 Windows ブート ローダー -------------------------------- identifier {default} device partition=C: path \WINDOWS\system32\winload.exe description Windows 10 locale ja-JP inherit {bootloadersettings} recoverysequence {1cea4e0a-4655-11eb-b8e8-86cd67d75de6} displaymessageoverride Recovery recoveryenabled Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \WINDOWS resumeobject {1cea4e07-4655-11eb-b8e8-86cd67d75de6} nx OptIn bootmenupolicy Standard Windows ブート ローダー -------------------------------- identifier {1cea4e0a-4655-11eb-b8e8-86cd67d75de6} device ramdisk=[unknown]\Recovery\WindowsRE\Winre.wim,{1cea4e0b-4655-11eb-b8e8-86cd67d75de6} path \windows\system32\winload.exe description Windows Recovery Environment locale ja-JP inherit {bootloadersettings} displaymessage Recovery osdevice ramdisk=[unknown]\Recovery\WindowsRE\Winre.wim,{1cea4e0b-4655-11eb-b8e8-86cd67d75de6} systemroot \windows nx OptIn bootmenupolicy Standard winpe Yes 休止状態からの再開 -------------------------------- identifier {1cea4e07-4655-11eb-b8e8-86cd67d75de6} device partition=C: path \WINDOWS\system32\winresume.exe description Windows Resume Application locale ja-JP inherit {resumeloadersettings} recoverysequence {1cea4e0a-4655-11eb-b8e8-86cd67d75de6} recoveryenabled Yes allowedinmemorysettings 0x15000075 filedevice partition=C: filepath \hiberfil.sys bootmenupolicy Standard debugoptionenabled No Windows メモリ テスター -------------------------------- identifier {memdiag} device partition=B: path \boot\memtest.exe description Windows メモリ診断ツール locale ja-JP inherit {globalsettings} badmemoryaccess Yes EMS 設定 -------------------------------- identifier {emssettings} bootems No デバッガー設定 -------------------------------- identifier {dbgsettings} debugtype Local RAM 不良 -------------------------------- identifier {badmemory} グローバル設定 -------------------------------- identifier {globalsettings} inherit {dbgsettings} {emssettings} {badmemory} ブート ローダー設定 -------------------------------- identifier {bootloadersettings} inherit {globalsettings} {hypervisorsettings} ハイパーバイザー設定 ------------------- identifier {hypervisorsettings} hypervisordebugtype Serial hypervisordebugport 1 hypervisorbaudrate 115200 再開ローダー設定 -------------------------------- identifier {resumeloadersettings} inherit {globalsettings}
こいつを消します。
C:\WINDOWS\system32>bcdedit /store B:\boot\bcd /delete {1cea4e0a-4655-11eb-b8e8-86cd67d75de6} この操作を正しく終了しました。 C:\WINDOWS\system32>bcdedit /store B:\boot\bcd /enum all Windows ブート マネージャー -------------------------------- identifier {bootmgr} device partition=B: description Windows Boot Manager locale ja-JP inherit {globalsettings} default {default} resumeobject {1cea4e07-4655-11eb-b8e8-86cd67d75de6} displayorder {default} toolsdisplayorder {memdiag} timeout 30 Windows ブート ローダー -------------------------------- identifier {default} device partition=C: path \WINDOWS\system32\winload.exe description Windows 10 locale ja-JP inherit {bootloadersettings} displaymessageoverride Recovery recoveryenabled Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \WINDOWS resumeobject {1cea4e07-4655-11eb-b8e8-86cd67d75de6} nx OptIn bootmenupolicy Standard 休止状態からの再開 -------------------------------- identifier {1cea4e07-4655-11eb-b8e8-86cd67d75de6} device partition=C: path \WINDOWS\system32\winresume.exe description Windows Resume Application locale ja-JP inherit {resumeloadersettings} recoveryenabled Yes allowedinmemorysettings 0x15000075 filedevice partition=C: filepath \hiberfil.sys bootmenupolicy Standard debugoptionenabled No Windows メモリ テスター -------------------------------- identifier {memdiag} device partition=B: path \boot\memtest.exe description Windows メモリ診断ツール locale ja-JP inherit {globalsettings} badmemoryaccess Yes EMS 設定 -------------------------------- identifier {emssettings} bootems No デバッガー設定 -------------------------------- identifier {dbgsettings} debugtype Local RAM 不良 -------------------------------- identifier {badmemory} グローバル設定 -------------------------------- identifier {globalsettings} inherit {dbgsettings} {emssettings} {badmemory} ブート ローダー設定 -------------------------------- identifier {bootloadersettings} inherit {globalsettings} {hypervisorsettings} ハイパーバイザー設定 ------------------- identifier {hypervisorsettings} hypervisordebugtype Serial hypervisordebugport 1 hypervisorbaudrate 115200 再開ローダー設定 -------------------------------- identifier {resumeloadersettings} inherit {globalsettings}
もうmbr2gptを一回実行してみます。
C:\WINDOWS\system32>mbr2gpt /validate /disk:0 /allowFullOS MBR2GPT: Attempting to validate disk 0 MBR2GPT: Retrieving layout of disk MBR2GPT: Validating layout, disk sector size is: 512 bytes MBR2GPT: Validation completed successfully
うまくいったようです。
ではGPTへ変換してみましょう。
C:\WINDOWS\system32>mbr2gpt /convert /disk:0 /allowFullOS MBR2GPT will now attempt to convert disk 0. If conversion is successful the disk can only be booted in GPT mode. These changes cannot be undone! MBR2GPT: Attempting to convert disk 0 MBR2GPT: Retrieving layout of disk MBR2GPT: Validating layout, disk sector size is: 512 bytes MBR2GPT: Trying to shrink the OS partition MBR2GPT: Creating the EFI system partition MBR2GPT: Installing the new boot files MBR2GPT: Performing the layout conversion MBR2GPT: Migrating default boot entry MBR2GPT: Fixing drive letter mapping MBR2GPT: Conversion completed successfully Call WinReReapir to repair WinRE MBR2GPT: Failed to update ReAgent.xml, please try to manually disable and enable WinRE. MBR2GPT: Before the new system can boot properly you need to switch the firmware to boot to UEFI mode!
回復パーティションを消したから怒られてるみたいだけど、一応GPTにはできたっぽいですね。
シャットダウンしてVMWareの設定を変えます。
VMWareの設定を変更する
VMWare Fusionの設定をレガシーBIOS→UEFIへ
↓
セキュアブートにする前に起動して確認します。
うまくいったのでシャットダウンしてからセキュアブートにします。
お次は、暗号化を有効にする にチェックです。
これをしないとTPMを追加できません。
DISK容量が足りないと暗号化できません。
最後にTPMモジュール追加です。
デバイスを追加するだけですが、元には戻せないと言われます。
Windows 11のインストール
正常性のチェックは通るのに、WindowsUpdateの画面を開くとシステム要件を満たしてないと言われたので、WindowsUpdateしてみましたが変わらず。
でも、Windows11 インストール アシスタントを実行してみたところインストールできました!
追記
Windows 11にしたら自動的に回復パーティションが作成されていました。
作り直す必要なかったですね。
さらにEFIシステムパーティションというものも追加されています。
BドライブにしていたのはGUIからドライブレターの削除ができました。
1Password 8に上げてSSHキーを管理出来るようにする
1Password 8で見た目が変わったり機能が増えたりしていますが、自分が一番おっと思ったのはSSHキーを管理出来るという所ですね。
というわけで、メモがてら記事にしていこうと思います。
インストール
いま(2022/7/9)時点でまだMac AppStoreには8はきていないのでダウンロードします。
1Password Installer.app を起動すれば自動的にアップデートされます。
だいぶ見た目が変わってます。(ダークモードに対応したのね)
設定
まずは設定を有効にします。
1Password > 環境設定 > 開発者
を開きます。
デフォルトだと何もチェックがついてない状態ですね。
SSHエージェントを使用する
にチェックします。
1Password CLI用の生体認証ロック解除
は op
というコマンドを使うようなのだがとりあえず今は使わないのでそのままです。
1PasswordがSSHキー名をディスクに保存出来るようにします
を許可します。
FingerPrintを表示されても分からんしね。
~/.ssh/config に表示されているスニペットを追加します。(xxxxxxxxxxのところのパスは環境によって違うようです)
Host * IdentityAgent "~/Library/Group Containers/xxxxxxxxxx.com.1password/t/agent.sock"
Remember key approval が、until 1Password locks
でも until 1Password quits
でもどちらにしろロックしたらTouch IDが出てくるので、自動ロックの間隔を調整してもいいんじゃないでしょうか。
デフォルトの10分は自分には厳しすぎます。
1Password > 環境設定 > セキュリティ > 自動ロック
で、変更しちゃいます。
既存のキーを使ってSSHする
ラズパイへのSSHキーを1Passwordで管理してみます。
キーを作るときにEd25519かRSA(2048ビット以上)にしていない場合は作り直す必要があります。
お勧めはEd25519らしいです。
とりあえず既にあるRSAの鍵をインポートします。
+新規アイテム > SSHキー で登録します。
秘密鍵を追加
からキーファイルを読み込む
でもいいし、ラズパイからわざわざ持ってこなこなくても クリップボードから鍵を張り付け
で登録出来ます。
既存のキーならローカルにあるかもしれないですが、クリップボード貼り付けができるのは地味に便利。
パスフレーズが設定されていれば入力画面が出てきます。
キーが登録出来ました。
それではログインしてみます。
既存のキーなので ~/.ssh/authorized_keys
は設定済みの想定です。
Touch IDでログイン出来ました!
ssh-keygenを使わずに1Passwordで新しいキーを作る事も出来ます。
その場合、秘密鍵をどこにもコピーせずに公開鍵をauthorized_keysに登録するだけなのでちょっと安心ですね。
Git Cloneできるようにする
個人ではGitHub、仕事ではBitbucketを使っているので両方試してみます。
GitHub
まずGitHubから。
Settings > SSH and GPG keys へ行きます。
New SSH key
を押します。
Titleをクリックすると、1Passwordのブラウザ拡張が入っていれば SSHキーの作成
が出ます。
作成と入力
を押すとキーが作成されて1Passwordへ登録され、GitHubの画面に反映されますので、Add SSH key
を押して登録します。
それではCloneしてみます。
まずはCLIで。
git clone git@github.com:gozuk16/test.git Cloning into 'test'... remote: Enumerating objects: 35, done. remote: Counting objects: 100% (14/14), done. remote: Compressing objects: 100% (9/9), done. remote: Total 35 (delta 5), reused 14 (delta 5), pack-reused 21 Receiving objects: 100% (35/35), 5.04 KiB | 1.26 MiB/s, done. Resolving deltas: 100% (9/9), done.
出来ました。
次に自分が使ってるGitクライアントのForkでやってみます。
CloneするときのプロトコルをhttpsからSSHに切り替えます。
1PasswordがTouch IDの画面を出してくれるのでピッと触ればCloneできます。
うーん便利!
ちなみに、GitHubは2023年末までにTwo-factor authenticationを設定せよというわけで2FAも1Passwordで設定しています。
Sign inの時に1Passwordでパスワードを入力すると遷移先ではtokenが自動でセットされるので便利です。(まあいいという事にしといて...)
Bitbucket
基本的には同じです。
Personal settings > SSH 鍵 > 鍵を追加 でGitHubと同じように出来ます。
その他
- いまのところ保管庫はデフォルトで作られるPersonalじゃないとダメみたいです
増えてくるとちょっと分かりにくくなるので、別の保管庫も何れ使えるようになるといいな。
- TailscaleにSSHの接続管理をしてくれる機能が追加されたようです
TailscaleのエージェントにSSHを内包してるのかな?
sshdを立てる必要すらないという事で、結構すごいなーと思った。
こうなると1Passwordとか言ってる次元じゃないよね。
調べようと思ってるけど、いまのところ会社でTailscale使えないので何となく先送りしてる。。。
iTerm2のプロファイルごとに表示する仮想デスクトップ(スペース)を切り替える
自分はMacの仮想デスクトップを常時2つ使っていてデスクトップ1を通常業務に、デスクトップ2はコード書き用にして、iTerm2のプロファイルも通常業務用とコード書き用に分けています。
iTerm2を起動したら任意のスペースに表示するっぽい設定があるのにうまく出来ていませんでした。
改めて試してみたらできちゃったのでメモしておきます。
まずスペースの設定は、 Preferences > Profiles > Window > Space
です。
多分そうだろうと思っていたけどここで間違いないです。
ここで表示したいスペースを選びます。
自分だったら通常業務用の desktop1
プロファイルは Space 1
に、コード書き用の desktop2
プロファイルは Space 2
に設定します。
ここで、スペースを選ぶと注意喚起のメッセージが出ます。
これを無視していたのがよくなかった…
ここに書いてあるように、システム環境設定で ^ 1
とか ^ 2
を有効にしないといけません。
システム環境設定 > キーボード > ショートカット > Mission Control
で、 デスクトップ1へ切り替え
とか デスクトップ2
へ切り替えと出ているのを必要な分だけチェックします。
最後にDockのアイコンから設定を確認します。
iTerm2アイコン右クリック > オプション > 割り当て先
です。
デフォルトで なし
になってると思いますが、自分はうまくいかなくていじってたので なし
に戻します。
これで、プロファイル毎に表示するデスクトップを固定することが出来ました!
gopsutilで温度情報を取得する(OS別)
この記事は、Infocom Advent Calendar 2021 7日目の記事です。
あまり業務とは関係ないのですが、shirou/gopsutilを使ってサーバ情報を表示するアプリを作っている過程で、各種温度情報が取れるのが分かりました。 ただし、Mac、Linux、Windowsでそれぞれ違っていて、試行錯誤したので記録に残しておきます。
今年のアドベントカレンダーは全然埋まってないので、皆さん頑張ってw
Mac
開発をしているのがMacなのでまずはMacでとれるようにします。
個人で使っているMacbook Air(Intel) Mojaveです。
package main import ( "fmt" "os" "github.com/shirou/gopsutil/v3/host" ) func main() { h1, h2, h3, _ := host.PlatformInformation() fmt.Println(h1, h2, h3) t, err := host.SensorsTemperatures() if err != nil { fmt.Println(err.Error()) os.Exit(1) } for _, v := range t { fmt.Printf("sensorKey: %s, temperature: %2.0f, sensorHigh: %2.0f, sensorCritical: %2.0f\n", v.SensorKey, v.Temperature, v.High, v.Critical) } }
実行してみます。
$ go run main.go darwin Standalone Workstation 11.5.1 sensorKey: TA0P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TA1P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TC0D, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TC0H, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TC0P, temperature: 58, sensorHigh: 0, sensorCritical: 0 sensorKey: TB0T, temperature: 36, sensorHigh: 0, sensorCritical: 0 sensorKey: TB1T, temperature: 36, sensorHigh: 0, sensorCritical: 0 sensorKey: TB2T, temperature: 32, sensorHigh: 0, sensorCritical: 0 sensorKey: TB3T, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TG0D, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TG0H, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TG0P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TH0P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TM0S, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TM0P, temperature: 54, sensorHigh: 0, sensorCritical: 0 sensorKey: TN0H, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TN0D, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TN0P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TI0P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TI1P, temperature: 0, sensorHigh: 0, sensorCritical: 0 sensorKey: TW0P, temperature: 49, sensorHigh: 0, sensorCritical: 0
TA0Pとかは、smc_darwin.hで定義されているようです。
https://github.com/shirou/gopsutil/blob/master/v3/host/smc_darwin.h
#define AMBIENT_AIR_0 "TA0P" #define AMBIENT_AIR_1 "TA1P" #define CPU_0_DIODE "TC0D" #define CPU_0_HEATSINK "TC0H" #define CPU_0_PROXIMITY "TC0P" #define ENCLOSURE_BASE_0 "TB0T" #define ENCLOSURE_BASE_1 "TB1T" #define ENCLOSURE_BASE_2 "TB2T" #define ENCLOSURE_BASE_3 "TB3T" #define GPU_0_DIODE "TG0D" #define GPU_0_HEATSINK "TG0H" #define GPU_0_PROXIMITY "TG0P" #define HARD_DRIVE_BAY "TH0P" #define MEMORY_SLOT_0 "TM0S" #define MEMORY_SLOTS_PROXIMITY "TM0P" #define NORTHBRIDGE "TN0H" #define NORTHBRIDGE_DIODE "TN0D" #define NORTHBRIDGE_PROXIMITY "TN0P" #define THUNDERBOLT_0 "TI0P" #define THUNDERBOLT_1 "TI1P" #define WIRELESS_MODULE "TW0P"
CPU関係では、TC0DとTC0Hは取れておらず、TC0Pだけ取れているようです。
PROXIMITYは近い・近接的な意味のようなのでCPU温度を見るならとりあえずTC0Pでよいのかなと思いました。
Windows
お仕事ではWindowsサーバを使うのでこちらも取得してみます。
とりあえず同じコードを実行してみます。
C:\home\gozu\go\src\github.com\gozuk16\cputemp>go run main.go Microsoft Windows 10 Pro Standalone Workstation 10.0.19042 Build 19042 例外が発生しました。 (アクセスは拒否されました ) exit status 1
どうやらWindowsでは管理者権限が必要みたいですね。
管理者権限で実行してみます。
C:\home\gozu\go\src\github.com\gozuk16\cputemp>go run main.go Microsoft Windows 10 Pro Standalone Workstation 10.0.19043 Build 19043 sensorKey: ACPI\ThermalZone\THM0_0, temperature: 40, sensorHigh: 0, sensorCritical: 0
ACPI\ThermalZone\THM0_0というのが1つだけ取れました。
これはWMIの情報のようです。wmicで確認のため同じものを取得してみます。 (この場合も管理者権限が必要です)
> wmic /namespace:\\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature Temperature CurrentTemperature 3132
3132度???
いやいやそんなわけない。
これはケルビンという値を10倍したものが取れるものらしい。
※ケルビンとは絶対温度の事で、摂氏を求めるには「ケルビン - 273.16」とすればよい
つまり、摂氏に直すと 3132 / 10 - 273.16 = 40.04 となります。
どうやらプログラムで取った値は正しそうですね。
管理者権限が必要なのは面倒くさいなぁ。
Linux
VMじゃない実機のLinuxだとラズパイがあるのでやってみました。
Raspberry Pi OS 64bit版にしてあるのですが、どうやらaptで入るGoは1.11という古いバージョンなのでダウンロードして入れます。
$ wget https://golang.org/dl/go1.16.7.linux-arm64.tar.gz $ sudo tar -C /usr/local -xzf go1.16.7.linux-arm64.tar.gz $ vi .bashrc # ↓を追加 export PATH=$PATH:/usr/local/go/bin $ . .bashrc $ go version go version go1.16.7 linux/arm64
同じものを実行します。
$ go run main.go raspbian debian 10.10 sensorKey: cpu_thermal, temperature: 62 sensorHigh: 0, sensorCritical: 0
cpu_thermalというのが1つ取れました。
確認のためコマンドでたたいてみます。
$ cat /sys/class/thermal/thermal_zone0/temp 62322
62322度な訳は無いw
これは1000倍で取れるそうなのであってます。
docker composeでInfluxDBの起動エラー
久しぶりにInfluxDBのdockerを起動したら動かなくなってた。
$ docker compose up [+] Running 2/2 ⠿ Network influxdb_default Created 0.0s ⠿ Container influxdb_influxdb_1 Created 0.0s Attaching to influxdb_1 influxdb_1 | chown: changing ownership of '/var/lib/influxdb2': Permission denied influxdb_1 | chown: changing ownership of '/var/lib/influxdb2/engine': Permission denied influxdb_1 exited with code 1
ぐぐったらこれが引っかかった。
user
を追加したら動いた。
version: '3' services: influxdb: image: influxdb ports: - "8086:8086" volumes: - ./influxdb/data:/var/lib/influxdb - ./influxdb/config:/etc/influxdb2 - ./influxdb/scripts:/docker-entrypoint-initdb.d environment: - DOCKER_INFLUXDB_INIT_MODE=setup - DOCKER_INFLUXDB_INIT_USERNAME=ユーザ名 - DOCKER_INFLUXDB_INIT_PASSWORD=パスワード - DOCKER_INFLUXDB_INIT_ORG=組織を指定 - DOCKER_INFLUXDB_INIT_BUCKET=バケットを指定 - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=トークンをここに書くよ user: "501:501"
Karabiner-elementsでMacのPowerPointの行末移動をctrl+eで出来るようにする
MacのPowerPointでCtrl+eと打つと「文字列中央揃え」になるんですよね。
これ間違いすぎてストレスたまりすぎたのでKarabinerで行末移動になるようにしました。
frontmost_application_if
でオフィス系ソフトとブラウザを指定していますが、
オフィス系ソフトとChromeは上手くいっていて、Firefox、Edge、Safariがまだ上手くいってません。
うーんなんだろう。
{ "description": "Left Control + e to End", "manipulators": [ { "type": "basic", "from": { "key_code": "e", "modifiers": { "mandatory": [ "control" ] } }, "to": [ { "key_code": "end" } ], "conditions": [ { "type": "frontmost_application_if", "bundle_identifiers": [ "^com\\.microsoft\\.Excel$", "^com\\.microsoft\\.Powerpoint$", "^com\\.microsoft\\.Word$", "^org\\.mozilla\\.firefox$", "^org\\.google\\.Chrome$", "^com\\.microsoft\\.edgemac$", "^com\\.apple\\.Safari$" ] } ] } ] }