ということで流れに乗ってみました。
毎週火曜日のペアプロ講習用に作成した問題を昨晩の #Perl入学式 オンラインミーティングで紹介したので Twitter でも紹介。情勢が収束したらまた懇親会でピザを食べつつお題に興じたい。 pic.twitter.com/n68luVPNEg
— OGATA Tetsuji (@xtetsuji) 2020年7月26日
アルゴリズムそんな自信ないのでどうなんだろう.....。競プロerからなんか突っ込まれそう
ということで流れに乗ってみました。
毎週火曜日のペアプロ講習用に作成した問題を昨晩の #Perl入学式 オンラインミーティングで紹介したので Twitter でも紹介。情勢が収束したらまた懇親会でピザを食べつつお題に興じたい。 pic.twitter.com/n68luVPNEg
— OGATA Tetsuji (@xtetsuji) 2020年7月26日
アルゴリズムそんな自信ないのでどうなんだろう.....。競プロerからなんか突っ込まれそう
最近YouTubeでPIENのプレイ動画をよく見るので作りました
pien
の後に渡したプログラムがシグナルで死んだ場合はぴえんの歌が再生されます
github.com
なんとなくRustの勉強も兼ねてRustで書いてます。
地味にbrewでもダウンロードできるようになってます。
$ brew tap anatofuz/pien $ brew install anatofuz/pien
別途音源が必要なので音源配布サイトからダウンロードして、ホームディレクトリに.pien.mp3
で置いておくと再生されます。
音声を流すのはafplayを雑に叩くみたいな世界観です。そぼく.....
RustでのCLIの作り方は全然解ってなかったので、いいかんじのチュートリアルを読みながら勉強しました。
肝なのは外部コマンドの終了コードの取得ですね。 Rustの場合は外部コマンドの終了コードはいい感じにパターンマッチで取得できます。
use std::process::Command; let status = Command::new("mkdir") .arg("projects") .status() .expect("failed to execute mkdir"); match status.code() { Some(code) => println!("Exited with status code: {}", code), None => println!("Process terminated by signal") }
この例だとNone
に分類されるやつらが全員シグナルで死んでるので、Noneの場合は音楽を再生すれば良いということになります。その為今回は入力で受け取ったコマンドの結果をパターンマッチし、シグナルで死んでたらafplayを実行するみたいな極めて単純な実装になってます。
こういう一発ネタみたいなコマンド作るのやはり楽しいですね。
8080ポートはgitlabのrailsアプリケーションのポートなのだけど、ここに直接プロキシするのではなく、gitlabのHTTPのルーティングを行っているgitlab-workhorseの8181ポートに繋げないと駄目だった
自分が在籍している学科ではオンプレ上にgitlabを構築して運用している。
gitlabが動いているサーバーはオンプレ上に構築したKVMで動かしているVMなのだけど、歴史的理由でこのサーバーでは他にjenkinsやredmineなども動作している。
もともとredmine-> jenkins -> gitlabの順でサーバー上に構築されたこともあり、サーバー全体のwebサーバーはapacheで動いている。
問題がgitlabのinstallでgitlab-ceを使っていたのだけれど、gitlab-ceはデフォルトでgitlabにまつわるすべてのミドルウェアなどもインストールして構築してくれる。 具体的に言うとデータベースとしてPostgreSQL、webサーバーとしてnginxを同梱している。
現状の学科のgitlabは、このgitlab-ceに同梱されているnginxをポート8000番で起動させ、apacheからそのnginxにプロキシをしていた。つまりapache -> nginx -> gitlabの順でHTTPリクエストが伝搬 される。
具体的に見るとこういう感じだった。大変ですね。
$ lsof -i :8000 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 5769 root 9u IPv4 131461357 0t0 TCP *:irdmi (LISTEN) nginx 5770 gitlab-www 9u IPv4 131461357 0t0 TCP *:irdmi (LISTEN) nginx 5770 gitlab-www 19u IPv4 131528575 0t0 TCP localhost:irdmi->localhost:52234 (ESTABLISHED) nginx 5770 gitlab-www 20u IPv4 131524330 0t0 TCP localhost:irdmi->localhost:52192 (ESTABLISHED) nginx 5771 gitlab-www 9u IPv4 131461357 0t0 TCP *:irdmi (LISTEN) nginx 5771 gitlab-www 18u IPv4 131526937 0t0 TCP localhost:irdmi->localhost:52196 (ESTABLISHED) nginx 5771 gitlab-www 19u IPv4 131530893 0t0 TCP localhost:irdmi->localhost:52244 (ESTABLISHED) nginx 5772 gitlab-www 9u IPv4 131461357 0t0 TCP *:irdmi (LISTEN) nginx 5772 gitlab-www 15u IPv4 131530209 0t0 TCP localhost:irdmi->localhost:52230 (ESTABLISHED) nginx 5773 gitlab-www 9u IPv4 131461357 0t0 TCP *:irdmi (LISTEN) httpd 7873 apache 16u IPv4 131524319 0t0 TCP localhost:52186->localhost:irdmi (CLOSE_WAIT) httpd 7874 apache 16u IPv4 131527717 0t0 TCP localhost:52192->localhost:irdmi (ESTABLISHED) httpd 8583 apache 16u IPv4 131528766 0t0 TCP localhost:52198->localhost:irdmi (CLOSE_WAIT) httpd 8831 apache 16u IPv4 131525112 0t0 TCP localhost:52164->localhost:irdmi (CLOSE_WAIT) httpd 9433 apache 16u IPv4 131524337 0t0 TCP localhost:52196->localhost:irdmi (ESTABLISHED) httpd 10272 apache 16u IPv4 131524317 0t0 TCP localhost:52184->localhost:irdmi (CLOSE_WAIT) httpd 11736 apache 16u IPv4 131529561 0t0 TCP localhost:52244->localhost:irdmi (ESTABLISHED) httpd 24102 apache 16u IPv4 131528566 0t0 TCP localhost:52230->localhost:irdmi (ESTABLISHED) httpd 24103 apache 16u IPv4 131525592 0t0 TCP localhost:52188->localhost:irdmi (CLOSE_WAIT) httpd 24111 apache 16u IPv4 131530228 0t0 TCP localhost:52234->localhost:irdmi (ESTABLISHED) httpd 24166 apache 16u IPv4 131526971 0t0 TCP localhost:52200->localhost:irdmi (CLOSE_WAIT)
この構成であまり問題は無かったのだけれど、諸事情でgitlabのHTTPヘッダにAccess-Control-Allow-Origin
の設定をする必要が出た。現状の構成だとApache側でAccess-Control-Allow-Origin
を付与しておけば良いと思ったのだけれど、実際はapache -> nginxに伝搬される際に、nginx側でヘッダ情報が落とされることが判明した。さらにgitlab-ceが生成するnginxの設定ファイルでAccess-Control-Allow-Origin
を付与するのが結構めんどくさそうだった。
というわけでapache -> nginx -> gitlab-ceのプロキシを止めて、apache -> gitlab-ceに一本化したい。本来ならapacheやめてnginxにしたいのだけれど、redmineやjenkinsのプロキシ設定も変更する必要があり、やや工数的にめんどいので段階的にやることにした。
まずはnginxを止めなければならない。
これらはgitlab側の設定ファイルgitlab.rb
を編集することで停止できる。
若干違うけれど、gitlab公式の同梱されてないnginxを使う方法が参考になった。 docs.gitlab.com
とりあえずnginxの使用を止める
nginx['enable'] = false
この後に続く nginx['hoge']
的な記述はすべてコメントアウトしておく。
末尾にこの2行を追加する(これは効果があるかどうかは不明)
gitlab_workhorse['listen_network'] = "tcp" gitlab_workhorse['listen_addr'] = "127.0.0.1:8181"
今まではこんな感じの設定だった
<VirtualHost *:443> ServerName gitlab.ie.u-ryukyu.ac.jp ProxyRequests off ProxyPass / https://127.0.0.1:8000/ ProxyPassReverse / https://127.0.0.1:8000/ SSLEngine on SSLProxyEngine on SSLProxyCheckPeerCN off SSLProxyCheckPeerName off SSLCertificateFile hoge.cer SSLCertificateKeyFile hoge.key SSLCertificateChainFile hoge.cer </VirtualHost>
何も考えずにnginxにプロキシしていたが、apacheからgitlabに直接プロキシする場合はある程度設定を書き加える必要がある。
様々な人がブログエントリで設定例を書いていたが、最終的にはgitlab公式が出しているapacheの設定例が一番正しかった。
httpsでやってることもあるので、この例の通りにやらないとリポジトリの中身が表示されないとか、LDAPログインした後にコールバックされないなどの悲しさが存在する。
ここまで設定したらgitrlabとapacheを再起動すればよい
gitlab-ctl reconfigure gitlab-ctl restart gitlab-ctl reconfigure systemctl restart httpd
akkaとakkaHTTPを最新にしてみたら動いた
diff --git a/chapter-up-and-running/build.sbt b/chapter-up-and-running/build.sbt index 1d6c95a..4e10c25 100644 --- a/chapter-up-and-running/build.sbt +++ b/chapter-up-and-running/build.sbt @@ -7,8 +7,8 @@ version := "1.0" organization := "com.goticks" libraryDependencies ++= { - val akkaVersion = "2.5.4" - val akkaHttpVersion = "10.0.10" + val akkaVersion = "2.6.6" + val akkaHttpVersion = "10.1.12" Seq( "com.typesafe.akka" %% "akka-actor" % akkaVersion, "com.typesafe.akka" %% "akka-stream" % akkaVersion,
最近Scalaやりたい感が強く、特にAkkaを使ってみたい気持ちがあったので「Akka実践バイブル」を図書館で借りて読み始めた。
Akkaが採用しているアクターモデルは今やっている研究にも応用できそうとかそういう意味合いもある。
Scalaあんま書いたことがないので、Scalaの勉強がてらみたいなところ。とりあえずsbtを使えば色々できるらしいということは解っている。
とりあえず第2章でサンプルコードがあったのでGitHubからcloneして動かした所見事に動かなかった。
日本語版のは本家のリポジトリをforkしており、それを実行すると次の様なエラーが出る。
[ERROR] Failed to construct terminal; falling back to unsupported java.lang.NumberFormatException: For input string: "0x100" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68) at java.base/java.lang.Integer.parseInt(Integer.java:658) at java.base/java.lang.Integer.valueOf(Integer.java:989) at jline.internal.InfoCmp.parseInfoCmp(InfoCmp.java:59) at jline.UnixTerminal.parseInfoCmp(UnixTerminal.java:242) at jline.UnixTerminal.<init>(UnixTerminal.java:65) at jline.UnixTerminal.<init>(UnixTerminal.java:50) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:166) at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:404) at java.base/java.lang.Class.newInstance(Class.java:591) at jline.TerminalFactory.getFlavor(TerminalFactory.java:211) at jline.TerminalFactory.create(TerminalFactory.java:102) at jline.TerminalFactory.get(TerminalFactory.java:186) at jline.TerminalFactory.get(TerminalFactory.java:192) at sbt.ConsoleLogger$.ansiSupported(ConsoleLogger.scala:123) at sbt.ConsoleLogger$.<init>(ConsoleLogger.scala:117) at sbt.ConsoleLogger$.<clinit>(ConsoleLogger.scala) at sbt.GlobalLogging$.initial(GlobalLogging.scala:43) at sbt.StandardMain$.initialGlobalLogging(Main.scala:116) at sbt.StandardMain$.initialState(Main.scala:125) at sbt.xMain.run(Main.scala:34) at xsbt.boot.Launch$$anonfun$run$1.apply(Launch.scala:111) at xsbt.boot.Launch$.withContextLoader(Launch.scala:130) at xsbt.boot.Launch$.run(Launch.scala:111) at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:37) at xsbt.boot.Launch$.launch(Launch.scala:119) at xsbt.boot.Launch$.apply(Launch.scala:20)
本家の方で動かすとぬるぽする
[info] Loading project definition from /Users/anatofuz/src/github.com/RayRoestenburg/akka-in-action/chapter-up-and-running/project java.lang.NullPointerException at java.base/java.util.regex.Matcher.getTextLength(Matcher.java:1770) at java.base/java.util.regex.Matcher.reset(Matcher.java:416) at java.base/java.util.regex.Matcher.<init>(Matcher.java:253) at java.base/java.util.regex.Pattern.matcher(Pattern.java:1134) at java.base/java.util.regex.Pattern.split(Pattern.java:1262) at java.base/java.util.regex.Pattern.split(Pattern.java:1335) at sbt.IO$.pathSplit(IO.scala:744) at sbt.IO$.parseClasspath(IO.scala:859) at sbt.compiler.CompilerArguments.extClasspath(CompilerArguments.scala:62) at sbt.compiler.AggressiveCompile.withBootclasspath(AggressiveCompile.scala:50) at sbt.compiler.AggressiveCompile.compile2(AggressiveCompile.scala:83) at sbt.compiler.AggressiveCompile.compile1(AggressiveCompile.scala:70) at sbt.compiler.AggressiveCompile.apply(AggressiveCompile.scala:45) at sbt.Compiler$.apply(Compiler.scala:74) at sbt.Compiler$.apply(Compiler.scala:65) at sbt.Defaults$.sbt$Defaults$$compileTaskImpl(Defaults.scala:789) at sbt.Defaults$$anonfun$compileTask$1.apply(Defaults.scala:781) at sbt.Defaults$$anonfun$compileTask$1.apply(Defaults.scala:781) at scala.Function1$$anonfun$compose$1.apply(Function1.scala:47) at sbt.$tilde$greater$$anonfun$$u2219$1.apply(TypeFunctions.scala:40) at sbt.std.Transform$$anon$4.work(System.scala:63) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226) at sbt.Execute$$anonfun$submit$1$$anonfun$apply$1.apply(Execute.scala:226) at sbt.ErrorHandling$.wideConvert(ErrorHandling.scala:17) at sbt.Execute.work(Execute.scala:235) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226) at sbt.Execute$$anonfun$submit$1.apply(Execute.scala:226) at sbt.ConcurrentRestrictions$$anon$4$$anonfun$1.apply(ConcurrentRestrictions.scala:159) at sbt.CompletionService$$anon$2.call(CompletionService.scala:28) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) at java.base/java.lang.Thread.run(Thread.java:830) [error] (compile:compile) java.lang.NullPointerException
なんか初手で出鼻くじかれた感じあって辛ぽよですね。3,4年前くらいの本なのでしゃーない気もする。いい感じにパッチ当ててるリポジトリを探してみよう。
自分が在籍している学科(琉大工学部知能情報コース)は学科関連のお知らせをインターネット経由で流している。歴史的にはネットニュース(fj)時代から運用されており、その後wordpressに移行している。
現在はここから見れる。
WordPressでの運用は元気に動いている間は良いのだけれど、数年前にplugin経由でGoogle検索結果を爆撃されるという事件があったりした。最近はDBのコネクションエラーが多発しており、ログを取って解析していても原因が追求できない。
更に追い打ちをかけるように学科ウェブはだいたいマルチサイト化されたWordPressで動かしているので、どこかでDBエラーなどが発生すると全滅するということになっていた。
まぁこれが辛いので静的サイト化するぞ!!!!! というのをid:unimarimoと話していたのだけど、最近のシステム更新のどさくさに紛れてシス管MTGで話したら河野先生も乗り気にできたので進めている。
静的サイト化としては色々方法があって、nuxt.jsを使う方法などを発見していた。 とはいえ学科のメンバーとwebサイトを管理しているシス管メンバーが毎年コンスタントにnuxt.jsのことが解るようになるかと言われると微妙なところがあった。
まぁこれはメンバーと主に僕の趣味で、バイナリをおいておけばどうにかなるhugoを使ってmarkdownから変換する形式にしていこうとなった。
ということで今考えている構成はこんな感じ
ci移行のとこと投稿に関しては手探りではあるのだけど、なんとなく行けそうな気がする。
news-ieは他に学科アカウントが無いと閲覧できないという機能があって、今まではwordpressのpluginで管理していたのだけれど、これはnginx側で制御することにしたい。ついでに今はwwwサーバーはapacheなのでapacheからnginxへの移行もやってしまう。
基本的には現在のnews-ieのエントリをすべて回収してくる必要がある。 賢い人はいるみたいですでにwordpress pluginでhugoで使えるmarkdown形式に変換した上でzipダウンロードしてくれるやつがあった。
管理コンソールでこのpluginを使ったところ、本当に動いているか怪しいほど時間はかかった。 1分以上立った後で、zipが無事ダウンロードされたのだけれど、ちゃんと添付ファイル込でmarkdownにしていたのでかなり良かった。
とりあえずこれで今までの投稿のmarkdownが手に入ったので、後は頑張ってhugoでhtmlを組み立てていくフェーズとなる。続きはまた...
golangにはビルド時のリンク関連の制御のldflags
オプションがある。
ldflags
を利用するとビルド時に変数の埋め込みなどが出来るのだが、これで引っかかった。
やろうとしていたことは次の様なコード。
環境変数の代わりにldflagsで変数埋め込みを行い、実行する場合は環境変数の設定を無くしたかった。
package main import ( "fmt" "os" ) var envtest string = os.Getenv("ENVTEST") func main() { fmt.Println(envtest) }
実際にこれを go build -ldflags "-X main.envtest=goodnight" ./main.go
の様にldflagsを使って変数埋め込み行いビルドした。
環境変数を設定していない状態で、生成したバイナリを実行するとこの様な結果になる。
$ ./main
何も表示されなかった。つまりenvtest
はENVTEST
環境変数をロードしにいっていることになる。
とはいえstrings
コマンドをかけてやると普通に出てくる。どういうことなの。
$ strings ./main | grep goodnight
goodnight
え〜と思い代入文を外して実験した。
package main import ( "fmt" ) var envtest string func main() { fmt.Println(envtest) }
これで全く同じ方法でビルドした。
$ ./main goodnight
埋め込まれてる!!!!!!!!!!
ドキュメントを見たところちゃんと書いてあった
-X importpath.name=value
Set the value of the string variable in importpath named name to value. This is only effective if the variable is declared in the source code either uninitialized or initialized to a constant string expression. -X will not work if the initializer makes a function call or refers to other variables. Note that before Go 1.5 this option took two separate arguments.
「This is only effective if the variable is declared in the source code either uninitialized or initialized to a constant string expression.」とのことだったので、ちゃんとドキュメントは読もうな.....
ちなみに開発環境では環境変数使って実行環境では使いたくないときはどうするべきなんだろう。。。
init
で空文字列かどうかを判定して、空文字列だったら環境変数から取るとかにするのがいいのかな。
というわけで一度投稿してみたかったエントリです!!!
2020年6月24日(水)に発売される WEB+DB Press Vol.117 の Perl Hackers Hub に「Perl歴史散策」を書かせていただきました!!みんな買ってくれ!!!!!!
沖縄だと多分無いですが大手書店では6月16日からテスト販売があるそうです!!!自分の近所の書店が大手書店だと思われる人は買ってください!!!
ちなみに外出するのはな...という皆様のために電子書籍でも販売しています!!!
気になる内容ですが
...と、個人的な趣味MAXみたいな内容でお送りしています。(別に僕が書いたコードの話ではない^q^)
今からPerlを始めてみよう、 Perlってどんな言語なのかちょっと知りたいというPerlビギナーの方はもちろんのこと。 PerlがどのようにC言語で実装されているか気になる方まで、 Perlに興味がある方なら面白いかなと思う内容だと思います!
Perl Hackers Hubは第一線のバリバリPerlエンジニアの方が多く執筆されており、業務で使っていない以前にそもそも業務をしていない学生だったので(!!!!????)となりましたが、せっかくチャンスを頂いたので書かせていただきました!
執筆はmarkdownベースの文法なファイルをガンガン書いていって、そのファイル上で校正をしていただける運用でした。こういう執筆作業でもgitみたいなバージョン管理使っているのか~!と驚きました。
実際に書籍の文章が我々の手元に届くまでにはかなりの労力がかかっている事を身を以て体験できました。徹底的に編集部の皆様に文章の校正をしていただいて、人々に伝わりやすい文章を作る難しさを痛感しました。今までと異なる目線で技術書などの書籍を見ることが出来るようになったと思います。
あとは犯罪以外で自分の名前が書かれた書籍が全国に頒布されるのは嬉しいですね。しかも憧れのWEB+DB PRESSなので感慨もひとしおです。
お誘い頂いたid:papixさんや、 的確な指摘で文章のリファクタリングをしていただいた技術評論社の稲尾さん、 英語や技術的内容のレビューをしていただいた監修の牧さんを始めとする校正などに関わってくださった皆さんに御礼申し上げます。