load data local infile時にMySQLで文字化けしてしまう

ちょっとハマったのでメモ

  • MySQL5.1.71
  • CentOS 5.2

MySQLでSjisファイルをロードするときに文字化けしてしまう

$ export LANG=ja_JP.sjis	# 効かない
$ mysql -uroot -hhost -ppass --local-infile=1 --default-character-set=sjis << Eof
use mysql
;
set names sjis	# 効かない
;
load data local infile "sjis.txt" into table table
;
Eof

悩みました

$ mysql -uroot -hhost -ppass --local-infile=1 --default-character-set=sjis << Eof
use mysql
;
set character_set_database=sjis	 # これでOK
;
load data local infile "sjis.txt" into table table
;
Eof

どうやらDBの設定がおかしかったようです

mysql> show global variables like "%charac%";
+--------------------------+--------------------------------------------------------------+
| Variable_name						| Value																												|
+--------------------------+--------------------------------------------------------------+
| character_set_client		 | latin1																											 |
| character_set_connection | latin1																											 |
| character_set_database	 | latin1																											 |
| character_set_filesystem | binary																											 |
| character_set_results		| latin1																											 |
| character_set_server		 | latin1																											 |
| character_set_system		 | utf8																												 |

これを変更するにはmy.cnfに設定し再起動すればOKです

$ vi my.cnf
[mysql]
default_character_set = sjis
[mysqld]
character-set-server=sjis

グローバル変数もこうなります

mysql> show global variables like "%charac%";
+--------------------------+----------------------------+
| Variable_name						| Value											|
+--------------------------+----------------------------+
| character_set_client		 | sjis											 |
| character_set_connection | sjis											 |
| character_set_database	 | sjis											 |
| character_set_filesystem | binary										 |
| character_set_results		| sjis											 |
| character_set_server		 | sjis											 |
| character_set_system		 | utf8											 |

macを10.9.1にバージョンアップしたらmac->winのSynergyでバックスラッシュが効かなくなってしまった場合の対処

サーバ側

  • MacOS 10.9
  • SynergyKM

クライアント側

  • windows7
  • Synergy1.3.1a-ja

こちらを参考に、http://wiki.nothing.sh/page/memo/Synergy 上記構成でMacをサーバにWindowsをクライアントとしてSynergyを使っていたのですが、どうやら10.9.1にバージョンアップしたらWindows側でバックスラッシュ「¥」が効かなくなってしまいました。

10.9.1のReleaseNoteをチラッと見ると、日本語入力周りの修正等と書いてあったのでもしやこれに引っかかったか?

非常に不便なので、ダメ元でWindows側のSynergyを1.3.1-jaに変更。

どうせ一緒だものね。

と、なんと、これでバックスラッシュが効くようになったとさ。

今回のMacOSのアップデートで、どうやらずいぶんと前からある不具合を直したのでしょうか?

LinuxからMac10.9へリモートディスプレイでX上のFirefoxを動かす

ちょっとはまったのでメモ。

通常X-Windows同士はお互いに、リモートでディスプレイ上のものを映すことができます。

A:Linux

B:Linux

A->BへsshでログインしBのFirefoxを起動しAのX上で操作するということです。

意外とこれが便利。

X-Windowを搭載しているMacでも同じことが当然できるはず。

ということで試してみる

古い記憶を辿りながら

Local

mac 10.9(hostname:mac,ip:192.168.0.1)

remote

RedHat 5.8 (hostname:linux,ip:192.168.0.2)

Macでの設定

[mac] $ xhost +

Linux側での設定

[mac] $ ssh linux
[linux] $ export DISPLAY=192.168.0.1:0
[linux] $ firefox
Error: cannot open display: 192.168.0.1:0

これが起動しない。

こちらに解決法が。。

http://ruepprich.wordpress.com/2013/01/08/x11-forwarding-on-os-x-10-8-2-mountain-lion/

Macでの設定

[mac] $ sudo xhost + linux

Linux側での設定

[mac] $ ssh -X linux
[linux] $ firefox

見事にMac側にFirefoxのウインドウが。。

DISPLAYは必要ないのね。。

Mahoutでjava.util.NoSuchElementExceptionが出た時の対処

機械学習用のライブラリ、ApacheMahoutを使用していてちょっと困ったのでメモ

import java.io.*;
import java.util.*;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.*;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;

class test{

	public static void main(String[] argv){
		try{
			DataModel model=new FileDataModel(new File("test.csv"));
			ItemSimilarity similarity=new PearsonCorrelationSimilarity(model);
			Recommender recommender= new GenericItemBasedRecommender(model,similarity);
			List recommendations=recommender.recommend(1,5);
			for(RecommendedItem recommendation:recommendations){
				long recommendCode=recommendation.getItemID();
				System.out.println(recommendCode);
			}
		}catch(Exception e){}
	}
}

