HPCメモ

HPC(High Performance Computing)に関連したりしなかったりすることのメモ書き

AWS cloud9 メモ

これまで、自宅兼オフィスではMac mini、外出先はASUSのtransbook(surfaceっぽいwindows tablet)と2環境を使い分けてきました。

しかし、この構成だと外出先で電源とwifiを確保して、さー仕事するぞーと意気込んで git pull したのに mac側で作業した後で push してなくて何もできないという悲しい事態が稀によく起きます・・・orz

こういうミスが嫌だったので、一昔前はデスクトップマシンは使わず全ての作業をノートPCでやってたんですが、 最近はiPadやらラズパイやらと使う端末が増えることはあっても1台にまとめるのは到底無理な感じです。

というわけで、複数端末間の開発環境の統一のためにAWS Cloud9を導入してみました。

aws.amazon.com

網羅的な解説資料は既に色々なところにあるので、私が調べたり試したものをいくつかトピック毎にまとめておきます。

セットアップ方法

EC2を使う環境の場合は、ドキュメントの通りに作業すればほとんどひっかかるところは無いと思います(そもそも選択するオプションがほとんど無い)

唯一気をつけておく必要があるのは最初に入力する "Name" で、これがIDE起動後に表示されるファイルツリーのrootの名前になるのであまり長い名前をつけてると見難くなりますw f:id:n_so5:20190401140358p:plain

何が使えるのか?

こちらにインストール済のパッケージの一覧があります。

docs.aws.amazon.com

  • Amazon Linux AMI ウェブサイトの「Amazon Linux AMI 2018.03 パッケージ」にリストされているパッケージ。

なんて書かれてますが、こちらのパッケージリストには、

  • gcc-4.8.5
  • gcc44-4.4.6
  • gcc48-4.8.5
  • gcc64-6.4.1
  • gcc72-7.2.1

と色々書かれてて、イマイチよくわかりません。とりあえずログインして、調べてみましょう。

[ec2-user@ip-10-0-0-248 environment]$ gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[ec2-user@ip-10-0-0-248 environment]$ which gcc
/usr/bin/gcc
[ec2-user@ip-10-0-0-248 environment]$ ls -l `which gcc`
lrwxrwxrwx 1 root root 21 Feb 18 10:29 /usr/bin/gcc -> /etc/alternatives/gcc

おお、alternativesだ・・・どうやって使うんだっけ。*1

ぐぐりながら調べてみたところ、どうやらgccは4.8.5しか入っていないようです。

[ec2-user@ip-10-0-0-248 environment]$ alternatives --display gcc
gcc - status is auto.
 link currently points to /usr/bin/gcc48
/usr/bin/gcc48 - priority 482
 slave cc: /usr/bin/gcc48
 slave c89: /usr/bin/gcc48-c89
 slave c99: /usr/bin/gcc48-c99
 slave gcov: /usr/bin/gcov48
 slave gcc.1: /usr/share/man/man1/gcc48.1.gz
 slave gcov.1: /usr/share/man/man1/gcov48.1.gz
