- 投稿日:2020-07-31T21:30:20+09:00
DynamoDBのデータをnode.jsのReadableStreamに流す
DynamoDBテーブルのデータをざーっと
ReadableStream
に流し込みたかったが、どうやってバックプレッシャーに対応すればいいのか分からなかったので対応させてみた。やりたいこと
- DynamoDBからデータを読み込む(基本は内部バッファサイズ分)
ReadableStream
にpush- ひたすら読み込んではpush
- 詰まったら一時停止
- 次回開始位置をpushしきれなかったアイテムに設定
- またpushできるようになったら続きから読み込み再開
- 以下繰り返し
- 全て読み込んでpushし終わったら処理終了
DynamoDBのQuery/ScanとLimit
DynamoDBのQuery/Scan操作では
Limit
を指定することで取得件数を制限することができる。
ただLimit
は検索結果の件数制限でなので、QueryFilter
やScanFilter
を掛けると検索結果がさらにフィルタリングされ指定した件数より少ない件数が返ってくる場合がある。クエリーで検索し、指定件数分の結果が揃ったら、クエリーフィルターでさらに絞る、というのはDynamoDBに限らずよくあるのでおそらく同じ動作なんだと思う。
まぁこれは
Limit
を指定してもフィルターを指定すると思ったとおりの件数は返ってこないですよ、という注意事項。DynamoDBのページネーション
DynamoDBのQuery/Scanは読み込みサイズが1MBを超えるとそこで帰ってくる。
Limit
を指定した場合も途中で帰ってくる。
まだ全てのデータを読み込み終えてない場合、次ページを取得するための開始地点がレスポンスに含まれる。
レスポンスに含まれるLastEvaluatedKey
を次回Query/Scan時のリクエストにExclusiveStartKey
として含めれば次ページを取得できる仕組みになっている。
LastEvaluatedKey
は実際にはプライマリーキー(パーティションキーあるいはパーティションキーとソートキーの組み合わせ)のオブジェクトである。
なのでLastEvaluatedKey
でなく、レスポンスに含まれるアイテムの何番目かをぶち込めば次回の読み込み開始位置はその項目の次からになる。なった。これを利用して、
ReadableStream
にpushしている途中でReadableStream
の内部バッファが一杯になった場合は、入り切らなかった次のアイテムを読み込み開始位置としてExclusiveStartKey
に設定することにした。ReadableStreamのハイウォーターマーク
ReadableStream
は内部バッファを持っていて、そのサイズ=閾値をハイウォーターマーク(HWM)という。
オブジェクトモードの場合はデフォルトで16
に設定されている。
データをpush
し続けてHWMに達すると、
push
がfalse
を返す_read
が呼ばれなくなるそれで内部バッファに空きがでると再び
_read
が呼ばれるらしい。
またpush
がfalse
を返しても内部バッファには詰め込まれてた気がする。たしか。HWMが上がるんだったかな・・・ということで、Query/Scanで取得したデータをpushしてる最中に
false
を返した場合はそこで処理を中断し、次のアイテム以降は残念ながら次回のQuery/Scan時に再取得することにした。諸々踏まえて
最終的にこんな感じの実装になった。
切り貼りしてたのでこのままでは動かないかも。雰囲気を感じ取って欲しい。class DynamoDBStream extends stream.Readable { : _read(size) { // 何度も呼ばれるので if (!this.#querying) { this.#querying = true; this.#params.Limit = size || this.hwm; this._query(this.#params); } } // HWMに達するまで再帰的にQueryを実行する _query(params) { const recursiveQuery = (params) => { // AWS.DynamoDB.DocumentClient.query() this.#ddb.query(params, (err, data) => { : let abort = false; for (const item of queryResult.Items) { // HWMに達したらそのitemまで処理済みとし次回の開始位置を指定して中断 if (!this.push(item)) { params.ExclusiveStartKey = item; abort = true; break; } } // 中断したら次の読み込み要求を待つ if (abort) { this.#querying = false; // 次ページがなかったら処理終了 } else if (typeof queryResult.LastEvaluatedKey === "undefined") { this.push(null); this.#querying = false; // 中断せず、次ページがあれば続けて次ページを取得 } else { params.ExclusiveStartKey = queryResult.LastEvaluatedKey; recursiveQuery(params); } }); } recursiveQuery(params); } : }余談: DynamoDBのコスト
リクエスト単位で課金される。また、結果整合性のある読み込みが一番安い。
Limit
を小さく指定しすぎるとリクエスト数が増えてしまい、ちゃりんちゃりん課金されてしまう。かと言って、あんまり
Limit
を大きくしてしまうと、詰め込みきれなかったデータが無駄になってしまうのでうまく調整しないといけない。頻繁にリクエストが細分化してしまう場合は、いっそのことStreamとは別にバッファを持ったほうがいいかもしれない。
- 投稿日:2020-07-31T20:52:26+09:00
Linuxでts-node-devを使うときに、エラー `ERR_FEATURE_UNAVAILABLE_ON_PLATFORM` が発生したときの対処法
発生したエラー
TypeError [ERR_FEATURE_UNAVAILABLE_ON_PLATFORM]: The feature watch recursively is unavailable on the current platform, which is being used to run Node.js at Object.watch (fs.js:1470:11) at add (/home/reoring/git/yyts/yychat-server/node_modules/filewatcher/index.js:74:34) at /home/reoring/git/yyts/yychat-server/node_modules/filewatcher/index.js:93:5 at FSReqCallback.oncomplete (fs.js:177:5)対処法
node-devの起動オプションに
--poll
を追加する。"scripts": { "start:dev": "ts-node-dev --poll src/index.ts", },参考
- 投稿日:2020-07-31T18:33:41+09:00
nodeの使用可能メモリを増強する場合、vm.max_map_countによる制限がかかることがある
環境
- 言語:node v14.7.0
- CPU
- AMD Ryzen 9 3900X 12-Core Processor
- Processer 24
- メモリ容量:62.8GB
- OS:Ubuntu 18.04.4 LTS (Bionic Beaver)
あらまし
メモリを64GB搭載しているUbuntu上で、
--max-old-space-size
オプションによって最大消費メモリを48GBに拡張した状態でnodeを動かしたところ、プログラムの内容に依存して、48GBを使い切れる場合と、20GB程度を消費した時点でメモリエラーが発生する場合の2通りの挙動があった。その原因はプログラムの動作の違いによるメモリアロケーションの仕方の違いにあり、メモリを使い切れないプログラムではマッピング数が超過することによりmmapシステムコールがENOMEMを発生させることによるものだった。
sudo sysctl -w vm.max_map_count=655300
コマンドによりシステムの最大マッピング数を拡張した結果、与えたメモリをプログラムが使い切れるようになった。はじめに
消費メモリの表示
次のブロックコードは、bash上でnodeの消費メモリを表示するワンライナーを動かした様子である。
$ node -e 'console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' 0.02828216552734375次のものは10,000,000個の数値の0で構成される配列を作った後で消費メモリを見た様子である。
$ node -e 'var a = Array.from({length: 10000000}, v => 0); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' 0.10385513305664062消費メモリは0.028GBから0.103GBに少し上がっている。
10メガ個の整数が70MB程度の消費を生み出したことになる。
--max-old-space-size
を指定しないとメモリ上限がすぐに訪れるでは、0ではなく100個の0で構成された配列を生成したらどうだろうか。
$ node -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 100}, v => 0)); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);'この環境には64GB程度のメモリがあるので、物理的には足りそうな気がする。
しかし、nodeが5GB程度を消費した段階で次のようなエラーが出る。$ node -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 100}, v => 0)); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' <--- Last few GCs ---> [27037:0x648f650] 45191 ms: Scavenge 4093.1 (4100.7) -> 4093.0 (4101.5) MB, 5.7 / 0.0 ms (average mu = 0.125, current mu = 0.081) allocation failure [27037:0x648f650] 45204 ms: Scavenge (reduce) 4094.0 (4105.5) -> 4094.0 (4106.2) MB, 5.6 / 0.0 ms (average mu = 0.125, current mu = 0.081) allocation failure [27037:0x648f650] 45218 ms: Scavenge (reduce) 4095.1 (4100.5) -> 4095.0 (4103.7) MB, 6.2 / 0.0 ms (average mu = 0.125, current mu = 0.081) allocation failure <--- JS stacktrace ---> FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 0x9fd5f0 node::Abort() [node] 2: 0x94a45d node::FatalError(char const*, char const*) [node] 3: 0xb7099e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node] 4: 0xb70d17 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node] 5: 0xd1a905 [node] 6: 0xd1b48f [node] 7: 0xd294fb v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node] 8: 0xd2d0bc v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node] 9: 0xcfb7bb v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node] 10: 0x1040c4f v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node] 11: 0x13cc8f9 [node] Aborted (core dumped)
Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
でGoogle検索すると、次のような--max-old-space-size
でnodeが消費できるメモリの上限を拡張すればいいという記事が大量に得られた。この環境には64GBのメモリがあるので、では48GBまで消費できるようにしてみよう。
$ node --max-old-space-size=$((1024 * 48)) -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 100}, v => 0)); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' 8.26059341430664無事、8.2GBのメモリを消費したのち正常に終了した。
指定されたメモリを使い切れない
では、「100個の0で構成された配列」ではなく「1000個の空配列で構成された配列」を生成したらどうだろうか。
そもそも消費メモリは10倍になるはずなのでメモリ不足になるはずである。
更に0ではなくここでは空配列を生成してみる。$ node --max-old-space-size=$((1024 * 48)) -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 1000}, v => [])); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);'予想では、48GBを使い切ってメモリ不足によるエラーで異常終了するはずである。
48GBを使い切る前にはガベージコレクションによって動作速度が極端に遅くなることも考えられる。
結果は、たったの16.8GBを消費した時点で次のようなエラーで終了した。
前節の結果により、--max-old-space-size
の効果は表れていることは判明している。$ node --max-old-space-size=$((1024 * 48)) -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 1000}, v => [])); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' <--- Last few GCs ---> [10261:0x648f730] 77051 ms: Scavenge 16379.4 (16414.4) -> 16377.4 (16428.1) MB, 32.2 / 0.0 ms (average mu = 0.794, current mu = 0.795) allocation failure [10261:0x648f730] 77103 ms: Scavenge 16393.4 (16428.1) -> 16395.3 (16430.4) MB, 27.8 / 0.0 ms (average mu = 0.794, current mu = 0.795) allocation failure [10261:0x648f730] 77189 ms: Scavenge 16395.3 (16430.4) -> 16393.6 (16441.6) MB, 86.3 / 0.0 ms (average mu = 0.794, current mu = 0.795) allocation failure <--- JS stacktrace ---> FATAL ERROR: Scavenger: semi-space copy Allocation failed - JavaScript heap out of memory Segmentation fault (core dumped)また、何回か実行するとエラー文がランダムで次のものになることがあった。
$ node --max-old-space-size=$((1024 * 48)) -e 'var a = Array.from({length: 10000000}, v => Array.from({length: 1000}, v => [])); console.log(process.memoryUsage().rss / 1024 / 1024 / 1024);' terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)どうして
--max-old-space-size
で48GBを指定しても16.8GBしか使っていない状態で終了するのだろうか?
どうすれば48GBを使い切ることができるのだろうか?調査
48GBを使い切れるコードと使い切れないコード
次のコードは、メモリ消費量の表示回数を上げたものである。
$ node --max-old-space-size=$((1024 * 48)) -e 'Array.from({length: 10000}, v => { console.log(process.memoryUsage().rss / 1024 / 1024 / 1024); return Array.from({length: 1000000}, v => []); });'実行するとひたすらメモリ消費量を表示し、20GB程度で異常終了した。
<前略> 20.046581268310547 20.084598541259766 20.122615814208984 20.160381317138672 terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped)
次のコードはそれを「空配列の配列の配列」ではなく「1の配列の配列」を生成するようにしたものである。
$ node --max-old-space-size=$((1024 * 48)) -e 'Array.from({length: 10000}, v => { console.log(process.memoryUsage().rss / 1024 / 1024 / 1024); return Array.from({length: 1000000}, v => 1); });'このコードは20GBで止まらず、指定された約48GBのメモリを使い果たして終了する!
しかも消費メモリが46GBを超えたあたりから頻繁にガベージコレクションでカクつき、なかなか消費メモリが上がらない状態になったアキレスと亀。<前略> 48.053977966308594 48.06153106689453 48.06904602050781 48.076324462890625 48.08384323120117 <--- Last few GCs ---> <中略> <--- JS stacktrace ---> FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 0x9fd5f0 node::Abort() [node] <中略> 17: 0x1018255 v8::internal::Runtime_NewArray(int, unsigned long*, v8::internal::Isolate*) [node] 18: 0x13cc8f9 [node] Aborted (core dumped)
変わったのはデータ構造の最深部が空配列か数値の1かだけ。
どちらも物理メモリがそもそも足りないので最終的に異常終了することには変わらない。
std::bad_alloc
はC++のnewが失敗したときのエラーらしい
std::bad_alloc
でGoogle検索すると、それがC++のnewから出されるものであることが分かった。nodeはC++で書かれていて、newを行っている箇所があるということになる。
std::bad_alloc
はC++のtry文で捕捉できるが、出る場所がnewという一般的なところであるだけに捕捉される個所とされない箇所の両方で発生する可能性があるのだろう。
それがエラー文がランダムで変わる原因と予想する。straceで見ると、mmapがENOMEMというエラーを出していることが分かった
straceとはプロセスのシステムコールを出力できるコマンドである。
とりあえず次のようにnodeの前に置いて実行してみた。
$ strace node --max-old-space-size=$((1024 * 48)) -e 'Array.from({length: 10000}, v => { console.log(process.memoryUsage().rss / 1024 / 1024 / 1024); return Array.from({length: 1000000}, v => 1); });'怒涛のログが出力されるが、その末尾は次のようになっている。
<前略> mprotect(0x29960bbc0000, 262144, PROT_READ|PROT_WRITE) = 0 brk(0x1bf9a000) = 0x1bf9a000 mmap(0x2ebbbafc0000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x2ebbbafc0000 munmap(0x2ebbbb000000, 258048) = 0 mprotect(0x2ebbbafc0000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x3ba59c200000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x3ba59c200000 munmap(0x3ba59c240000, 258048) = 0 mprotect(0x3ba59c200000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x3f3009d40000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x3f3009d40000 munmap(0x3f3009d80000, 258048) = 0 mprotect(0x3f3009d40000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x330b57380000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x330b57380000 munmap(0x330b573c0000, 258048) = 0 mprotect(0x330b57380000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x207b9d440000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x207b9d440000 munmap(0x207b9d480000, 258048) = 0 mprotect(0x207b9d440000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x300db2380000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x300db2380000 munmap(0x300db23c0000, 258048) = 0 mprotect(0x300db2380000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x8e44e340000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x8e44e340000 munmap(0x8e44e380000, 258048) = 0 mprotect(0x8e44e340000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x1a79a5c00000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x1a79a5c00000 munmap(0x1a79a5c40000, 258048) = 0 mprotect(0x1a79a5c00000, 262144, PROT_READ|PROT_WRITE) = 0 mmap(0x9abb4d00000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(0x9abb4d00000, 520192, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mprotect(0xafbb8382000, 86016, PROT_READ|PROT_WRITE) = 0 mprotect(0xafbb83c2000, 249856, PROT_READ|PROT_WRITE) = 0 mprotect(0xafbb8402000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0xafbb8442000, 4096, PROT_READ|PROT_WRITE) = 0 mprotect(0xafbb8482000, 4096, PROT_READ|PROT_WRITE) = 0 mmap(NULL, 1040384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) brk(0x1c0a2000) = 0x1bf9a000 mmap(NULL, 1175552, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(0x7efbe4000000, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory) mmap(NULL, 1040384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory) futex(0x7efbfebab1a0, FUTEX_WAKE_PRIVATE, 2147483647) = 0 write(2, "terminate called after throwing "..., 48terminate called after throwing an instance of ') = 48 write(2, "std::bad_alloc", 14std::bad_alloc) = 14 write(2, "'\n", 2' ) = 2 write(2, " what(): ", 11 what(): ) = 11 write(2, "std::bad_alloc", 14std::bad_alloc) = 14 write(2, "\n", 1 ) = 1 rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0 rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0 getpid() = 15400 gettid() = 15400 tgkill(15400, 15400, SIGABRT) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 --- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=15400, si_uid=1003} --- +++ killed by SIGABRT (core dumped) +++ Aborted (core dumped)ここで、以下の行によって、mmapという部分で
ENOMEM
というエラーが出ていることが分かる。
なぜメモリは余っているのにCannot allocate memory
なのだろうか。mmap(NULL, 67108864, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = -1 ENOMEM (Cannot allocate memory)ENOMEMが出る条件はメモリ不足およびマッピング数超過
mmapのmanに重要な情報が書いてあった。
ENOMEM
メモリーに空きがない、または処理中のプロセスのマッピング数が最大数を超過した。
マッピング数が最大数を超過した
場合、メモリが余っていてもENOMEMが出る。
出るエラー自体は共通のENOMEMなので、おそらくプログラムから見るとメモリ不足と区別できないだろう。
JavaScript heap out of memory
というエラーメッセージになるのも納得できる。
sudo sysctl -w vm.max_map_count=
で最大マッピング数を増加できる次の場所からマッピング数の上限を増やす方法が得られた。
sysctl vm.max_map_count
で現在の値が分かる。
sudo sysctl -w vm.max_map_count=65536
で値を設定できる。変更はシステム全体に影響し、再起動で元に戻るらしい。
対策
vm.max_map_count
の値を現在の10倍にしてみた。$ sysctl vm.max_map_count vm.max_map_count = 65530 $ sudo sysctl -w vm.max_map_count=655300 vm.max_map_count = 655300結果
対策後、再び空配列の配列の配列を生成するコードを起動してみた。
$ node --max-old-space-size=$((1024 * 48)) -e 'Array.from({length: 10000}, v => { console.log(process.memoryUsage().rss / 1024 / 1024 / 1024); return Array.from({length: 1000000}, v => []); });'その結果、期待通り与えた約48GBのメモリを最後まで使い切ってから異常終了するようになった。
<前略> 48.66949462890625 48.756752014160156 48.79401397705078 48.831199645996094 48.86867141723633 <--- Last few GCs ---> <中略> <--- JS stacktrace ---> FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 0x9fd5f0 node::Abort() [node] <中略> 11: 0x13cc8f9 [node] Aborted (core dumped)あとがき
結局node固有の問題ではなかった。
C++の問題ですらなかった。当初は「16.8GB」で止まるという点からヒープサイズが別に制限されていたり、GCの関係でメモリの使い方がそういうものなのかと考えたり、C++で22億個のオブジェクトをnewすると32ビット整数が足りなくなってnewに失敗するのかもしれないとか考えていた。
- 投稿日:2020-07-31T14:31:30+09:00
nodebrewで入れたnodeが存在するのにno such file or directoryになる問題
【注意】これを読んでも解決しません
環境
- Raspberry Pi 4
- Ubuntu Mate 64bit
- nodebrew 1.0.1
- node v12.18.3
症状
nodeコマンドが実行できない
$ node -v -bash: /home/user/.nodebrew/current/bin/node: No such file or directory$ ls -la /home/user/.nodebrew/current/bin/node -rwxr-xr-x 1 user user 40769188 7月 31 14:06 /home/user/.nodebrew/current/bin/nodeあるじゃないか!!!
…存在するファイルの no such file or directory は、どうやら32bitに対応していない64bit OSで32bitのバイナリを実行しようとしたときに出るらしい?
諦め
たぶん
「Can we update the $arch for aarch64 to have capability to choose arm64?」
このissueが原因なのですが、PRも放置されマージされそうにないので、諦めて他の方法で入れようと思います