こんなかんじでアイテムベースのレコメンドを作成していたのですが、CSVファイルを読み込んだ際に

java.util.NoSuchElementException
				at com.google.common.base.AbstractIterator.next(AbstractIterator.java:75)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.processLine(FileDataModel.java:384)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.processFile(FileDataModel.java:340)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.buildModel(FileDataModel.java:239)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.reload(FileDataModel.java:208)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.(FileDataModel.java:194)
				at org.apache.mahout.cf.taste.impl.model.file.FileDataModel.(FileDataModel.java:149)

こんなエラーが出て進まない時がある。実行したのはLinux64Bit環境のjdk1.6。

同じものをwindows7のjdk1.6で動かしてもエラーが出ない。。。

読み込んだCSVは600万行程度

よくわからないのですがCSVの最後に改行を入れるとエラーなく動作。

わけわからん

rubyでMongoDBにISODateを入れる試み

  • ruby1.9.3

apacheのログなどを解析する場合にはmongodbに一度入れると扱いやすくなります。

そこでこのプレーンテキストのapacheのログをrubyを使っていれる試みをしてみました

この辺りを参考に

http://mironal-memo.blogspot.jp/2012/07/mongodb-ruby.html

gem install mongo
gem install bson_ext

ログからip,時間、urlの3つ、必要なものを抽出します

zcat access.log.gz |awk '{print $1"\t"$4"\t"$7}' > log.txt
#!/bin/env ruby
require "mongo"

