- 投稿日:2020-01-18T22:42:28+09:00
Goclipse "could not start goclipse because java version is 0"
はじめに
Goclipseの設定でハマったので記録を残しておきます。
動作確認環境
OS:
macOS Mojave Version 10.14.6 (18G84)STS:
Spring Tool Suite 4
Version: 4.5.0.RELEASE
Build Id: 2019121710521. 余計なファイルを削除
https://github.com/GoClipse/goclipse/issues/256
にWorkaroundが記載されていたので、やってみた所、プラグインが起動するようになりました。Note that the error message is not true, Goclipse does start successfully despite what the message says, so you can just keep using it. As a workaround, locate the plugins directory in the Eclipse installation, and delete the com.googlecode.goclipse.jvmcheck_1.0.0.v201607061938.jar file, this will prevent the error message from being shown.
STSを使っていたので、以下のPATHにありました。
/Applications/SpringToolSuite4.app/Contents/Eclipse/plugins/com.googlecode.goclipse.jvmcheck_1.0.0.v201607061938.jarでも、使用感がイマイチだったので結局Goclipse自体を使うのは断念しました。。。
- 投稿日:2020-01-18T18:03:04+09:00
golangの並行処理のための言語要素に対応するCSPの記述を理解して形式検証の実践を開始しよう(検証編:クリティカルセクション)
はじめに
単純ですが具体的な例を示したいと思います。今回題材とするのは、「クリティカルセクション問題」です。これは並行処理のプログラムが資源を共有したりする場合に出くわす問題です。
今回、検証に使うツールはモデル検査ツールPAT(Process Analysis Toolkit)とします。利用の際にところどころツールの画面などができますが、ツールそのものの使い方の詳細は省かせていただきます。もちろん、同等の機能を持つ別なツールを使っても同様の検証が可能です。
クリティカルセクション問題
この問題は並行動作する2つのスレッドに対して、以下の要求が満たされているアルゴリズムを構成することです。
- 要求1 : 排他制御。あるスレッドがクリティカルセクションを実行中は他のスレッドのクリティカルセクションを実行する事はできない。
- 要求2 : あるスレッドがクリティカルセクション以外の処理を実行している場合には他のスレッドはいつでもそのクリティカルセクションを実行できる。
この2つの要求を満たすアルゴリズムはすでにいくつか知られているものがあります(Dekker's Algorithmなど)。しかし、本記事では、そのような完成したプログラムではなく、道半ばで上記の要求を満たしていないGo言語のプログラムを示し、それを形式言語であるCSPで記述し、検証する方法を説明します。
なお、今回の検証は要求1に絞って説明する事にします。
コード例: 要求1がNG - 同時に2つのThreadのクリティカルセクションが動作可能になってしまう
go言語での記述
各スレッドの定義(コード片)を載せます。
var Thread0inside int = 0; var Thread1inside int = 0; func ThreadZero() { for { for Thread1inside == 1 {} Thread0inside = 1; CriticalSectionZero() Thread0inside = 0; OtherStuffZero(); } } func ThreadOne() { for { for Thread0inside == 1 {} Thread1inside = 1; CriticalSectionOne() Thread1inside = 0; OtherStuffOne(); } }それぞれのスレッドは、まず、相手のスレッドがクリティカルセクションに入っているかどうかを確認します。入っていないないならクリティカルセクションに入りますが入っている間はそこにとどまります(ロック)。クリティカルセクションに入っているかどうかはそれぞれのスレッドが持つフラグの値を確認します。
と、一見、特に問題はなさそうですが・・動かして確認したい人のために
また、当然ながらここに示したコード片だけでは、実行して確認する事はできません。このプログラムを確認するには以下の追加コードが必要になります:
- 各スレッドの「無限ループ」を有限にする
定義されていない関数を定義する
- CriticalSectionZero(),CriticalSectionOne(),OtherStuffZero(),OtherStuffOne()はここを実行している事わかるような表示を行うようなものにする(fmt.Printfを使うなど)。
main関数を作る
- mainの中でThreadZero()とThreadOne()をgo routineとして起動
- 2つのThreadが終了するのに十分なWaitを行う(time.Sleepなどを利用)
goのコード(参考程度にどうぞ)
https://gist.github.com/fujim2/dc3625b8f20fc5eb40c3fb91e3d15356
critical_bad.go の各スレッドのsleepをコメントアウトすると2つのスレッドのクリティカルセクションが重なって実行されるのが観測できます。CSPでの記述と検証
上記プログラムをCSPで記述してみます。
var Thread0inside = 0; var Thread1inside = 0; ThreadZero() = [!(Thread1inside == 1)] T0Start ->CriticalSectionZero{Thread0inside = 1} ->T0End{Thread0inside = 0} ->OtherStuffZero ->ThreadZero(); ThreadOne() = [!(Thread0inside == 1)] T1Start ->CriticalSectionOne{Thread1inside = 1} ->T1End{Thread1inside = 0} ->OtherStuffOne ->ThreadOne(); System = ThreadZero() || ThreadOne();プログラミング言語に対応するCSPでの表現にはいくつかバリエーションがあるのですが、今回はできるだけコードと対応が付くようなものにしてみました。
状態の遷移空間を確認してみる
多くの「モデル検査ツール」は、「検査」の機能だけでなく、シミュレーションの機能を持っている事が多いです。ここでは、PATのシミュレーション機能を使って、このプログラムの振る舞いの空間を可視化してみます。
なかなか複雑ですね。この中のどこかに問題(要件を満たさない状況)があったとしても、なかなか見つけるのは大変かもしれません。
検証
さて、モデル検査ツールの本領を発揮してもらいましょう。以下の様なPATの検証式を使って検証します。今回は、モデル検査でよく使われる「時相論理式(temporal logic)」を使った検証は行わず、ツールの方ですでに用意されているものを使います。
検証式
以下の様な検証式を使って検証したいと思います。
#assert System deadlockfree; #define badstatus (Thread0inside==1 && Thread1inside == 1); #assert System reaches badstatus;1行目はそもそも、Systemがデッドロックしないという検証式です。
2行目は2つのスレッドが同時にクリティカルセクションに入っているという「bad status」の定義です
3行目はSystemがこのbadstatusという状態に到達する可能性がある、という検証式です。2つの検証式はの結果を確認してみます。PATでは、検証のための画面で検証式を選択し、「verify」というボタンを押すことで検証が開始し、結果はコンソールに表示されます。結果、
- 1つ目の検証式はVALIDでした。つまり「デッドロックしない」事が検証できました。
- 2つ目の検証式もVALIDでした。つまり、badstatusになるという事ですから問題がある、という指摘です。
2つ目の検証式は「到達可能性(reachability)」を検査したのですが、ツールは、検査結果を確認した後に、「Simulate Witness Trace」というボタンを押すことで、シミュレーション機能と連動して、パスを表示してくれます(検証の機能とシミュレーションの機能が連動しています)。
左側の表示エリアにはステップ毎の変数の値などが表示されていますが、Thread1insideとThread0insideの値がともに1になっている事(クリティカルセクションが同時に実行されている)がわかります。
CSPのコード(参考程度にどうぞ)
https://gist.github.com/fujim2/26afdf75cb84b01b144ac031546f1943
なお、このプログラムの問題が、これだけかどうかはこの時点ではわかりません。
さいごに
ここで示したプログラムコードは非常に小さいものですが、それでも、思ったようにはつくれない、それが「並行・並列」プログラミングの難しさです。そして、その原因の多くは並行に動作するために起こる動作タイミングの非決定性、そしれそれに関係して肥大している振る舞い空間にあると思います。このおかげで、往々にしてプログラムは直観に反する振る舞いの経路をたどって、思いもよらない不具合を引き起こします。
なお、本記事の題材は、「並列コンピューティング技法 - 実践マルチコア/マルチスレッドプログラミング(Clay Breshears著)」訳本の第3章「正当性の検証と性能測定」の例を参考にしました(コード・文書ともにコピペなどはしておりません)。
今回は以上です。では。
- 投稿日:2020-01-18T16:54:06+09:00
VSCodeでGo Toolsにビルドタグを渡す方法
背景
VSCodeのGo拡張を使用している際、異なるビルドタグを持ったファイルにある変数や関数等を参照しようとするとコード補完が上手く働かずundeclaredになってしまいます。これはLanguage Serverであるgopls1がタグ無しの状態で参照しているため起こる事象なのでタグを渡してあげる必要があります。
lib_util.go// +build test package lib var ( testUtil = "test util" )lib.gopackage lib import ( "fmt" ) func p() { fmt.Println(testUtil) // undeclared name: testUtil }対処法
settings.json
に以下のような形で追記してやることでgoplsを含む各種Go Toolsにビルドタグを渡せます。プロジェクト毎に変更したい場合はWorkspaceレベルで設定してやると良いでしょう2。適用後はVSCodeを再起動するかF1メニューから "Developer: Reload Window" する必要があります(私の環境では "Go: Restart Language Server" だと上手くいきませんでした)。
"go.toolsEnvVars": { "GOFLAGS": "-tags=test" },参考文献
- 投稿日:2020-01-18T09:05:51+09:00
IntellijでGolangやるときの設定Tips
Gakuです。
Intellijで新規Golang PJを作成した際、いつも忘れるので、自分用の備忘録として残しておきます。go rootの設定(必須)
Preference > Language & Frameworks > Go > GOROOT
go modを有効にする
pj rootフォルダで
gakumbp:ddd-golang gaku$ go mod init go: creating new go.mod: module github.com/gaku3601/ddd-golang上記を実行し、go.modを作成する。
Go Modulesの設定をしていないと、実行は可能だがコードがエラーの状態になってしまう。
Preference > Language & Frameworks > Go > Go Modules(vgo)
で以下のように設定する。
これで、コードのエラーがなくなる。
自動fmt、自動imports
Preferences > Tools > File Watchers
の+でgo fmt・goimortsを選択
これで自動フォーマット、自動importが効くようになる
linter
Preferences > Tools > File Watchers
でgolangci-lintを選択
go.modをpj root以外に設定している場合、Working directoryをgo.modが配置している場所と同じところを指定する。
lintが効くようになる。
- 投稿日:2020-01-18T07:38:50+09:00
スクリプト言語の比較しながらGoのお勉強 〜 環境構築編(MacOS)
ごあいさつ
はじめまして。@kuroseetsと申します。
2000年からフリーランスで仕事を始め開発12年、インフラ8年経験してきたオッサンです。
皆さんはどのプログラミング言語、スクリプト言語が好きですか?または仕事などで何をよく使っていますか?
開発をされている方だとJavaが多いのかな?またはC#?Ruby?PHP?
事務系でスクリプトを組む方などはVBScriptなども現役ですよね。
私は現在インフラ運用構築側にいますので、私を含めて周辺でよく使われているのが、Python, Ruby, Perl, Bash辺りが多く、最近ではさらにGolangが増えてきている印象です。(あくまで個人的主観で、ですよ
それぞれ好みはあるとは思いますが、環境や現場による制約で使えるもの使えないものがありまして、私もその都度現場でキャッチアップしてスキルを身に付けてきました。
現在ではInfrastructure as Code
と謳われるだけあって、構成管理の設定ファイル以外でも手を動かすことも増えてきたと身を以て感じています。
今回個人的にGolangを勉強しようと思っているのですが、折角なので勉強ついでに有名なスクリプト言語を比較してみようかなと思います。
対象はGolangの他、Python, Ruby, Perl, Bash(インフラ運用4強スクリプト!)を予定しています。
環境構築
使うからには最新版を使いたい!
ということで常に最新版をインストールしやすく、また管理しやすくするためにバージョン管理ツール越しにインタプリタをインストールすることにしました。anyenvのインストール
@rinpa さんの https://qiita.com/rinpa/items/81766cd6a7b23dea9f3c を参考にしてインストールしました。
各スクリプト言語を使用するのにenv系コマンドは非常に便利なのですが、個別にインストールすると面倒です。
が、anyenvで一元管理できたら非常に便利ですね。# anyenvインストール brew install anyenv # anyenvが実行できるか確認 anyenv --version # 初期ディレクトリがないので初期化して作成 anyenv install --init # インストールできるenv系コマンドの確認 anyenv install -l # 各envをインストール anyenv install goenv anyenv install pyenv anyenv install rbenv anyenv install plenv # 環境変数の設定 echo 'eval "$(anyenv init -)"' >> ~/.bash_profile source ~/.bash_profilegolang
golangの最新版のインストールはgoenvに従って粛々と進めていきます。
# インストール可能なgoのバージョンを確認 goenv install -l # 最新版をインストール(執筆時は1.13.6) goenv install 1.13.6 # インストールしたバージョンを指定 goenv global 1.13.6 # 指定したバージョンが実行できているか確認 go --versionpython
pythonも同様に最新版をインストールします。
# インストール可能なpythonのバージョンを確認 pyenv install -l # 最新版をインストール(執筆時は3.8.1) pyenv install 3.8.1 # インストールした最新版バージョンを指定 pyenv global 3.8.1 # 指定したバージョンが実行できているか確認 python --versionruby
rubyも同じ手順です。
# インストール可能なrubyのバージョンを確認 rbenv install -l # 最新版をインストール(執筆時は2.7.0) rbenv install 2.7.0 # インストールした最新版バージョンを指定 rbenv global 2.7.0 # 指定したバージョンが実行できているか確認 ruby --versionperl
そしてperlも。
# インストール可能なrubyのバージョンを確認 plenv install -l # stableの最新版をインストール(執筆時は5.30.1) plenv install 5.30.1 # インストールした最新版バージョンを指定 plenv global 5.30.1 # 指定したバージョンが実行できているか確認 perl --versionbash
anyenvにはbashのバージョンを管理するツールがありませんので、下記のツールを利用させて頂きました。
https://i-beam.org/2015/12/25/211817/サイトを参考にインストールしてみましたがエラーが出ました
git clone https://github.com/ueokande/bashvm ~/.bashvm echo 'source $HOME/.bashvm/bin/bashvm-init' >> ~/.bashrc source ~/.bashrc readlink: illegal option -- f usage: readlink [-n] [file ...]BSD系のMacは
readlink
に-f
オプションがないみたいですね
こちらを参考にreadlink -f
するコマンドを作成
https://stackoverflow.com/questions/1055671/how-can-i-get-the-behavior-of-gnus-readlink-f-on-a-maccat << 'EOF' > /usr/local/bin/readlinkf #!/bin/sh TARGET_FILE=$1 cd `dirname $TARGET_FILE` TARGET_FILE=`basename $TARGET_FILE` # Iterate down a (possible) chain of symlinks while [ -L "$TARGET_FILE" ] do TARGET_FILE=`readlink $TARGET_FILE` cd `dirname $TARGET_FILE` TARGET_FILE=`basename $TARGET_FILE` done # Compute the canonicalized name by finding the physical path # for the directory we're in and appending the target file. PHYS_DIR=`pwd -P` RESULT=$PHYS_DIR/$TARGET_FILE echo $RESULT EOF chmod 755 /usr/local/bin/readlinkf
readlink -f
しているところをこのコマンドに置き換えます--- bashvm-init.bak 2020-01-18 07:08:43.000000000 +0900 +++ bashvm-init 2020-01-18 07:09:30.000000000 +0900 @@ -124,7 +124,7 @@ export -f bashvm export BASHVM_HOME=${BASHVM_HOME:-$HOME/.bashvm} -PATH="$(readlink -f $(dirname $BASH_SOURCE)):$PATH" +PATH="$(readlinkf $(dirname $BASH_SOURCE)):$PATH" test -f $BASHVM_HOME/config && source $BASHVM_HOME/config export bashvm_default_version=${bashvm_default_version:-system}改めて
source ~/.bashrc
を実行すると成功しました
ではbashの最新版をインストールします# 執筆次の最新は5.0 bashvm install 5.0 # インストールした最新版バージョンを指定 bashvm use 5.0 # 指定したバージョンが実行できているか確認 bash --version
以上で構築作業は完了です。
次回から各言語を比較しながらプログラミングしていきます。
- 投稿日:2020-01-18T00:27:34+09:00
インフラ構築あるあるをGoで解決する!
Goにはまってるインフラエンジニアです。
インフラ構築あるある
をGoで解決したいと思ってます。背景
その昔のワタシと後輩の電話
※後輩は現地のマシンルーム、ワタシは事務所にいました。後輩:コマンド間違えました!よくわからんコトになってます!
ワタシ:よくわからんって何や!ログ見て!
後輩:マシンルーム圏外やから外から電話してます!ログ見れないっす!
ワタシ:とりあえずSSHでログ見るか...
ワタシ:何やったのかさっぱりわからぬ\(^o^)/
ワタシ:現地行くか....ってことがよくありましたね。こういうときのミスない遠隔HELPって何かできないかな〜と思って、
chatサーバ作るぜ!って思いました。巷にはwebsocketを使ったchatはあったのですが、↑みたいな場面ってSSHしかできないようなケースあるんで、
普通のsocketで作りました。あまり先行事例がなくて、結構ムズかったです。ゴルーチンとチャネルが難しい....感想
slackすげーなって本当に思いました。
作り終わったあと、プログラミング言語Go読んだら、8章にチャットサーバあった.....
chatでテスト難しくね?それともワタシのアーキテクチャがダメなのか? ← このへん改善やな....工夫したとこ
- ターミナルからSSHでつなぐので、ルームでトークを分ける機能とかいらね!ってことでルームは公開ルーム1つだけっす!
- 過去のトークはgrep検索したいやん!ってことでテキストファイルでトークを残すことにしました!
https://github.com/kuritayu/infra-tools/blob/master/cmd/tchat/main.go
go get github.com/kuritayu/infra-tools
でも取れますとりあえず使い方。
- 作業サーバにSSHでログイン
tchat &
でサーバを起動(-pでポートを指定できる)- 別ターミナルからSSHでログイン
tchat -c
でサーバに接続- 名前を聞かれるので適当に入れる
- メッセージ入れると接続している人全員に配信する
NAME: tchat - chat tool by terminal USAGE: tchat [global options] command [command options] [arguments...] VERSION: 1.0 COMMANDS: help, h Shows a list of commands or help for one command GLOBAL OPTIONS: -c (default: false) -p value (default: 7777) --help, -h show help (default: false) --version, -v print the version (default: false)