Current `best' version is /usr/bin/gcc48.
[ec2-user@ip-10-0-0-248 environment]$ alternatives --config gcc

There is 1 program that provides 'gcc'.

  Selection    Command
-----------------------------------------------
*+ 1           /usr/bin/gcc48

Enter to keep the current selection[+], or type selection number: 
failed to create /var/lib/alternatives/gcc.new: Permission denied

しかも、よくみたらgfortranが入っていません。AWSの人はFortran死すべし派だったのか?

yum install一発で4.8.5がインストールされるので必要になったらインストールしましょうか。

[ec2-user@ip-10-0-0-248 environment]$ sudo yum install -y gcc-gfortran
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main                                                                                                                                          | 2.1 kB  00:00:00     
amzn-updates                                                                                                                                       | 2.5 kB  00:00:00     
epel/x86_64/metalink                                                                                                                               | 6.7 kB  00:00:00     
epel                                                                                                                                               | 4.7 kB  00:00:00     
1060 packages excluded due to repository priority protections
Resolving Dependencies
--> Running transaction check
---> Package gcc-gfortran.noarch 0:4.8.5-1.22.amzn1 will be installed
--> Processing Dependency: gcc48-gfortran >= 4.8.5 for package: gcc-gfortran-4.8.5-1.22.amzn1.noarch
--> Running transaction check
---> Package gcc48-gfortran.x86_64 0:4.8.5-28.142.amzn1 will be installed
--> Processing Dependency: libgfortran.so.3()(64bit) for package: gcc48-gfortran-4.8.5-28.142.amzn1.x86_64
--> Running transaction check
---> Package libgfortran.x86_64 0:6.4.1-1.45.amzn1 will be installed
amzn-main/latest/filelists_db                                                                                                                      | 5.7 MB  00:00:01     
amzn-updates/latest/filelists_db                                                                                                                   | 7.3 MB  00:00:00     
epel/x86_64/filelists_db                                                                                                                           | 7.9 MB  00:00:00     
--> Processing Dependency: libquadmath.so.0(QUADMATH_1.0)(64bit) for package: libgfortran-6.4.1-1.45.amzn1.x86_64
--> Processing Dependency: /usr/lib64/libquadmath.so.0.0.0 for package: libgfortran-6.4.1-1.45.amzn1.x86_64
--> Processing Dependency: libquadmath.so.0()(64bit) for package: libgfortran-6.4.1-1.45.amzn1.x86_64
--> Running transaction check
---> Package libquadmath.x86_64 0:6.4.1-1.45.amzn1 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==========================================================================================================================================================================
 Package                                   Arch                              Version                                        Repository                               Size
==========================================================================================================================================================================
Installing:
 gcc-gfortran                              noarch                            4.8.5-1.22.amzn1                               amzn-main                               3.8 k
Installing for dependencies:
 gcc48-gfortran                            x86_64                            4.8.5-28.142.amzn1                             amzn-updates                            8.0 M
 libgfortran                               x86_64                            6.4.1-1.45.amzn1                               amzn-main                               391 k
 libquadmath                               x86_64                            6.4.1-1.45.amzn1                               amzn-main                               197 k

Transaction Summary
==========================================================================================================================================================================
Install  1 Package (+3 Dependent packages)

Total download size: 8.5 M
Installed size: 20 M
Downloading packages:
(1/4): gcc-gfortran-4.8.5-1.22.amzn1.noarch.rpm                                                                                                    | 3.8 kB  00:00:00     
(2/4): libgfortran-6.4.1-1.45.amzn1.x86_64.rpm                                                                                                     | 391 kB  00:00:01     
(3/4): libquadmath-6.4.1-1.45.amzn1.x86_64.rpm                                                                                                     | 197 kB  00:00:00     
(4/4): gcc48-gfortran-4.8.5-28.142.amzn1.x86_64.rpm                                                                                                | 8.0 MB  00:00:02     
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Total                                                                                                                                     3.3 MB/s | 8.5 MB  00:00:02     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : libquadmath-6.4.1-1.45.amzn1.x86_64                                                                                                                    1/4 
  Installing : libgfortran-6.4.1-1.45.amzn1.x86_64                                                                                                                    2/4 
  Installing : gcc48-gfortran-4.8.5-28.142.amzn1.x86_64                                                                                                               3/4 
  Installing : gcc-gfortran-4.8.5-1.22.amzn1.noarch                                                                                                                   4/4 
  Verifying  : gcc-gfortran-4.8.5-1.22.amzn1.noarch                                                                                                                   1/4 
  Verifying  : libgfortran-6.4.1-1.45.amzn1.x86_64                                                                                                                    2/4 
  Verifying  : gcc48-gfortran-4.8.5-28.142.amzn1.x86_64                                                                                                               3/4 
  Verifying  : libquadmath-6.4.1-1.45.amzn1.x86_64                                                                                                                    4/4 

Installed:
  gcc-gfortran.noarch 0:4.8.5-1.22.amzn1                                                                                                                                  

Dependency Installed:
  gcc48-gfortran.x86_64 0:4.8.5-28.142.amzn1                 libgfortran.x86_64 0:6.4.1-1.45.amzn1                 libquadmath.x86_64 0:6.4.1-1.45.amzn1                

Complete!
[ec2-user@ip-10-0-0-248 environment]$ gfortran --version
GNU Fortran (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28)
Copyright (C) 2015 Free Software Foundation, Inc.

GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING

しかし相変わらず、alternativeの方にはfortranは出力されない。

[ec2-user@ip-10-0-0-248 environment]$ alternatives --display gcc
gcc - status is auto.
 link currently points to /usr/bin/gcc48
/usr/bin/gcc48 - priority 482
 slave cc: /usr/bin/gcc48
 slave c89: /usr/bin/gcc48-c89
 slave c99: /usr/bin/gcc48-c99
 slave gcov: /usr/bin/gcov48
 slave gcc.1: /usr/share/man/man1/gcc48.1.gz
 slave gcov.1: /usr/share/man/man1/gcov48.1.gz
Current `best' version is /usr/bin/gcc48.
[ec2-user@ip-10-0-0-248 environment]$ alternatives --display gfortran
gfortran - status is auto.
 link currently points to /usr/bin/gfortran48