conn=Mongo::Connection.new
db=conn.db("database")
col=db.collection("logs")
open("log.txt"){|f|
	f.each{|line|
		line.chomp!
		ay=line.split("\t")
		col.insert({"ip"=>ay[0],"date":"ISODate(Time.parse(ay[1].gsub("[","").sub(":"," ")).strftime('%Y-%m-%dT%H:%M:%SZ'))","url":ay[2])
	}
}

こんな感じで入るのかと思ったのですがISODateにはなりません

仕方がないので一度ファイルにします

  • create.rb
#!/bin/env ruby
puts "use database"
open("log.txt"){|f|
	f.each{|line|
		line.chomp!
		ay=line.split("\t")
		puts 'db.logs.insert({ip:"'+ay[0]+'","date":ISODate("'+Time.parse(ay[1].gsub("[","").sub(":"," ")).strftime('%Y-%m-%dT%H:%M:%SZ'))+'"),"url":"'+ay[2]+'"))'
	}
}
ruby create.rb > mongo.dat
mongo < mongo.dat

これくらいしかわかりませんでした

20131225 追記

一度ファイルにせずともできました

#!/bin/env ruby
require "rubygems"
require "mongo"
require "time"
include Mongo
db=MongoClient.new("localhost",27017).db("database")
col=db.collection("test")
col.insert({"id"=>"id0","date"=>Time.parse("2013-12-25 00:00:00").utc})

Time型のオブジェクトを作成し、utcへ変換するとMongodbではISODateへとなっています

sshでsudoを使ってtomcatをスタートする

  • centos 5系
$ ssh user@server sudo /usr/local/tomcat/bin/startup.sh
sudo: sorry, you must have a tty to run sudo

どうやらttyがないとエラーになるらしいので以下のオプションをつける

$ ssh -t user@server sudo /usr/local/tomcat/bin/startup.sh

このままだとスタートアップしてもsshでログアウトするとTOMCATも終了してしまう

$ ssh -t use@server sudo nohup /usr/local/tomcat/bin/startup.sh

nohupを使うことによりログアウト後もTOMCATが終了しない

ちなみに/etc/sudoersは

root	ALL=(ALL)	 ALL
user ALL=NOPASSWD: /usr/bin/nohup /usr/local/tomcat/bin/startup.sh

さらにパスワードを入れるのが面倒な場合は

  • remotestart.sh
#!/bin/sh
restart(){
expect << Eof
set timeout -1
spawn ssh -t user@host sudo nohup /usr/local/tomcat/bin/startup.sh
match_max 100000
expect -exact "user@host's password: "
send -- "password\r"
expect eof
Eof
}
restart

このシェルを実行

marveriksにアップデートしたらSynergyのキー配列が変

以前Windowsをサーバにmacをクライアントでsynergyを使用していたのですが、macのOSをmountain lion からmavericksにアップデートしたところ、synergyで記号がまたまたおかしくなってしまった

以前はキーボードの設定で地域をオーストラリアなどにすればよかったのですが今回はそういう設定がなくなった模様。。

いろいろごじゃごじゃやってようやく解決

  • mac 10.9 + SybergyKM
  • windows 7 + Synergy1.3

1.macのシステム設定からキーボードを選択

2.入力ソースで+からbritish-PCを選択

3.ことえりを選択し英字のチェックを外す

つまり英語入力時にはbritish-PCを使えば106キーボードの記号がそのまま出ます

そろそろバグ修正してもらえませんかねぇ

Scala+SlickでTupple22問題を解決してみた

slickというかscalaには有名なタプル22問題があります。

23項目以上のメンバを持ったcase classが作れない。

どうやらscala2.11では解消されているようですが、まだベータ版ということで使うのにはためらいます

そこでネストしたcase classを用いて23カラム以上持つデータベースのテーブルを取得するものを作成してみました

  • scala2.10.2
  • slick2.10-1.0.1
  • eclipse 4.3
  • Tests.scala

import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession
import scala.slick.jdbc.{GetResult, StaticQuery => Q}
import Q.interpolation

	 case class PartA(a01: Int, a02: Int, a03: Int, a04: Int, a05: Int, a06: Int, a07:Int, a08:Int, a09:Int, a10:Int)
	 case class PartB(a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17:Int, a18:Int, a19:Int, a20:Int)
	 case class PartC(a21: Int, a22: Int, a23: Int, a24: Int)
	 case class Whole(id: Int, p1: PartA, p2: PartB, p3: PartC)

		object Tests extends Table[Int]("test"){
			def id = column[Int]("id", O.PrimaryKey)
			def a01 = column[Int]("a01")
			def a02 = column[Int]("a02")
			def a03 = column[Int]("a03")
			def a04 = column[Int]("a04")
			def a05 = column[Int]("a05")
			def a06 = column[Int]("a06")
			def a07 = column[Int]("a07")
			def a08 = column[Int]("a08")
			def a09 = column[Int]("a09")
			def a10 = column[Int]("a10")
			def a11 = column[Int]("a11")
			def a12 = column[Int]("a12")
			def a13 = column[Int]("a13")
			def a14 = column[Int]("a14")
			def a15 = column[Int]("a15")
			def a16 = column[Int]("a16")
			def a17 = column[Int]("a17")
			def a18 = column[Int]("a18")
			def a19 = column[Int]("a19")
			def a20 = column[Int]("a20")
			def a21 = column[Int]("a21")
			def a22 = column[Int]("a22")
			def a23 = column[Int]("a23")
			def a24 = column[Int]("a24")

			def * = id

			def all = (
				id,
				(a01, a02, a03, a04, a05, a06, a07, a08, a09, a10),
				(a11, a12, a13, a14, a15, a16, a17, a18, a19, a20),
				(a21, a22, a23, a24)
			)
	
			private def connectDB[Any](db:javax.sql.DataSource,f: => Any): Any = {
				Database.forDataSource(db) withSession {f}
			} 
			implicit val sqlToClass=GetResult(rs=>Whole(rs<<,PartA(rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<),PartB(rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<,rs<<),PartC(rs<<,rs<<,rs<<,rs<<)))
 
			def select(db:javax.sql.DataSource,id:String):Option[Whole]= {
				connectDB(db,
				{
				sql"select 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4 ".as[Whole].list.headOption
				}
		)
	}
}

  • TestsTest.scala

import javax.sql._
import javax.naming._

import org.junit._

import com.mysql.jdbc.jdbc2.optional._

class StockMasterTest {
	 private def testDataSource:javax.sql.DataSource={
	System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory")
	System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming")
	val ic = new InitialContext()
	ic.createSubcontext("java:")
	ic.createSubcontext("java:comp")
	ic.createSubcontext("java:comp/env")
	ic.createSubcontext("java:comp/env/jdbc")

		val ds = new MysqlConnectionPoolDataSource()
	ds.setUser("root")
	ds.setPassword("password")
	ds.setDatabaseName("dbname")
	ds.setServerName("localhost")
	ds.setPortNumber(3306)
	ic.bind("java:comp/env/jdbc/database", ds)
	ds
	} 

	@Test
	def select:Unit={
		val list=Tests.select(testDataSource,"id");
		println(list)

	}

}
  • eclipse4.3で実行
Some(Whole(0,PartA(1,2,3,4,5,6,7,8,9,0),PartB(1,2,3,4,5,6,7,8,9,0),PartC(1,2,3,4)))

とりあえず動いているようです

iptablesでNAT変換しTOMCATをポート80で動かす

色々やりかたはあると思うのですが、ROOT権限で動かしたくなかったので

iptablesでNAT変換します

iptables -F
iptables -t nat -F
iptables -X
iptables -Z
iptables -t nat -A OUTPUT -d localhost -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A OUTPUT -d `hostname` -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -A PREROUTING -d `hostname` -p tcp --dport 80 -j REDIRECT --to-ports 8080
iptables -t nat -L