selinux上のCGIでjavaを動かせるようにする方法
これまで使ってたCGIを移設したら動かなくなって、その理由がselinuxのポリシーだった。 ポリシーの作り方と書き換え方をメモ。
環境はCentOS6.6で、kernel 2.6.32、apache2.2.15 この上でブラウザからjavaを実行しようとしたら
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007fcf589ac000, 2555904, 1) failed; error='Permission denied' (errno=13)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (malloc) failed to allocate 2555904 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /tmp/jvm-21000/hs_error.log
こんな感じのエラーが出力された。
とりあえずPermission deniedなことはわかったけど、なんのパーミッションがないのか分からず、検索したところ
In case anyone else is looking for a way to resolve this without explicitly disabling SELinux, the wiki page at centos.org helped me understand what was going on.
By default, the security context that Java is running in when called from Apache does not allow things like reading a file, allocating memory, accessing the network etc. The easiest way to resolve these errors is by using the semodule and audit2allow applications. Essentially, check the SELinux audit log (could be /var/logs/audit/audit.log, but I used /var/log/messages and extracted the avc errors). In the log you should see things like
linux - Run java in php apache2 - Super User
ということでどうやらselinuxだからメモリアロケーションの権限が無いらしい。ここに書いてあるwiki HowTos/SELinux - CentOS Wiki に解決法があった。
audit.logというログファイルをもとに追加するポリシーを作成するらしい。 まず作成・登録するためのツール群が入ってなかったのでインストール
$ sudo yum install policycoreutils-python
$ sudo grep java_t /var/log/audit/audit.log | audit2allow -m javalocal > javalocal.te
としてjavalocal.teの中身を確認。
module javalocal 1.0; require { type httpd_sys_script_t; class process execmem; } #============= httpd_sys_script_t ============== #!!!! This avc is allowed in the current policy allow httpd_sys_script_t self:process execmem;
関係ありそうなことが書いてあるか確認する。
上のようにcentos wikiに書いてあるとおりやったけど、下のように後から全部を読み込ませても同じ結果になることを確認した。audit2allowが良きに計らってくれるらしい。
$ sudo cat /var/log/audit/audit.log | audit2allow -m javalocal > javalocal.te
確認したら、実際に登録するppファイルを作成する
$ sudo grep java_t /var/log/audit/audit.log | audit2allow -M javalocal
これでjavalocal.ppができているので
$ sudo semodule -i javalocal.pp
で登録。
IRangesパッケージのnarrowにおけるstart
例によってR言語上級ハンドブックを使った勉強会からのネタ。
Section26でBioconductorのIRangesパッケージを使った区間データの取り扱いのところで出てくるnarrow関数の引数がわかりにくかった。
narrow関数
こんな感じで区間を狭める
# Bioconductor のインストール > source("http://bioconductor.org/biocLite.R") > biocLite("IRanges") # データの生成 > y.start <- seq.int(4, 22, by = 6) > y.end <- seq.int(7, 30, by = 6) # IRanges オブジェクトに格納する > y <- IRanges(y.start, y.end) > y > y IRanges of length 4 start end width [1] 4 7 4 [2] 10 13 4 [3] 16 19 4 [4] 22 25 4 > narrow(y, start=1:3, width=2) IRanges of length 4 start end width [1] 4 5 2 [2] 11 12 2 [3] 18 19 2 [4] 22 23 2
このnarrowの引数のstartがピンとこなかった。
このstartは各区間の何番目から開始するかという値でベクトルで与えると対応する区間が指定した場所からのスタートになる。
上の例だとc(1,2,3)というベクトルが与えられているので
- 区間1(4〜7)では1番目の4から
- 区間2(10〜13)では2番めの11から
- 区間3(16〜19)では3番目の18から
となる。与えられなかった区間4(22〜25)では1番目の22から始まっている。
またendという引数もあって同様に終わるところを指定できる。
Rでマルチコア計算
R言語上級ハンドブックのChapter2 Section25「マルチコアで計算を繰り返し行う」でmulticoreパッケージを使った演算を行ってる。Windows環境ではこのパッケージが動かないので、ここにメモ。
計算はすべてMacでやってます。
実行時間を比較
テキストではモンテカルロ積分を使った演算をして、マルチコアを用いるmclapply、sapply、forの3通りの実装で速度を比較しています。
# テストデータを作成 > x.num <- 100 > x <- seq(0.1, 2.5, length = x.num) > m <- 100000 > u <- runif(m) # 並列化して確率密度関数を計算 > system.time(mclapply(x, + function(x) { + g <- x * exp( -(u * x)^2 / 2) + mean(g) / sqrt(2 * pi) + 0.5 + } + )) ユーザ システム 経過 38.962 7.810 0.152 # 並列化せずに確率密度関数を計算 (sapply) > system.time(sapply(x, + function(x) { + g <- x * exp( -(u * x)^2 / 2) + mean(g) / sqrt(2 * pi) + 0.5 + } + )) ユーザ システム 経過 0.228 0.126 0.354 # 並列化せずに確率密度関数を計算 (for) > system.time(numeric(x.num) + for ( i in 1:x.num ) { + g <- x[i] * exp( -(u * x[i])^2 / 2) + cdf[i] <- mean(g) / sqrt(2 * pi) + 0.5 + }) ユーザ システム 経過 0.226 0.110 0.335
経過時間(テキスト137ページの表のelapsed)を比較するとmclapplyが倍以上速い。
mclapply | sapply | for | |
---|---|---|---|
経過時間 | 0.152 | 0.354 | 0.335 |
計算してるiMacは4コアなので並列効率はそこそこ?
sapplyとforが似たり寄ったり
もっとsapplyのほうが速いって聞いてたんですけど。というわけでもうちょっと計算してみた。
# テストデータを作成 > x.num <- 100 > x <- seq(0.1, 2.5, length = x.num) > m <- 1000000 > u <- runif(m) > mc <- numeric(100) > for(i in 1:100){ + t <- system.time(mclapply(x, + function(x) { + g <- x * exp( -(u * x)^2 / 2) + mean(g) / sqrt(2 * pi) + 0.5 + } + )) + mc[i] = t[3] + }
mを10倍にして100回施行。これをmclapply、sapply、forについてそれぞれ実行して、それぞれの経過時間のmeanとvarを計算。
mclapply | sapply | for | |
---|---|---|---|
mean | 1.88988 | 5.05238 | 5.06731 |
var | 0.0006068137 | 0.01092876 | 0.008823186 |
MacでRcppを動かしたい
珍しく続けて更新。
R言語上級ハンドブックを使った勉強会をしてまして、躓いたところを補完しておきます。
環境
MacOSX10.9 Marvericks、Xcode 5.0.1の上でThe R Project for Statistical Computingで配布されているR 3.0.2 binary for Mac OS Xを動かしてる。
C++のコードをコンパイルしようとするとエラー
Chapter1 section13 「S4/Refference ClassをRcppで生成する」ではC++のソースをコンパイルしてRで使おうっていう章でテキストは以下のような流れ。
> install.packages(c("inline", "Rcpp")) > library(inline) > library(Rcpp) > inc <- ' using namespace Rcpp; using namespace std; class Student { :(中略) } ' > mod_std <- cxxfunction(signature(),plugin="Rcpp",includes=inc) > mod_student <- Module("mod_student", getDynLib(mod_std)) > Student <- mod_student$Student > student1 <- new (Student, 18, "Taro")
incにコードが入ってて、それをcxxfunctionでコンパイルしたい。
だがしかし、cxxfunctionを実行すると、
以下にエラー dyn.load(libLFile) : 共有ライブラリ '/var/folders/9r/x2b16sds2l30w0tds8p29k740000gn/T//RtmpbtB1sk/filed517926b08c.so' を読み込めません: dlopen(/var/folders/9r/x2b16sds2l30w0tds8p29k740000gn/T//RtmpbtB1sk/filed517926b08c.so, 6): Symbol not found: __Z8demangleRKNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE Referenced from: /var/folders/9r/x2b16sds2l30w0tds8p29k740000gn/T//RtmpbtB1sk/filed517926b08c.so Expected in: flat namespace in /var/folders/9r/x2b16sds2l30w0tds8p29k740000gn/T//RtmpbtB1sk/filed517926b08c.so
なんかのダイナミックライブラリが読み込めてないって怒られる。
調べてみたところ、Rをコンパイルした環境と使ってる環境が違うんじゃないかって話で、具体的にはRはlvm-gcc 4.2を使ってコンパイルされてて、MacOSXのコンパイラがclang++なのが問題っぽい。
Rをコンパイルすればいい
手っ取り早く解決するためにRをコンパイルすることにした。とはいってもソース落としてきたりするのは面倒なのでhomebrew*1で一発解決。
$ brew install R
このRは/usr/local/bin/にインストールされる*2。先にあったバイナリ版のRは/usr/bin/Rにシンボリックリンクがあるのでこれを消して新しくbrew版のRのリンクを置いておく。これでRStudioからも見える。
$ rm /usr/bin/R $ ln -s /usr/local/bin/R /usr/bin
Windows環境で出るエラーについて
以下のような別のエラーが出てて
Error in compileCode(f, code, language = language, verbose = verbose) : Compilation ERROR, function(s)/method(s) not created! In addition: Warning message: running command 'C:/PROGRA~1/R/R-30~1.2/bin/x64/R CMD SHLIB file156c720a4197.cpp 2> file156c720a4197.cpp.err.txt' had status 1
ざっと調べたところfortranのコンパイラが足りないとかなんとか。とりあえずいろいろ導入してくれるRTools(http://cran.r-project.org/bin/windows/Rtools/)っていうのを入れるといいらしい。Rcpp・inlineパッケージを使ってC++とRを連携させる - My Life as a Mock Quantに詳しく書いてあったので見てみるといいかもしれません。
*1:homebrewのインストールと使い方はHomebrewの使い方 - maruko2 Note.とかを参考に。
*2:本当は/usr/local/Cellar/r/3.0.2/bin/Rにあるけどわかりやすいからこっちで
正規表現の後読みと先読みとAtomic grouping
R言語上級ハンドブックを使って勉強会をしてて、perl互換の正規表現というところで引っかかったのでメモ。
31ページから引用
# Perl互換の正規表現による柔軟な文字列抽出 text <- "@bar [email protected] @foo@" # 先読み・後読みなどの利用 strapply(text, "(?<!\\w)@(?>\\w+)(?!@)", backref = 0, perl = TRUE)
\が二重になってるのはRの仕様で文字列中の\をエスケープしないと関数に\として渡せないかららしい。
perlの正規表現では(?~)は特別な意味を持っていて、そのうち先読みと後読み、それからAtomic groupingの3つがここで使われてる。
ちなみに上記のマッチの結果は@barになる。
先読みと後読み
マッチする条件を前後に拡張する。
パターン | 意味 |
---|---|
(?<=hoge) | 前にhogeがあるときだけマッチ |
(?<!hoge) | 前にhogeがないときだけマッチ |
(?=hoge) | 後にhogeがあるときだけマッチ |
(?!hoge) | 後にhogeがないときだけマッチ |
さっきの正規表現の最初と最後はそれぞれ
- (?<!\\w)
- (次に続く@の)前に\wがない
- (?!@)
- (前にある“@(?>\\w+)”の)後に@がない
という意味になる。
先読みと後読みを効果的に使う例として桁のカンマを挿入するcommafying numbersが有名で
my $text = "The population of 298444215 is growing"; text =~ s/(?<=\d)(?=(\d\d\d)+(?!\d))/,/g; print "$text\n"; # The population of 298,444,215 is growing
とかできる。
atomic grouping
真ん中の正規表現(?>\\w+)はatomic groupingというやつで「強欲な」マッチングをする。
強欲の説明はコードをみたほうが話が早い。
my $text = "something"; if($text =~ /\w+ing/){ print "MATCH\n"; }else{ print "NOT match\n"; } if($text =~ /(?>\w+)ing/){ print "MATCH\n"; }else{ print "NOT match\n"; }
これを実行すると
MATCH NOT match
となる。
はじめの\w+は単純な正規表現ですべての半角英数字とアンダースコアが1つ以上続くという意味。そのあとにingが続いている。この場合マッチングではingの部分はパターン中のingに譲って\w+はsomethにマッチする。
つぎの(?>\w+)は「強欲な」マッチングで後に続くingに譲らない。そのため(?>\w+)がsomething全体にマッチする。結局(?>\w+)ingはsomethingにマッチできない。
このテキストで、atomic groupingを使って結果が変わるわけでもないのにどうして採用したのか分からないけど、強欲なマッチングについて知らなかったのでタメにはなった。
参考にしたサイト
参考にした本
- 作者: Jeffrey E.F. Friedl,株式会社ロングテール,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2008/04/26
- メディア: 大型本
- 購入: 24人 クリック: 754回
- この商品を含むブログ (84件) を見る
- 作者: 荒引健,石田基広,高橋康介,二階堂愛,林真広
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2013/09/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (11件) を見る
LDRからホットキー一発でPocketに投げるUserScript
iPhoneにしてReeder使い始めるためにGoogleReaderに変更したんで約4年弱かな。LDRに返り咲いた。
その記念にChromeでPocketにホットキー一発でポストできるスクリプトを今の仕様で動くようにしてみたよ。
Pocket from LDR for Greasemonkey
実はこのままだと使えなくて各自書きなおしてもらわないといけないのでめんどくさい。すまん。
詳しい使い方とかはREADMEかlivedoor readerからPocketにワンキーで投稿する | ふて寝。で。
gitの人はこちらからどうぞ。
Pocket from LDR for Greasemonkey
LDRに返り咲いた
記念カキコ。