はじめに
macのストレージがカツカツになりました。
ストレージ不足のせいでXcodeのアップデートができない困った状況です…。
でも、私の環境における諸悪の根源はわかっています。
EthereumのDApps作業用に使っているgethのデータディレクトリです。
rinkebyディレクトリだけで78GBも喰っています…。
こいつをなんとかしてストレージ不足を解消することにしました。
で、試行錯誤の結果、gethのデータを外付けSSDへ移行できたので、その際の手順をメモしておきます。
環境
私の環境は下記となります。
PC:MacBook Air(13-inch, Early 2014)
OS:Catalina(10.15.6)
HD:256GB(フラッシュストレージ)
gethのバージョン:1.9.9
外付けSSD:SanDisk Extreme ポータブル SSD(250GB)
(※ヨドバシで8800円でした)
では、手順を見ていきましょう。
外付けSDDの形式確認/フォーマット
外付けSSDをWindowsパソコンと共有できたら便利なので互換性のあるexFATにしたい所ですが、私の環境ではgethの起動時に下記のエラーがでて同期できませんでした。
Fatal: Error starting protocol stack: listen unix /Volumes/ssd_drive/geth/rinkeby/geth.ipc: bind: invalid argument
ですので、外付けSSDのフォーマットはAPFSにしました。
(※すでに外付けSSDがAPFSでフォーマットされている場合は、下記の手順.2(フォーマット)はスキップしてください)
(※途中まで試した感じだと[Mac OS拡張(ジャーナル)]でも動きそうな感じはしましたが、最後までは試していません)
手順.1:ディスクユーティリティの起動
外付けSSDをmacに接続して[Launcpad]→[その他]→[ディスクユーティリティ]を起動します。
手順.2:外付けSSDのフォーマット
*ご注意*
以下の手順を試す際は、間違ってmacのHDをフォーマットしないように、対象のドライブが外付けのSSDになっているかをよく確認した上で行ってください
対象の外付けSSDを右クリックして[消去...]を選択します。
開いたダイアログにて、フォーマットを[APFS]に設定して、[消去]を実行します。
(※APFSが表示されない場合/エラーがでる場合は後述の[補足:APFSの設定がうまくいかない場合]を参照ください)
(※セキュリティオプションで[最も安全]を選ぶと時間がかかるのでご注意ください=試しにやったら日が暮れました…)
補足:APFSの設定がうまくいかない場合
case.1
APFSが選択できない場合は、一旦[Mac OS拡張(ジャーナル)]形式で消去した後、対象のSSDを右クリックしたメニューから[APFSに変換...]を選択します。
case.2
APFS変換時に「A GUID Partition Table (GPT) partitioning scheme is required.」エラーがでる場合は[diskutil]にて初期化します。
まず、[ターミナル]を起動します。
続いて、下記のコマンドにて外付けSSDのディスク番号を確認します。
$ diskutil list
*実行例*
[MacBook-Air:~ hakumai$ diskutil list
/dev/disk0 (internal, physical):
#: TYPE NAME > SIZE IDENTIFIER
0: GUID_partition_scheme *251.0 GB disk0
1: EFI EFI > 209.7 MB disk0s1
2: Apple_APFS Container disk1 250.8 GB disk0s2/dev/disk1 (synthesized):
#: TYPE NAME > SIZE IDENTIFIER
0: APFS Container Scheme - +250.8 GB disk1
Physical Store disk0s2
1: APFS Volume Macintosh HD - Data 221.2 GB disk1s1
2: APFS Volume Preboot 82.3 MB disk1s2
3: APFS Volume Recovery 528.8 MB disk1s3
4: APFS Volume VM 1.1 GB disk1s4
5: APFS Volume Macintosh HD 11.1 GB disk1s5/dev/disk2 (external, physical):
#: TYPE NAME > SIZE IDENTIFIER
0: GUID_partition_scheme *250.1 GB disk2
1: EFI EFI 209.7 MB disk2s1
2: Microsoft Basic Data 名称未設定 249.8 GB disk2s2
↑ 私の環境では、外付けSSDが[disk2]として認識されていました。
ディスク番号がわかったら、下記のコマンドにて外付けSSDをフォーマットします。
$ diskutil eraseDisk APFS [設定するドライブ名] [対象のディスク番号]
*実行例*
[MacBook-Air:~ hakumai$ diskutil eraseDisk APFS ssd_drive disk2
Started erase on disk2
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk2s2 as APFS with name ssd_drive
Mounting disk
Finished erase on disk2
↑ドライブ名を[ssd_drive]、ディスク番号を[disk2]でフォーマットした例です。
case.3
[diskutil]の[APFS]指定で失敗する場合は、オプション[JHFS+](Mac OS拡張)で初期化し、その後[case.1]の手順をお試しください。
$ diskutil eraseDisk JHFS+ [設定するドライブ名] [対象のディスク番号]
手順.3:ドライブ名の設定
ドライブ名をクリックしてお好きな名前をつけましょう。
ここでは[ssd_drive]としました。
gethの同期時に、このドライブ名でパスを指定することになります。
例えば上記例であれば、パスは[/Volumes/ssd_drive]となります。
gethで同期
外付けSSDに適当なディレクトリを作成してgethの同期を開始します。
(※ここでは接続先をRinkebyテストネットとしています)
(※外付けSSDに作成した[geth/rinkeby]ディレクトリを保存先にしたいので、パスとして[/Volumes/ssd_drive/geth/rinkeby]を指定しています)
$ geth --rinkeby --datadir /Volumes/ssd_drive/geth/rinkeby
↓同期中、retryが出まくったのでかなりドキドキしました(※外付けSSDへの書き込みが遅いせいかもしれません…)。
count=1920 elapsed=10.325ms processed=163021371 pending=6704 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:07.173] Imported new state entries count=1920 elapsed=12.420ms processed=163023291 pending=5893 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:07.927] Imported new state entries count=1536 elapsed=8.910ms processed=163024827 pending=5925 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:08.735] Imported new state entries count=1536 elapsed=8.045ms processed=163026363 pending=6121 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:09.517] Imported new state entries count=1536 elapsed=9.212ms processed=163027899 pending=5965 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:10.249] Imported new state entries count=1920 elapsed=11.310ms processed=163029819 pending=5222 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:10.916] Imported new state entries count=1536 elapsed=9.066ms processed=163031355 pending=4988 retry=0 duplicate=18423 unexpected=60488
ですが、ひたすら放置しておいたら、同期が完了してくれました。
↓下記のログが出力されたら同期の完了です(※gethを終了するには[Ctrl+C]を入力します)。
INFO [01-06|08:59:34.821] Fast sync complete, auto disabling
同期にかかった時間は24時間弱、ほぼ丸一日でした。
感覚的にはmacのHD(フラッシュストレージ)を対象にした時に比べて、2〜3倍遅い印象です。
mac側のコネクタがType-Aなので、Type-Cの利用できるmacならもっと速いのではないかと思います。
truffleとの連携確認:読み込み
同期したデータディレクトリを対象にgethをRPCモードで起動します。
$ geth --allow-insecure-unlock --rpc --rpcapi personal,web3,eth,net --verbosity 0 console --rinkeby --datadir /Volumes/ssd_drive/geth/rinkeby
次に、ターミナルの別タブからTruffleを起動します
(※rinkebyのネットワーク設定がされているプロジェクトフォルダへ移動してから起動してください)
$ truffle console --network rinkeby
テストアカウントの残高を確認します(※残高表示が0だったり実際の値と違う場合は同期が完了していないので再同期してください)。
truffle(rinkeby)> web3.eth.getBalance( accounts[0] )
'474167714324901098982'
MetaMask等で残高を増減した後、再度残高を確認します(※ここでは[0.16ETH]減らしてみました)。
truffle(rinkeby)> web3.eth.getBalance( accounts[0] )
'474005299324901098982'
ちゃんと同期がとれています。
[truffle]との連携確認:デプロイ
スマートコントラクトをデプロイしてみます。
(※プロジェクトのビルドが通り、migrateの設定に問題がない状況でデプロイしてください)
[truffle(rinkeby)> migrate --f 2
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Migrations dry-run (simulation)
===============================
> Network name: 'rinkeby-fork'
> Network id: 4
> Block gas limit: 10000000 (0x989680)
2_deploy_contracts.js
=====================
Replacing 'HelloWorld'
----------------------
> block number: 7844413
> block timestamp: 1609893660
> account: 0xebfCB28c530a9aAD2e5819d873EB5Cc7b215d1E1
> balance: 474.003238390901098982
> gas used: 1030467 (0xfb943)
> gas price: 2 gwei
> value sent: 0 ETH
> total cost: 0.002060934 ETH
-------------------------------------
> Total cost: 0.002060934 ETH
Summary
=======
> Total deployments: 1
> Final cost: 0.002060934 ETH
Starting migrations...
======================
> Network name: 'rinkeby'
> Network id: 4
> Block gas limit: 10000000 (0x989680)
2_deploy_contracts.js
=====================
Replacing 'HelloWorld'
----------------------
> transaction hash: 0xdf4bb76e2ca3913cd637cd7ceaeec0aafc409743493cf3fbb10c85249c7f2ec7
> Blocks: 1 Seconds: 4
> contract address: 0xaD1c3A4E6E19955C4a3cdB993843d7aC78F7294c
> block number: 7844412
> block timestamp: 1609893664
> account: 0xebfCB28c530a9aAD2e5819d873EB5Cc7b215d1E1
> balance: 473.984389984901098982
> gas used: 1045467 (0xff3db)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.02090934 ETH
> Saving artifacts
-------------------------------------
> Total cost: 0.02090934 ETH
Summary
=======
> Total deployments: 1
> Final cost: 0.02090934 ETH
デプロイも問題なく完了しました。
外部クライアントから適当にアクセスし、その結果もEthescanから確認できました。
https://rinkeby.etherscan.io/address/0xaD1c3A4E6E19955C4a3cdB993843d7aC78F7294c
どうやら問題なく動いているようです。
結果として、mac側のストレージから[geth]のデータディレクトリを削除することができました。
空き容量も100GBを回復して、Xcodeのアップデートも無事完了しました。
めでたしめでたし。
まとめ
gethの同期先を外付けSSDを対象にした場合、macのHDと比べて同期に時間がかかるので、ストレージをとるか速さをとるかで検討しましょう。
たまにsolidityをいじってデプロイする程度のgeth利用であれば、データを外付けSSDへ移行するのは十分ありだと思います。