/usr/bin/gfortran48 - priority 482
 slave f95: /usr/bin/gfortran48
 slave gfortran.1: /usr/share/man/man1/gfortran48.1.gz
Current `best' version is /usr/bin/gfortran48.

これは、別バージョンのgccを入れた時にgccだけバージョンを変えて、gfortranを変え忘れるとはまるパターンですね・・・

nodeもv6.14.3とかいう挑戦的なバージョンですが、こっちはnvmが入っているのでltsの最新あたりまで上げときましょう。

[ec2-user@ip-10-0-0-248 WHEEL]$ nvm install lts/*
v10.15.3 is already installed.
Now using node v10.15.3 (npm v6.4.1)

で、この辺の初期化処理を自動化しようと思って色々と調べていたのですが、どうやらそういう仕組みは用意されていないようです。 こちらに初期化スクリプトというのがあって、これを使ってねってことかと思ったんですが、なぜかJavascriptです。

docs.aws.amazon.com

数時間ぐぐった結果こちらの記事で使われている例くらいしか見つけられなかったのですが、 これはひょっとするとcloud9独自の初期化処理用プラグイン的なものなんでしょうかね?

qiita.com

AWSのドキュメントによると

現時点では、IDE での初期化スクリプトへのコードの追加は実験的な機能であり、完全にはサポートされていません。初期化スクリプトにコードを追加するときは、ご自分の判断で行ってください。AWS Cloud9 には、この機能をいつでも変更する権利があります。

とのことなので、そのうちもっと分かりやすものが作られるのに期待しておきましょう。 *2

当面はパッケージの追加インストールくらいしかしないので、シェルスクリプトでも作ってgistあたりに置いておく運用が楽そうです。 *3

hibernate設定

環境作成時のウィザードで"Cost-saving setting"という内容で書かれているのですが、 inactive になってから、設定した時間が経過したらEC2のインスタンスを落としてくれるという設定があります。

ちょくちょくブラウザを開きっぱなしにして外出してしまう私としては、 大変ありがたい機能なんですが、どういう条件で inactive と判定してるのかよく分からなかったのでちょっと実験してみました。

実験方法

inactiveになって30分後にhibernateする設定(デフォルト設定)で、次の3パターンで放置し30分以上経過してから止まってたかどうかを確認します。 なお、ブラウザウィンドウは全て表示したままにしています。

  1. IDEを起動しているがterminal、ファイルともに開いていない状態
  2. IDEを起動してファイルを開いた状態
  3. IDEを起動してterminalを開きプロンプトが表示された状態
  4. IDEを起動してterminalを開き定期的に表示が更新されるコマンド(top)を実行した状態
  5. 何も起動せずに preview windowを押して8080ポートにアクセスしたままの状態
  6. immediate windowでwhile(true) console.log("hoge")しておいた場合

stopした時刻は、Cloud Trailには出てこないので(たぶんOS側でシャットダウンしてる)一晩放置してから、IDEのterminal経由で/var/log/messagesをチェックしてみました。

実験結果

全パターンシャットダウンされませんでした。

その後、ブラウザウィンドウを閉じて30分程度経過したところで、EC2コンソールをリロードしながら眺めていたらstopping->stopと遷移していったので、どうやらブラウザが開いてるとIDE上で何もしていなくてもactiveと判定されるようです。*4

というわけで、EC2側の実行状態には関係なくて、ブラウザとの接続が失われるとinactive状態と判定されるようです。

ここまで調べてから、ふとドキュメントを見ていたらしっかりとブラウザからの接続が全部無くなってからの時間ですよって書かれてました。 無駄にインスタンスを立ちあげてしまった・・・ orz

docs.aws.amazon.com

[Cost-saving setting (コスト削減のセットアップ)] で、environment の IDE に接続されているすべてのウェブブラウザインスタンスが閉じられてから、AWS Cloud9 で environment の Amazon EC2 インスタンスがシャットダウンされるまでの時間を選択します。または、デフォルトの選択のままにします。

PCをスリープにするか、ネットワーク接続が切れればinactiveとして扱ってもらえそうなので、たいていの場合は大丈夫そうですが、モバイルルータやテザリングでノートPCを使ってる人とかCellular版のiPadを使っている人は要注意ですね。

複数プロジェクト対応

1つのEnvironmentに複数のプロジェクト(というかgit repository)を配置することができますが、各種設定時に1つ注意が必要になります。

cloud9から立ち上げられたEC2インスタンスは$HOME直下に "environment"というディレクトリが作成されていて、ここがIDEのファイルブラウザ画面のrootになります。したがって、この下にディレクトリを掘ってgitリポジトリを複数作る(またはgit cloneしてくる)ことで複数プロジェクトを1つのEnvironmentに配置することができるのですが、ビルダーやランナー、あとコードフォーマッターなんかの起動時は、"$HOME/environment"がcurrentディレクトリになります。

code formatterにeslintを設定したのに動かなくって、AWS Developer Forumsで教えてもらいながら調べてたのですが、ローカルインストールされたコマンドを叩く場合は、次のように$fileの存在するディレクトリまで移動してからnpxを叩く必要があります。

cd `dirname $file`;npx eslint --fix `basename $file`

ビルダーやランナーの設定にnpmを使う場合も同様で、プロジェクトのディレクトリの下へ移動してからコマンドを実行する必要があります。 こちらは設定ファイルに "working_dir": "$file_path" という項目を追加しておけば、大丈夫です*5

ランナーの設定

デフォルトのランナーは大変お粗末な感じで、例えばC++ランナーだと次のような設定になっています。分割コンパイルはしない前提なのか、$fileをコンパイルして生成された実行ファイルを呼び出すだけのものです・・・

{
  "script": [
    "set -e",
    "if [ \"$debug\" == true ]; then ",
    "    g++ -ggdb3 -std=c++11 $file -o $file.o",
    "    chmod 755 \"$file.o\"",
    "    node $HOME/.c9/bin/c9gdbshim.js \"$file.o\" $args",
    "else",
    "    g++ -std=c++11 $file -o $file.o",
    "    chmod 755 $file.o",
    "    $file.o $args",
    "fi"
  ],
  "info": "Running $file",
  "debugger": "gdb",
  "$debugDefaultState": false,
  "selector": "^.*\\.(cpp|cc)$",
  "trackId": "Cplusplus"
}

プロジェクト全体でcmakeを使っているのであればcmake&&make&&make testみたいな感じで書き直しておきましょう。 あと、clean buildの設定も必要ですね。そもそもプロジェクト毎にcmakeを使うのかGNU auto toolsなのかはたまたmakefile直書きなのかと違うからこれに対応して・・・と考えると破綻しそうなので、私はこの設定を作り込むのは諦めました。

単にterminalを開いてビルドすれば良いだけなので・・・

起動中のインスタンスの確認

画面の右上にcloud9のアイコンがありますが、その隣のボタン(たぶんAWSのユーザ名の頭文字)をクリックするとドロップダウンリストが現れて、cloud9のダッシュボードと、EC2コンソールへのリンクが表示されます。また、cloud9のアイコンはdashboardへのリンクになっています。

f:id:n_so5:20190401141028p:plain

*1:スパコン関連はmodule使ってるとこが多いもんでこいつほとんど使ったこと無いんです

*2:そもそもドキュメントが不足してて何を書けば動くのやらさっぱり分かりませんorz

*3:私の場合はもとももドットファイルgithubで管理してたので、そこにシェルスクリプトを追加しました。

*4:1のケースだけ実験すれば十分だった・・・

*5:code formatterの設定では$fileは使えるけど$file_pathは使えないので一手間かけないといけないのです・・・