- 投稿日:2020-07-31T23:44:49+09:00
Vagrantを使って仮想マシンを楽に構築する
気になるLinuxを試しに使ってみたい時はVirtualBoxなどの仮想マシンを使うと思います。実験とか一時的な環境であればそれで十分ですが、何かソフトウェアの実行環境、または開発環境として仮想マシンを使う場合は環境構築にかかる作業が手間に感じる時があります
ある程度手を付けて環境が汚れてきて初期状態に戻したい時や、別の環境を用意したくなった時にVagrantを使えば環境構築の手順を自動的に進めることができるので、手間を省くことができます
install
以下のURLからVagrantとVirtual Boxのそれぞれのパッケージをダウンロードしてインストールします
- Vagrant
- VirtualBox
Boxを選ぶ
Vagrant Cloudのサイトから欲しいOSのイメージ(BOX)を探します
https://app.vagrantup.com/boxes/search
色々な人が作っているBoxがあって良し悪しがありますが、以下の物を選ぶと安心でしょう
- hashicorp (Vagrantの公開元)
- bento(Chef社)
init
公開されているイメージを自分のPCにダウンロードして、仮想マシンの初期化をします。Vatrant Cloudで見つけたBoxの名前を
vagrant init
コマンドに指定して実行しますターミナル(Windowsの場合はPowerShell)を開いてコマンドを実行します
イメージのダウンロードと初期化# 実行前に作業ディレクトリを作り、その中で作業します > mkdir vagrant > cd vagrant # 例として Ubuntu/xenial をダウンロードします > vagrant init ubuntu/xenial64実行した場所にVagrantfileが作られます
実行結果> vagrant init ubuntu/xenial64 A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.Vagrantfileの編集
必要に応じて用意したい仮想マシンの設定したい時は、生成されたVagrantfileを編集します。変更を間違えて初期状態に戻したい時はVagrantfileを削除して、再度
vagrant init <Box名>
を実行すればやり直せますVagrantfileの詳しい説明については https://www.vagrantup.com/docs/vagrantfile をご参照ください。大体の項目はVirtualBoxの設定操作に紐づいていますので、必要な所は感覚的に分かると思います
変更したVagrantfileを適用するには
--provision
オプションを指定して実行します# 仮想マシンが起動していない場合 > vagrant up --provision # 起動中の仮想マシンを再起動させて適用する場合 > vagrant reload --provision起動
Vagrantfileのあるディレクトリ内で
vagrant up
を実行します> vagrant up # 複数の仮想マシンがインストールされている場合は `--provider` オプションで明示して実行します > vagrant up --provider virtualboxssh
起動した仮想マシンのシェルを操作するには
vagrant ssh
を実行します> vagrant sshポートフォワーディングの設定をした場合は2222番ポート(デフォルト状態)に接続すればssh接続で操作することもできます。以下でログインできます
- ユーザー名: vagrant
- パスワード: vagrant
停止
起動した仮想マシンを停止するには、Vagrantfileのあるディレクトリ内で
vagrant halt
を実行します> vagrant haltその他のコマンド
よく使用するコマンドをまとめました
コマンド 動作 メモ vagrant box add Boxをダウンロードします vagrant box remove ダウンロードしたBoxを削除します vagrant box list ダウンロードしたBoxの一覧を表示します vagrant init 仮想マシンの初期化 実行したディレクトリにVagrantfileが作成されます vagrant ssh 起動した仮想マシンのsshシェルを開きます Vagrantfileのあるディレクトリで実行します vagrant up 仮想マシンを起動します Vagrantfileのあるディレクトリで実行します vagrant halt 仮想マシンを停止します Vagrantfileのあるディレクトリで実行します vagrant reload 仮想マシンを再起動します Vagrantfileのあるディレクトリで実行します vagrant destroy 仮想マシン削除 Vagrantfileのあるディレクトリで実行します vagrant package 仮想マシンをパッケージング(Box形式で出力)します tips
ファイルの保存先
通常は上記の
vagrant
コマンドで削除すればいいですが、Vagrantをアンインストールしてしまった時は以下の場所を開いて、ファイルを削除すればいいですダウンロードしたBox
~/.vagrant.d/boxes
~
はユーザーのホームディレクトリ(WindowsならばC:\users\ユーザー名
)です仮想マシンの関連ファイル
~/VirtualBox VMsGuest Additionsのバージョンを上げる
仮想マシンにインストールされているAdditionsのバージョンが古いなどで上手く動かない場合は以下のコマンドでバージョンを上げることができます
> vagrant plugin install vagrant-vbguest双方向に読み書きできる共有フォルダーを作る
Vagrantfile に以下の記述を追加します。上記の手順でGuest Additionsを最新にするとトラブルは少ないと思います
config.vm.synced_folder "./output", "/vagrant/output", type:"virtualbox"
- 投稿日: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-31T18:29:09+09:00
【AWS×WordPress】504 Gateway Time-outが出た
はじめに
AWS(AWS Linuxインスタンス)上でWordPressをたてて使用していたが、ある日突然504 Gateway Time-outが出た。
504 Gateway Time-outの意味
Wikipediaによると、5XXはサーバエラーを指し、504は「ゲートウェイタイムアウト。ゲートウェイ・プロキシサーバはURIから推測されるサーバからの適切なレスポンスがなくタイムアウトした。」を意味する。サーバ側のエラーということでAWS上での問題っぽそう。
色々試してみる
試したこと①
AWS上に構築したWordPressで「504 gateway timeout」が頻発した時の対処法
ALBのターゲットグループをhttp&https→httpに変更したということだが、もともとhttpだった。試したこと②
【504 Gateway Time-out】【Bad Request】でブログがつながらない!AWSのELBをチェック
DNS名・IPアドレス直打ちで入れたらアクセスできたというが、今回はできず。試したこと③
【WordPress】504 Gateway Time-out が出た時の対処法
$ df -hストレージの容量を確認できるとのことだが、使用% を見ても、特に割合が高くなかった。
試したこと④
【AWS】【WordPress】「504 Gateway Timeout Error」の原因
Apacheが起動しているかを確認するとのこと。$ sudo systemctl status httpd.serviceこの時
Active: active (running)
になっていたため、てっきりApache側での問題ではないと勘違いしていたが、これは間違いだった。解決策
$ sudo systemctl restart httpd.service今回はApahceがいつの間にか落ちてしまったらしく、上記コマンドでApacheを再び起動させ、504エラーが解消されWordPressの画面が表示された。
statusで確認してもたまにうまく反映できてないことがあるらしいので、psコマンドでちゃんとプロセスが起動しているかを確認する方が確実とのこと。反省点
ネット記事を探して手当たり次第、試していたが下記記事のようにもう少し問題点を切り分けて行うべきだった。
インフラ苦手な人が知っておくといい、Webサイトにつながらない障害パターンと解決方法
ググった方が早い場合もあるが、インフラ力を高めるためにもログなどで原因を予測した上で確認したい。
- 投稿日:2020-07-31T18:04:28+09:00
[Zabbix] Web監視の応答時間は画像ファイルなども含む?
はじめに
ZabbixのWeb監視は応答時間(Response time)を取得しグラフ表示できますが、画像ファイルなど全ての要素を読み込んだ時間なのか、それともHTMLファイル単体なのか検証してみました。
環境
- Zabbix 4.0.1
- CentOS 7.5 + Apache 2.4
Webブラウザから
まずは普通にクライアントからWebブラウザでページ表示し、その時のWebサーバーのログを確認してみます。
access_log172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET / HTTP/1.1" 200 454 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo1.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo2.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo5.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo3.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo4.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo7.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /logo8.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:52 +0900] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0" 172.16.xx.xx - - [14/Nov/2018:13:54:53 +0900] "GET /logo6.png HTTP/1.1" 200 51614 "http://172.16.yy.yy/" "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0"PNG形式の画像ファイルなどもログに記録されていることが分かりました。
Zabbixから
次にZabbixのWeb監視を設定し、監視時のWebサーバーのログを確認。
access_log172.16.zz.zz - - [14/Nov/2018:13:57:38 +0900] "GET / HTTP/1.1" 200 454 "-" "Zabbix"ログに記録されたのは『GET /』だけでした。
つまりHTMLファイル単体のみ読み込んでいることが分かります。さいごに
3秒ルールという言葉があるようにWebサイトの表示速度は重要ですが、ZabbixのWeb監視の応答時間はそのままユーザーからみた表示時間とならないので鵜呑みにしないようにしましょう。
- 投稿日:2020-07-31T16:06:31+09:00
Docker コンテナ内でmatplotlibなどを使った画像表示されない場合の対処法
Docker コンテナ内でmatplotlib等で画像表示しようと思ったらこけたので記します
Ubuntu 16.04.6 LTS環境でやってます。[問題点]
Docker run した後にコンテナに入り、matplotlibでplot.show()すると画像が何も表示されず、コマンドが終わる。
もしくはdocker _tkinter.TclError: couldn't connect to display
_tkinter.TclError: no display name and no $DISPLAY environment variable
_tkinter.TclError: couldn't connect to display :0.0
みたいなエラーが出てくる。[対処法]
①まずターミナルに以下のコマンドをうつ$sudo apt-get install x11-xserver-utils $xhost +②docker run する時には以下をオプションにつける
-v /tmp/.X11-unix:/tmp/.X11-unix
-e DISPLAY=unix$DISPLAY
③もしmatplotlibがコンテナに入ってなかったらコンテナ起動後のインテラクティブモードで
pip install matplotlib
④ もしtkinterがコンテナに入っていなかったらコンテナ起動後のインテラクティブモードで
apt-get update
apt-get python3-tk
なおpython3-tkをインストールする際、居住地域を答えるくだりがありました。これでうまくコンテナ内でも画像表示されるようになりました。
- 投稿日:2020-07-31T15:37:44+09:00
Linuxに ps の代替ツール procs をインストール(Mac・Windowsでも使える)
メモリやCPU使用率が見やすくなる
https://github.com/dalance/procs1. インストール
$ sudo rpm -i https://github.com/dalance/procs/releases/download/v0.10.3/procs-0.10.3-1.x86_64.rpm2. 設定
リンク先の設定を反映(https://github.com/dalance/procs/blob/master/config/large.toml)
$ mkdir -p ~/.config/procs/ $ vi ~/.config/procs/config.toml3. 使用例
$ procs $ procs --sortd cpu $ procs --sortd rss $ procs --sortd rss nginx
- 投稿日:2020-07-31T09:59:46+09:00
systemdで/var/run配下にUNIX Socket用のディレクトリを切ったら落とし穴にハマった件と対処法
動作確認環境
- CentOS7のサーバ
※Ubuntu20.04も同じ実装なので同じくハマるかと思います
落とし穴にハマった流れ
やりたいこと
hoge
というアプリケーションのAPIサーバを建てたい
- フロントは
nginx
でリクエストを受けてアプリケーションに渡すhoge
はsystemd
でデーモン化するhoge
はnginx
からのリクエストをUNIX Socket
で受け取る
UNIX Socket
は/var/run/hoge/hoge.sock
とするやったこと
/var/run/hoge
ディレクトリを作成する
- パーミッションは
hoge:hoge
とするhoge
とnginx
の各種設定ファイルを配置してデーモンを起動する
- この時点で動いたことは確認できた
- サーバを再起動する
- 再びAPIを叩くと
nginx
がBad Gateway
のエラーを返した
- 調べてみると
/var/run/hoge/hoge.sock
がディレクトリごと無くなっていた原因
- CentOS7では
/var/run
配下がtmpfs
になっており、サーバを再起動すると/var/run
配下のファイルが消えてしまう# /var/run は /run へのシンボリックリンク $ ls -ld /var/run lrwxrwxrwx. 1 root root 6 Jul 25 2019 /var/run -> ../run # /run は tmpfs をマウントしている $ mount | grep /run tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)対処法
systemdのUnitファイルに
RuntimeDirectory
の設定を追加する
tmpfiles.d
のMANページによると原文System daemons frequently require private runtime directories below /run to store communication sockets and similar. For these, it is better to use RuntimeDirectory= in their unit files (see systemd.exec(5) for details), if the flexibility provided by tmpfiles.d is not required. The advantages are that the configuration required by the unit is centralized in one place, and that the lifetime of the directory is tied to the lifetime of the service itself. Similarly, StateDirectory=, CacheDirectory=, LogsDirectory=, and ConfigurationDirectory= should be used to create directories under /var/lib/, /var/cache/, /var/log/, and /etc/. tmpfiles.d should be used for files whose lifetime is independent of any service or requires more complicated configuration.日本語訳システムデーモンは、通信ソケットなどを格納するために、/runの下にプライベートランタイムディレクトリを必要とすることがよくあります。 これらについては、tmpfiles.dによって提供される柔軟性が必要ない場合は、ユニットファイルでRuntimeDirectory =を使用することをお勧めします(詳細については、systemd.exec(5)を参照)。 利点は、ユニットに必要な構成が1か所に集中化されていること、およびディレクトリの存続期間がサービス自体の存続期間に関連付けられていることです。 同様に、/var/lib/、/var/cache/、/var/log/、および/etc/の下にディレクトリを作成するには、StateDirectory=、CacheDirectory=、LogsDirectory=、およびConfigurationDirectory=を使用する必要があります。 tmpfiles.dは、存続期間がサービスに依存しないか、より複雑な構成が必要なファイルに使用する必要があります。とあるので、
RuntimeDirectory
の設定を追加します。また、今回はパーミッションを
0755
としたいので以下の様にRuntimeDirectoryMode
も設定します。UNITファイルに追加した行RuntimeDirectory=hoge RuntimeDirectoryMode=0755※
systemd.exec
のMANページによると/run
が起点となるため、フルパスではなく/run
配下に作りたいディレクトリ名を指定します参考リンク
- man - tmpfiles.d
- man - systemd.exec(5)
- Handling /var/run with systemd
- 投稿日:2020-07-31T09:44:05+09:00
GitとGitHubの関係性について
はじめに
Gitとは
ソースコードのバージョンを管理するツール
GitHubとは
Gitを利用した、開発者を支援するWebサービスGitとGitHubですが、関連性は強ものの別物であり、Gitを利用しているからと言ってGitHubを使用しなければならないというわけではありません。
後述しますが、GitのホスティングサービスはGitHub以外にも存在しております。Git誕生の歴史と利便性
そもそもGitはどのようにして誕生したのか。
その経緯から、Gitの利便性を確認していきましょう。Gitの生みの親はLinuxOSを作ったリーナス・トーバルズ氏です。
氏は、当初Linuxカーネル開発で「BitKeeper」というバージョン管理システムを用いておりました。
ライセンスの問題により「BitKeeper」使用することができなくなったため、代替するサービスを探したもののフリーのバージョン管理システムでは、氏の掲げる高度な要求水準を満たせるものはありませんでした。
そのためトーバルズ氏自ら開発に着手し、そこで誕生したものが「Git」になります。
ではこれまでのバージョン管理ツールと比べてGitは何に優れているのでしょうか。Gitが優れている点、それは分散型のリポジトリであることにあります。
従来リポジトリは全体で1つでしたが、Gitは「ローカル」と「リモート」の2つを持っています。
この分散型のメリットは、システム開発を複数で行った場合に、開発者それぞれがソースコードを書いていきリポジトリに追加していくことになるため、開発者が増えればその分だけリポジトリに不整合が生じる可能性が高まります。そういったリポジトリの不整合を防ぐために、各開発者が自身のマシンでローカルリポジトリに変更を記録していき、全体の状況を見てリモートリポジトリに変更を記録していくことで利便性が高まりました。
分散型という今までにない形でバージョン管理を行うことで、従来の管理ツールに対して感じていた懸念は払拭され、現在に至るまで開発に用いられるようになりました。
GitHubとは
Gitという言葉がついているので、専用サービスのような印象を受けますが、こういったGitのホスティングサービスとしては他にもあり、GitHubを必ず利用しなければならないというわけではありません。
GitHubは、クラウド上でGitを用いたバージョン管理をすることができ、Gitを更に使いやすくする機能が備わっております。
その中でも「フォーク」「プルリクエスト」「マージ」の3つの機能があることで、利便性が向上し、多くのユーザーから支持を得ています。
- フォーク:誰かのリポジトリを取得(コピー)して改変することができる。
- プルリクエスト:自身が行ったソースコードの変更点について他のメンバーにレビュー依頼ができる機能
- マージ:人のコードを自分のコードに導入すること。
「フォーク」してコードの改修を行い、オーナーへ「プルリクエスト」を行う。
「プルリクエスト」を受けたオーナーはそのコードを「マージ」する。
また、GitHubはソーシャルコーディングの場とも呼ばれており、他の人のソースコードを見ることができます。
これによって、開発への参加やフィードバックなどオープンソースでの開発がしやすくなったのもGitHubのメリットになります。GitHub以外に使用されている代表的なGitのホスティングサービス
各種選ばれる違いとしては、ホスティングがWebサービス型とインストール型で違うことや、対応するVCSの違い、無料のプライベートリポジトリ、料金形態と様々です。
まとめ
Gitとは分散型にする事で、開発効率をあげる目的を持ったバージョン管理ツールであり、
GitHubはそれをオープンソースとしてチーム開発の利便性向上や、技術者のコミュニティ形成に役立っているサービスである。参照記事
ITmedia エンタープライズ
https://www.itmedia.co.jp/enterprise/articles/0504/20/news075.html
FERROWS
https://job.fellow-s.co.jp/useful_info/feature_detail/Art-0488
Linix.com
https://www.linux.com/
- 投稿日:2020-07-31T01:27:24+09:00
Flutter in Docker - Dockerコンテナ内にFlutter開発環境を構築して利用する方法
1. はじめに
Flutterの開発環境をDockerコンテナ (今回はUbuntu 20.04 LTS) に構築し、macOSやLinux OSのHost PCからあたかもHost PC上で開発しているのと同じような環境を構築する方法を紹介します。この仕組みを利用すれば、リモート (サーバー) に開発環境を構築し、それにローカルPCからアクセスしてFlutterアプリの開発が可能です。
Flutter in Docker全体像
(補足) 今回はトライしていませんが、Dockerコンテナ内にAndroid版 (Aundroid Studioを利用したエミュレータ上での動作) も原理上は動作可能なはずです。
Dockerコンテナ化するメリット (例)
- 開発環境を複製・削除し易く、同じ環境を第三者に配ることが可能
- 環境をDockerコンテナ化しておくとCI/CD時に便利
- OSに依存せず (Linux or macOS) 、Android/iOS以外の環境での動作確認が可能
ターゲット (Host PC) 環境
- macOS
- Linux OS (Flutter, Dockerが動作する64bit Linux環境であれば基本的にどのディストリービューションでもOK)
2. Dockerインストール
Docker自体のインストール方法については割愛しますが、基本的に公式サイトの手順通りに進めれば大丈夫です。
- macOS: Install Docker Desktop on Mac
- Linux (Ubuntu): Install Docker Engine on Ubuntu
3. Dockerコンテナイメージの作成
Dockerコンテナイメージを作成する手順について説明します。Dockerコンテナ内のOS (rootfs) はUbuntu 20.04にしました。今回はDockerfileは利用せず、全て手動による手順での説明です。
Ubuntu 20.04 イメージ (rootfs) の取得
$ docker pull ubuntu:20.04Dockerコンテナの起動
以下のコマンドでDockerコンテナを起動してそのコンテナ中に入ります。基本的にセキュリティなし (
--privileged
) で、Host PCのOSと同じ権限でアクセス出来るようにします。なお、ここで指定したパラメータを後述のDocker-composeの設定ファイルでも利用するため、まずはこの設定のまま実行して下さい。
$ docker run -it --name flutter-docker ¥ --privileged -h flutter -u root -w /root ¥ --add-host=flutter:127.0.1.1 --net=host ubuntu:20.04問題がなければプロンプトが
#
に変わり、Dockerコンテナ内の操作に切り替わっています。例えば、uname
コマンドを打つとLinux OSになっていることが分かります。# root@flutter:~# uname -a Linux flutter 4.19.76-linuxkit #1 SMP Tue May 26 11:42:35 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux必要なツールのインストール
Dockerコンテナ内のUbuntu OSに必要なパッケージをインストールします。
xserver-xorg
のインストール時にはロケールやキーボードの情報を求められますが、適当で良いです (無難ならUS) 。# apt update # apt install git unzip clang xserver-xorg pkg-config libgtk-3-dev curl cmake ninja-buildChromeブラウザのインストール (必要があれば)
# apt install wget gnupg # sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' # wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - # apt update # apt-get install google-chrome-stable参考: https://qiita.com/pyon_kiti_jp/items/e6032eb6061a4774aece
Flutter SDKのインストール
Flutter SDKをgit cloneして、/opt以下に配置します。
# https://github.com/flutter/flutter.git # mv flutter /opt/コンテナイメージの保存
ここまででコンテナ内での作業は全て終了です。なので、コンテナから抜けます。
# exit作成したコンテナをDockerイメージファイルとして保存します。ここで指定したパラメータを後述のDocker-composeの設定ファイルでも利用するため、まずはこの設定のまま実行して下さい。
$ docker commit flutter-docker flutter-docker/ubuntu:latest4. Host PC側の設定 (macOSの場合のみ)
Dockerコンテナ内のGUIアプリケーションはX11プロトコルで動作するため、そのGUIアプリの画面をHost PC側のX11サーバーに転送する必要があります。macOSの場合、Host側のX11サーバーとしてXQuartzがありますので、それをインストールして利用します。
XQuartzのインストール
$ brew cask install xquartzHost PCを再起動します。再起動後、
DISPLAY
環境変数が以下のように設定されていることを確認します。$ echo $DISPLAY /private/tmp/com.apple.launchd.NagCeWDLYl/org.macosforge.xquartz:0DockerコンテナのX11クライアントからのアクセスを許可します。
$ xhost +$(hostname) $ xhost + local:rootコマンドラインもしくは、LaunchPadから
XQuartz
を立ち上げておきます。
5. Host PC側の設定 (Linux OSの場合のみ)
Linux OSの場合は大抵がX11デフォルトだと思いますので、以下の対応だけを行います。
$ xhost + local:root6. VSCode環境構築
VSCodeのインストールとVSCodeからDockerコンテナを利用するためのExtensions等をインストールします。
VSCodeのインストール
以下を参考にしてインストールしてください。
- Linux (Ubuntu): https://qiita.com/yoshiyasu1111/items/e21a77ed68b52cb5f7c8
- macOS: https://qiita.com/watamura/items/51c70fbb848e5f956fd6
VSCode Extensionsインストール
以下の3つのExtensionsをインストールします。
7. Docker Composeファイルの作成
VSCodeからDockerコンテナ内のFlutter SDKを利用するために、Docker Composeと先ほどインストールしたVSCode Extensionsの
Remote Development
の設定ファイルを作成します。作成したファイルは https://github.com/Kurun-pan/flutter-docker に置いているため、Host OS (Linux or macOS) に合わせて利用して下さい。$ mkdir flutter_docker $ cd flutter_dockerカレントディレクトリ (flutter_docker) 以下に
docker-compose.yml
ファイルと.devcontainer/devcontainer.json
ファイルの2つを作成します。
Host OSがmacOSの場合
DISPLAY
環境変数にhost.docker.internal:0
を設定するのがポイントのはずでしたが、上手く行かなかったため、{write your host name!!}
の部分はmacOSのhostnameを指定してください。。誰か正しい方法を知っていれば教えて下さい。https://github.com/Kurun-pan/flutter-docker/tree/master/macos
docker-compose.ymlversion: "3" services: flutter: image: flutter-docker/ubuntu:latest working_dir: /root/workspace command: sleep infinity environment: - HOME=/root - no_proxy=127.0.0.1,localhost #- DISPLAY="host.docker.internal:0" - DISPLAY={write your host name!!}:0 volumes: - ~/.gitconfig:/home/root/.gitconfig - ./:/root/workspace - ~/.Xauthority:/root/.Xauthority network_mode: "host" extra_hosts: - flutter:127.0.1.1.devcontainer/devcontainer.json{ "name": "Flutter docker", "dockerComposeFile": [ "../docker-compose.yml", ], "service": "flutter", "remoteUser": "root", "remoteEnv": { "QT_X11_NO_MITSHM": "1", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/flutter/bin", }, "settings": { "terminal.integrated.shell.linux": null }, "runArgs": [ "--privileged", "-P", ], "extensions": ["dart-code.flutter"], "workspaceMount": "source=${localWorkspaceFolder}/workspace,target=/root/workspace,type=bind,consistency=delegated", "workspaceFolder": "/root/workspace" }Host OSがLinuxの場合
Linux OSの場合、OpenGLでDRM (DRI) をDockerコンテナ内のFlutterアプリが利用できるように、
/dev/dri
をbind-mountします。https://github.com/Kurun-pan/flutter-docker/tree/master/linux
docker-compose.ymlversion: "3" services: flutter: image: flutter-docker/ubuntu:latest working_dir: /root/workspace command: sleep infinity environment: - HOME=/root - no_proxy=127.0.0.1,localhost volumes: - ~/.gitconfig:/home/root/.gitconfig - ./:/root/workspace - /tmp/.X11-unix:/tmp/.X11-unix devices: - /dev/dri:/dev/dri network_mode: "host" extra_hosts: - flutter:127.0.1.1Host OSの
DISPLAY
環境変数を引継ぎます。.devcontainer/devcontainer.json{ "name": "Flutter docker", "dockerComposeFile": [ "../docker-compose.yml", ], "service": "flutter", "remoteUser": "root", "remoteEnv": { "QT_X11_NO_MITSHM": "1", "DISPLAY": "${localEnv:DISPLAY}", "XAUTHORITY": "/tmp/.X11-unix", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/flutter/bin", }, "settings": { "terminal.integrated.shell.linux": null }, "runArgs": [ "--privileged", "-P", ], "extensions": ["dart-code.flutter"], "workspaceMount": "source=${localWorkspaceFolder}/workspace,target=/root/workspace,type=bind,consistency=delegated", "workspaceFolder": "/root/workspace" }8. Flutter in Dockerの実行
VSCode立ち上げ
docker-compose.yml
が存在するディレクトリでVSCodeを立ち上げます。$ code .VSCode Remote Containerのオープン
ウインドウ左下の
><
の部分をクリックもしくは、shift+alt+p
でコマンドパレットを開き、Remote-containers: Open Folder in Container...
を選択します。
VSCodeウインドウ下部にターミナルが開きます。このターミナル操作対象は作成したDockerコンテナイメージ (flutter-docker/ubuntu:latest) です。
Flutterサンプルアプリのプロジェクト作成
ここからVSCodeのターミナル (Dockerコンテナ) で以下のコマンドを実行し、Flutterサンプルアプリを実行します。
# flutter config --enable-linux-desktop # flutter config --enable-web # mkdir sample # cd sample # flutter create .Flutterサンプルアプリの実行
サンプルアプリ for Linux Desktop
# flutter run -d linuxコマンドを実行する以外には、VSCodeでdartソースコードを開いて、GUI操作でもアプリ実行やブレークポイントを利用したデバッグ等が可能です。
サンプルアプリ for Web
対応中なので少々お待ちを。。
# flutter run -d chrome
- 投稿日:2020-07-31T00:30:59+09:00
ブートローダーのインストールに失敗したときにディスクを消し飛ばす前に確認すること
はじめに
最近Manjaroをインストールしようとしたのですが、
Boost.Python error in job "bootloader". Command 'grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=Manjaro --force' returned non-zero exit status 1. Installing for x86_64-efi platform. Could not prepare Boot variable: No space left on deviceというエラーが出て失敗しました。
"No space left"から/boot/efiのためのパーティションが小さすぎるのかと考えディスクを全消去しやり直しても改善せず、更にはkubuntuのインストールも試して同様にブートローダーのインストールで失敗しました。
一応kubuntuのインストールは成功したので今回の問題の対処法を共有します。最初に確認すべきこと
※マニュアルにも書いてあることです
特に自分でパーティションを設定する場合の注意事項ですが、/boot/efiのためのパーティションはファイルシステムをFAT32に設定する必要があります。マウントポイントも/boot/efiを選択し、bootフラグを付与することも必要です。
パーティショニングを自動で行う場合などは自動的に上記の設定になると思うのでおそらくあまり気にする必要はありません。それでも冒頭のエラーメッセージが出る場合
参考 ArchWiki Unified Extensible Firmware Interface
まずはターミナルを起動し
ls /sys/firmware/efi/efivars/dump-*でdumpで始まるファイルの有無を調べます。自分の場合はこれが大量に存在し容量を圧迫していました。
"No space left"と言われていたのはこれのことだったようです。ディスクを全消去したところでこのフォルダの中身までは綺麗になりません。
(sudo) rmで削除することができるのでdumpで始まるファイルを削除します。
この後kubuntuのインストールを試したところ無事に完了しました。
(Manjaroは後日試します)おわりに
自分が件のエラーメッセージを検索にかけたところ、ヒットしたのは主にパーティションのファイルシステムやフラグ付与の話でした。
dumpファイルの存在にもっと早く気づいていればわざわざ全削除までしなくても良かったなあと思っているので同様の症状に悩む方の参考になれば幸いです。