레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Java인 게시물을 표시합니다. 모든 게시물 표시

mac JDK 설치

# JDK 의 오픈소스는 크게 openjdk 와 adoptopenjdk 가 있다.
# openjdk (TCK(Technology Compatibility Kit) 인증됨)설치
https://formulae.brew.sh/formula/openjdk
# 가장 최신 버전이 설치된다.
brew install openjdk

# 현재 openjdk 는 최신버전(13)외 11만 설치할 수 있다.
brew install openjdk@11

# 다음 위치에 java, javac 등이 있다.
/usr/local/opt/openjdk/bin

# 참고로 /usr/local/opt/openjdk 는 실제 아래로 경로에 소프트 링킹되어 있다.
/usr/local/Cellar/openjdk
/usr/local/Cellar/openjdk@11


#####


# adoptopenjdk(openjdk 호환, TCK(Technology Compatibility Kit) 인증이 안됨) 설치
https://github.com/AdoptOpenJDK/homebrew-openjdk
# brew cast 로 openjdk 최신 버전 설치
brew cask install adoptopenjdk

# 특정 버전을 설치하는 경우
brew cask install adoptopenjdk12
brew cask install adoptopenjdk11
brew cask install adoptopenjdk/openjdk/adoptopenjdk8

# 설치 위치
# jdk 버전을 변경하고 싶을때는 export JAVA_HOME= 으로 아래 경로를 설정하면 된다.
/Library/Java/JavaVirtualMachines/adoptopenjdk-12.jdk/Contents/Home/
/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home/
/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/

springboot 2.2 사용시 gradle war 파일 생성

# springboot 2.x 부터는 gradle 5 이상을 사용해야 한다.
# springboot 2.x 이상 사용하는 경우 gradle 의 war 플러그인 설정이 달라야 한다.
# springboot 2.0 부터 war 를 상속받아 bootWar 사용하기 때문이다.
https://docs.spring.io/spring-boot/docs/current/gradle-plugin/api/org/springframework/boot/gradle/tasks/bundling/BootWar.html

# build.gradle 파일
// war 플러그인 추가
apply plugin: 'war'

// SpringBoot 사용하지 않거나 2.x 이전에서는 일반적인 war task 로 명시한다.
war {
  archiveFileName = "ysoftman-0.0.1-SNAPSHOT.war"
}
// SpringBoot 사용하지 않거나 2.x 이상에서는 bootWar task 로 명시해야 한다.
// 그렇지 않으면 디폴트 프로젝트명.war 로 생성된다.
bootWar {
  archiveFileName = "ysoftman-0.0.1-SNAPSHOT.war"
}

# 빌드하면 ./build/libs/ysoftman-0.0.1-SNAPSHOT.war 을 확인할 수 있다.
gradle clean build -b build.gradle

# springboot gradle 플러그인 참고
https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/

C Coding Convention and Naming Notation

# BSD Convention(style)
# 버클리 대학교 Eric Allman 프로그램머의 이름을 따 Allman 스타일이라고도 한다.
# 함수와 조건문 반복문 모두 중괄호 시작 위치가 뉴라인에서 시작한다.
# 장점: 중괄호의 시작 위치가 일관적이라 코드 읽기가 쉽다.
# 단점: 라인 수 증가

int funcA()
{
 if (condition > 0)
 {
  result = 1 + 1;
 }
}

# K&R(Kernighan and Ritchie) Convention(style)
# C 언어를 만드신 두분의 이름을 딴 스타일로
# 함수에는 BSD 와 같이 중괄호 시작위치가 뉴라인에서 시작하지만
# 조건문과 반복문에서는 공백후 시작한다.
# 장점: 코드량(라인수) 감소
# 단점: 중괄호 시작 위치에 일관성이 없어 BSD 에 비해 코드 읽기가 어렵다.
int funcA()
{
 if (condition > 0) {
  result = 1 + 1;
 }
}

# 참고로 함수 이름 과 { 시작 전에 파라미터를 선언하는 것으로
# K&R(Kernighan and Ritchie) old(obsolete)스타일로 거의 사용하지 않는다.
int func1(int_param, char_param)
int int_param;
char *char_param;
{
    printf("%s int_param=%d char_param=%s\n", __FUNCTION__, int_param, char_param);
    return 0;
}

# 기타 스타일
https://en.wikipedia.org/wiki/Indentation_style

# 헝가리언 표기법
# MS 프로그래머인 Charles Simonyi  가 사용한 이름 표기 방식으로 특수한 prefix 를 사용한다.
bool bFlag;
char *pName;
char cChar;
char szName[10];
int nIndex;
float fNum;
class CClass

# 카멜(Camel) 표기법
# 소문자로 시작해서 단어 사이를 대소문자로 구별한다.
void myTestFunction() {}

# 파스칼(Pascal) 표기법
# 첫번째 문자를 대문자로 시작한다.
void MyTestFunction() {}

Windows 프로그램 삭제 문제 Microsoft Fix It 으로 해결하기

프로그램 및 기능(appwiz.cpl) 에서 프로그램을 삭제하려면 해당 파일이나 경로 잘못되어 삭제가 안되는 경우가 있다.
이런 경우에는 다음의 사이트에서 Microsoft Fix It 을 다운받아 사용해보자.

http://support.microsoft.com/kb/2438651/ko

예) 이전 버전의 java 삭제 실패시 다음의 순서대로 실행한다.
















Java 테스트 페이지

실제 자바를 설치해도 웹 브라우저가 인식하지 못하는 경우 있는데,
이럴때 자바가 올바르게 작동중인지 테스트할 수 있는 웹페이지다.

http://java.com/ko/download/installed.jsp

Cassandra thrift 사용하기

/////////////////////////////////////////////////////////////
// ysoftman
// Cassandra Client Test (Java + thrift)
// thrift 는 Cassandra 배포(Cassandra/lib/*.jar) 에 포함되어 있음
// 컴파일 및 실행
// export CLASSPATH=/Users/ysoftman/workspace/test_code/CassandraTest/apache-cassandra-1.2.5/lib/*:.
// javac CassandraTest.java
// java CassandraTest
/////////////////////////////////////////////////////////////
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.lang.Math;


import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
import org.apache.cassandra.thrift.ColumnParent;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.thrift.SuperColumn;
import org.apache.cassandra.thrift.Mutation;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.NotFoundException;
import org.apache.cassandra.thrift.SlicePredicate;
import org.apache.cassandra.thrift.SliceRange;
import org.apache.cassandra.thrift.KeyRange;
import org.apache.cassandra.thrift.KeySlice;
import org.apache.cassandra.thrift.TimedOutException;
import org.apache.cassandra.thrift.UnavailableException;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/*
cassandra 0.7 이상 API 를 사용함
# 컬럼패밀리(cf) 생성;
create column family game2 with comparator=UTF8Type and subcomparator=UTF8Type and column_type=Super and key_validation_class=UTF8Type and default_validation_class=UTF8Type;
*/
public class CassandraTest
{
public static ByteBuffer toByteBuffer(String value) throws UnsupportedEncodingException
{
return ByteBuffer.wrap(value.getBytes("UTF-8"));
}

public static String toString(ByteBuffer buffer) throws UnsupportedEncodingException
{
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
return new String(bytes, "UTF-8");
}
public static void main(String[] args) throws TException, InvalidRequestException, UnavailableException, UnsupportedEncodingException, NotFoundException, TimedOutException
{
InsertData("127.0.0.1", 9160, "testdb", "col1");
// Search1("127.0.0.1", 9160, "testdb", "col1");
// Search2("127.0.0.1", 9160, "testdb", "col1");
// Search3("127.0.0.1", 9160, "testdb", "col1");
}

// 대량의 Data Insert
public static void InsertData(String ip, int port, String keyspace, String columnfamily) throws TException, InvalidRequestException, UnavailableException, UnsupportedEncodingException, NotFoundException, TimedOutException
{
long timebefore = 0;
long timeafter = 0;
long timeinsert = 0;

// cassandra db 접속하기
TSocket socket = new TSocket(ip, port);
socket.setTimeout(10000);
TTransport tr = new TFramedTransport(socket);
TProtocol proto = new TBinaryProtocol(tr);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();

// keyspace 사용
client.set_keyspace(keyspace);

// 반복적으로 데이터 넣기
String key_UserNo = "1";
//ColumnParent parent = new ColumnParent();
//parent.setColumn_family(columnfamily);
for (int i=1; i<=100; i++)
{
// 키값 자동적으로 증가
key_UserNo = Integer.toString(i, 10);

SuperColumn supercol = new SuperColumn();
supercol.setName("Map".getBytes("UTF-8"));
// MapID 와 Score 컬럼을 반복적으로 저장
for (int j=1; j<=1000; j++)
{
Column colMapID = new Column();
colMapID.setName(("MapID_"+j).getBytes("UTF-8"));
colMapID.setValue(toByteBuffer(Long.toString(j, 10)));
colMapID.setTimestamp(System.currentTimeMillis());
//client.insert(toByteBuffer(key_UserNo), parent, colMapID, ConsistencyLevel.ONE);

// 랜덤 넘버 생성
Random r = new Random(System.currentTimeMillis());
long num = Math.abs((r.nextLong()%1000));

Column colScore = new Column();
colScore.setName(("Score_"+j).getBytes("UTF-8"));
colScore.setValue(toByteBuffer(Long.toString(num, 10)));
colScore.setTimestamp(System.currentTimeMillis());
//client.insert(toByteBuffer(key_UserNo), parent, colScore, ConsistencyLevel.ONE);

supercol.addToColumns(colMapID);
supercol.addToColumns(colScore);
}
// supercolumn -> mutation 에 추가
Mutation mutation = new Mutation();
ColumnOrSuperColumn columnOrsupercolumn = new ColumnOrSuperColumn();
columnOrsupercolumn.setSuper_column(supercol);
mutation.setColumn_or_supercolumn(columnOrsupercolumn);

// mutation -> list 에 추가
List<Mutation> mutationlist = new ArrayList<Mutation>();
mutationlist.add(mutation);

// list -> map 에 추가
Map<String, List<Mutation>> mutationlistmap = new HashMap<String, List<Mutation>>();
// column family 와 mutation list 추가
mutationlistmap.put(columnfamily, mutationlist);

// map -> map 에 추가
Map<ByteBuffer, Map<String, List<Mutation>>> data = new HashMap<ByteBuffer, Map<String, List<Mutation>>>();
// rowkey 와 mutationlistmap 추가
data.put(toByteBuffer(key_UserNo), mutationlistmap);

timebefore = System.currentTimeMillis();
client.batch_mutate(data, ConsistencyLevel.ONE);
timeafter = System.currentTimeMillis();
timeinsert = (timeafter-timebefore)/1000;

// insert 시간이 오랜 걸린 경우
if (timeinsert > 5)
{
System.out.println("Data Count:"+i+"   insert time: "+timeinsert+"sec");
}

// 진행상황 파악을 위해
if (i%10 == 0)
{
System.out.println("Data Count:"+i);
}
}

tr.close();
}

// rowkey 와 컬럼을 주고 값 찾기
public static void Search1(String ip, int port, String keyspace, String columnfamily) throws TException, InvalidRequestException, UnavailableException, UnsupportedEncodingException, NotFoundException, TimedOutException
{
// cassandra db 접속하기
TSocket socket = new TSocket(ip, port);
socket.setTimeout(10000);
TTransport tr = new TFramedTransport(socket);
TProtocol proto = new TBinaryProtocol(tr);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();

// keyspace 사용
client.set_keyspace(keyspace);

// rowkey 를 알경우, 해당 로우의 컬럼의 패스 설정하여 조회
ColumnPath path = new ColumnPath();
path.setColumn_family(columnfamily);
path.setSuper_column(toByteBuffer("Map"));
path.setColumn(toByteBuffer("MapID_1"));

System.out.println(path.getColumn_family());
ColumnOrSuperColumn result1 = client.get(toByteBuffer("1"), path, ConsistencyLevel.ONE);
System.out.println(toString(result1.getColumn().value));

tr.close();
}

// rowkey 를 주고 특정범위의 컬럼에 대한 값 찾기
public static void Search2(String ip, int port, String keyspace, String columnfamily) throws TException, InvalidRequestException, UnavailableException, UnsupportedEncodingException, NotFoundException, TimedOutException
{
// cassandra db 접속하기
TSocket socket = new TSocket(ip, port);
socket.setTimeout(10000);
TTransport tr = new TFramedTransport(socket);
TProtocol proto = new TBinaryProtocol(tr);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();

// keyspace 사용
client.set_keyspace(keyspace);

// rowkey 를 알경우, 해당 로우의 전체 데이터 조회
ColumnParent parent = new ColumnParent();
parent.setColumn_family(columnfamily);
parent.setSuper_column(toByteBuffer("Map"));

SlicePredicate predicate = new SlicePredicate();
// 검색할 컬럼 범위 지정
// 모든 컬럼
//SliceRange sliceRange = new SliceRange(toByteBuffer(""), toByteBuffer(""), false, 10000);
// 특정 범위의 컬럼
SliceRange sliceRange = new SliceRange(toByteBuffer("Score_1"), toByteBuffer("Score_1000"), false, 10000);
predicate.setSlice_range(sliceRange);

List<ColumnOrSuperColumn> result2 = client.get_slice(toByteBuffer("1"), parent, predicate, ConsistencyLevel.ONE);
int i = 0;
for (i=0; i<result2.size(); i++)
{
Column column = result2.get(i).column;
System.out.println(toString(column.name) + " -> " + toString(column.value));
}
System.out.println("Count Column: "+i);

tr.close();
}

// 전체 row 에서 특정 컬럼의 값을 찾기
// 찾은 값들 중에서 조건이상 컬럼 카운트하기
public static void Search3(String ip, int port, String keyspace, String columnfamily) throws TException, InvalidRequestException, UnavailableException, UnsupportedEncodingException, NotFoundException, TimedOutException
{
// cassandra db 접속하기
TSocket socket = new TSocket(ip, port);
// 데이터가 많으면 시간이 오래 걸려 timeout 을 넉넉하게 준다.
socket.setTimeout(1000000);
TTransport tr = new TFramedTransport(socket);
TProtocol proto = new TBinaryProtocol(tr);
Cassandra.Client client = new Cassandra.Client(proto);
tr.open();

// keyspace 사용
client.set_keyspace(keyspace);

// 전체 로우를 대상으로 데이터 조회
ColumnParent parent = new ColumnParent();
parent.setColumn_family(columnfamily);
parent.setSuper_column(toByteBuffer("Map"));

SlicePredicate predicate = new SlicePredicate();
// 검색할 컬럼 범위 지정
// 모든 컬럼
//SliceRange sliceRange = new SliceRange(toByteBuffer(""), toByteBuffer(""), false, 10000);
// 특정 범위의 컬럼
SliceRange sliceRange = new SliceRange(toByteBuffer("Score_1000"), toByteBuffer("Score_1000"), false, 10000);
predicate.setSlice_range(sliceRange);

KeyRange kr = new KeyRange();
kr.setCount(100000);
// 모든 키에 대해서
//kr.start_key = toByteBuffer("");
//kr.end_key = toByteBuffer("");
kr.setStart_key(toByteBuffer(""));
kr.setEnd_key(toByteBuffer(""));

long timebefore = 0;
long timeafter = 0;
long timefetch = 0;
long timesearch = 0;
timebefore = System.currentTimeMillis();
List<KeySlice> rows = client.get_range_slices(parent, predicate, kr, ConsistencyLevel.ONE);
timeafter = System.currentTimeMillis();
timefetch = (timeafter-timebefore)/1000;
int i = 0;
int cntCol = 0;
timebefore = System.currentTimeMillis();
for (i=0; i<rows.size(); i++)
{
KeySlice ks = rows.get(i);
// 각 로우의 컬럼 출력
List<ColumnOrSuperColumn> temp = ks.getColumns();
//System.out.print("rowkey["+i+"]"  );
int j;
for (j=0; j<temp.size(); j++)
{
Column column = temp.get(j).column;
String colname = toString(column.name);
System.out.println("Column name : " + colname);
long colvalue = Long.parseLong(toString(column.value));
//System.out.print(colname + " -> " + colvalue + "    ");

// 컬럼 값이 500 인상이면 카운트
if (colvalue >= 500)
{
cntCol++;
//System.out.print("checked    ");
}
}
//System.out.print("\n");
}

timeafter = System.currentTimeMillis();
timesearch = (timeafter-timebefore)/1000;

System.out.println("all rows: "+rows.size() +", colvalue>=500 : "+cntCol);
System.out.println("Elapsed Time -> fetch:"+ timefetch + "sec + search: "+timesearch+"sec");

tr.close();
}
}

Cassandra 설치 및 쿼리

# 구글의 Bigtable과 아마존 Dynamo 의 특징을 합쳐서 만듦
# 장비추가의 과정이 단순(새로운 장비를 추가하고 설정을 바꾼 후 cassandra 재시작)
# 어떤 노드에 장애가 발생하더라도 전체 시스템이 멈추지 않음
# Availability(유효성)과 Consistency(일관성) 사이의 균형을 사용자가 선택해 사용(Read replica count, write replica count를 설정하여)
# Column 을 모아 저장하는 Column oriented DB 라사 연관된 데이터를 읽기에 적합
# SSTable(Sorted String Table)에 데이터를 추가후 SSTable 통째로 저장하기 때문에 데이터를 넣을 위치를 찾을 필요가 없어 Write 가 빠름
# 사용방법 : CLI(Command Line Interface) 쉘을 이용하거나 카산드라 쓰리프트(interface/thrift)를 이용한 프로그램 개발
# 데이터모델
# 클러스터(Cluster) : 여러대의 서버로 구성된 카산드라 클러스터 자체
# 키스페이스(KeySpace) : RDB 의 스키마에 해당하는 개념으로 하나의 카산드라 클러스터는 여러개의 키 스페이스를 가질 수 있음
# 칼럼패밀리(ColumnFamily) : RDB 의 테이블에 대응하는 개념으로 키 스페이스는 여러개의 칼럼 패밀리를 가질 수 있음
# 칼럼(Column) : 카산드라에서 저장되는 데이터의 최소 단위이며, 이름, 값, 타임스탬프를 가짐(이름이 키역할을 함)
# 슈퍼칼럼(SuperColumn) : 여러 개의 칼럼을 묶어 관리하는 단위이며, 칼럼 패밀리 정의 시 ColumnType=Super 로 명시해야함

# 다운로드
wget http://mirror.apache-kr.org/cassandra/1.2.5/apache-cassandra-1.2.5-bin.tar.gz
tar zxvf apache-cassandra-1.2.5-bin.tar.gz
cd apache-cassandra-1.2.5

# 설정 수정
vi conf/cassandra.yaml
data_file_directories:
    - /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/data
commitlog_directory: /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/commitlog
saved_caches_directory: /home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/saved_caches

vi conf/log4j-server.properties
log4j.appender.R.File=/home/ysoftman/apache-cassandra-1.2.5/ysoftman_db/log/system.log

# Cassandra 구성 하기
# JDK 설치(http://www.oracle.com/technetwork/java/javase/downloads/index.html)

# 다음 처럼 set
set CASSANDRA_HOME=/home/ysoftman/apache-cassandra-1.2.5

# Cassandra node tool
# 디스크 강제 쓰기
bin/nodetool -h localhost flush

# 요청 작업 상태 보기
bin/nodetool -h localhost tpstats

# thrift 상태 보기
bin/nodetool -h localhost statusthrift

# cfg 상태 보기(db 크기등..)
bin/nodetool -h localhost cfstats

#Cassandra 실행
bin/cassandra -f > null &

# Cassandra 쿼리하기
# Cassandra-cli (Command Line Interface) 실행하고 접속하기(포트 30000 사용)
bin/cassandra-cli
connect localhost/30000;

# 또는 한번에 시작하면서 접속하기
bin/cassandra-cli --host localhost --port 30000

# 클러스터 목록 보기
show cluster name;

# 키스페이스 목록 보기
show keyspaces;

# 키스페이스 생성
create keyspace testdb;

# 키스페이스 제거
drop keyspace testdb;

# 키스페이스 선택
use testdb;

# 컬럼패밀리(cf) 생성
create column family col1 with comparator=UTF8Type and subcomparator=UTF8Type and column_type=Super and key_validation_class=UTF8Type and default_validation_class=UTF8Type;

# cf 의 rows_cache 크기 변경
update column family col1 with rows_cached=5000;

# cf 의 keys_cache 크기 변경
update column family col1 with keys_cached=2000;

# cf 의 secondary index 설정
# rowkey 가 첫번째 인덱스
# super column 에 인덱스 지원 안됨
update column family col1 with column_metadata= [{column_name:temp, validation_class:UTF8Type, index_type:KEYS}];

# cf=col1에 rowkey=1234, super컬럼=Map, MapID_100컬럼=1000 저장
set col1[1234][Map][MapID_100]='1000';

# cf=col1에 rowkey=1234, super컬럼=Map, Score_100컬럽=100 저장
set col1[1234][Map][Socre_100]=100;

# cf=col1에 rowkey=1234, 모든 컬럼 조회
get col1[1234];

# cf=col1에 rowkey=1234, 컬럼 10개 까지만 조회
get col1[1234] limit 10;

# cf=col1에 rowkey=1234, Map의 Score_100 컬럼 삭제
del col1[1234][Map][Score_100];

# cf=col1에 rowkey=1234, 데이터의 모든 컬럼 삭제
del col1[1234];

# cf col1 모든 데이터 1000 개까지 조회
list col1 limit 1000

# cf=col1에 rowkey=1234, 컬럼 개수
count col1[1234];

MongoDB mongo-java-driver 사용하기

# testcode
https://github.com/ysoftman/test_code/blob/master/mongodb_java/MongoDBTest.java

install jenkins

# Debian/Ubuntu 에서 패키지 저장소 추가해서 설치하는 경우
# jenkins 접속 키 추가
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -

# jenkins 저장소 위치 추가
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'

# apt-get 갱신
sudo apt-get update

# jenkins 설치
sudo apt-get install jenkins

# jenkins.war 위치 파악
dpkg -L jenkins


#####


# Redhat/Centos 에서 rpm 패키지 다운받아 설치하는 경우
wget https://pkg.jenkins.io/redhat/jenkins-2.112-1.1.noarch.rpm
sudo rpm -ivh jenkins-2.112-1.1.noarch.rpm

# jenkins rpm 버전 업데이트시 다음과 같이 설치하면 현재 설치된 jenkins(서비스가 중지된 상태라도)와 충돌 에러가 발생한다.
sudo rpm -ivh jenkins-2.112-1.1.noarch.rpm
jenkins-2.112-1.1.noarch에서 설치되는 /etc/init.d/jenkins 파일은 jenkins-2.40-1.1.noarch 패키지의 파일과 충돌합니다
jenkins-2.112-1.1.noarch에서 설치되는 /etc/sysconfig/jenkins 파일은 jenkins-2.40-1.1.noarch 패키지의 파일과 충돌합니다
jenkins-2.112-1.1.noarch에서 설치되는 /usr/lib/jenkins/jenkins.war 파일은 jenkins-2.40-1.1.noarch 패키지의 파일과 충돌합니다

# jenkins rpm 버전 업데이트시 rpm 옵션으로 -U(업그레이드)하면 된다.
sudo rpm -Uvh jenkins-2.112-1.1.noarch.rpm

# jenkins home 디렉토리 변경
sudo vi /etc/sysconfig/jenkins
JENKINS_HOME="/home/ysoftman/jenkinsdata"

# 기본 포트 변경시
sudo vi /etc/default/jenkins
HTTP_PORT=8080

# 서비스로 jenkins 구동
# 정지할때는 stop 옵션 사용
sudo service jenkins start

# 최신 OS 라면 systemctl 사용
sudo systemctl start jenkins


#####


# mac 에서 패키지로 설치하는 경우
# 설치
brew install jenkins

# 실행
/usr/local/opt/jenkins/bin/jenkins 스크립트 파일에서 아래 명령을 실행한다.
java -jar /usr/local/opt/jenkins/bin/libexec/jenkins.war

# 디폴트 JENKINS_HOME 디렉토리
cd $HOME/.jenkins


#####


# .war 로 구동하는 경우
java -jar /usr/share/jenkins/jenkins.war

# 8080 포트를 이미 다른 프로세스가 사용하고 있다면 다음과 같은 에러 발생
Caused by: java.io.IOException: Failed to listen on port 8080

# 다른 포트를 사용하여 구동
java -jar /usr/share/jenkins/jenkins.war --httpPort=8888


#####


# 구동시 참고 사항
# 로그 위치
vi /var/log/jenkins/jenkins.log

# 또는
https://127.0.0.1:8080/log/all

# 접속해 보기
http://127.0.0.1:8080

# admin 패스워드는 다음 로그 파일에 기록되어있다.
# 로그 파일로 이 파일을 수정후 재시작해도 admin 패스워드는 변경되지 않았다.
cat /var/lib/jenkins/secrets/initialAdminPassword

# 암호 분실시 /var/lib/jenkins/config.xml 에서 다음과 같이 수정하여 재시작
<useSecurity>false</useSecurity>

# jenkins home, jenkins 서버 이전시 홈 디렉토리를 복사(백업/복구)하면 된다.
/var/lib/jenkins

# job 설정은 다음 위치에 config.xml 파일로 저장된다.
/var/lib/jenkins/jobs/job이름/config.xml

# 재시작시 '곧 Jenkins가 종료될 예정입니다.' 메시지 후 재시작 되지 않을때
# /restart 페이지에서 바로 종료 할 수 있다. (rest api 참고)
http://127.0.0.1/restart

Redis Java Client Jedis 테스트

// ysoftman
// Redis Java Client Connector - jedis 사용
// jar 다운로드 https://github.com/xetorthio/jedis/downloads
import redis.clients.jedis.Jedis;

public class RedisTest {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
// jedis.auth("password");

System.out.println("jedis.dbSize() = " + jedis.dbSize());

// set 해보기
System.out.println("jedis.set(\"nickname\", \"Hello Redis~\") = " + jedis.set("nickname", "Hello Redis~"));

// get 해보기
System.out.println("jedis.get(\"nickname\") = " + jedis.get("nickname"));
}
}

Eclipse "Can't load IA 32-bit .dll on a AMD 64-bit platform" 에러 발생시

Eclipse 에서 실행시 "Can't load IA 32-bit .dll on a AMD 64-bit platform" 는 JNI 로 생성된 32bit .dll 을 64bit JVM 에서 실행할때 발생하는 에러다.
.dll 을 64bit 다시 빌드를 하거나 Eclipse 에서 JVM 을 32로 설정하도록 한다.

Windows -> Preferences -> Java -> Installed JREs -> Add -> Standard VM -> jre7 Edit
-> JRE home -> C:\Program Files (x86)\Java\jre7 로 설정



Java long type variable

자바의 long 형은 64bit 크기로
-9223372036854775808 ~ 9223372036854775807 의 범위를 가진다.

다음과 같이 숫자 끝에 L 또는 l(소문자)을 붙여주지 않으면 int 형으로 인식해 컴파일 에러가 발생하다.
long num = 123456789123456789; ---> (X)
long num = 123456789123456789L; ---> (O)
long num = 123456789123456789l; ---> (O)

참고로 unsigned 형이 없는 자바에선 64bit 이상의 값을 저장하기 위해선 BigInteger 를 사용해야 한다.
import java.math.BigInteger;
BigInteger num = new BigInteger("123456789123456789123456789");

Linux Ubuntu JDK 설치하기

[방법1]
# apt-get repository 에 JDK 위치를 ppa 로 추가
# PPA(Personal Package Archive)
sudo add-apt-repository ppa:webupd8team/java

# 만약 sudo: add-apt-repository: command not found 발생시 다음 패키지를 설치
# Ubuntu 12.10 이전
sudo apt-get install python-software-properties

# Ubuntu 12.10 이후
sudo apt-get install software-properties-common

# apt-get 갱신
sudo apt-get update

# 설치
sudo apt-get install oracle-java7-installer


[방법2]
# 웹에서 직접 JDK 다운로드
http://www.oracle.com/technetwork/java/javase/downloads/index.html

# 파일 이동
mv /tmp/jdk-7u21-linux-x64.tar.gz

# 압출 풀기
tar zxvf jdk-7u21-linux-x64.tar.gz

# 설치
sudo update-alternatives --install /usr/bin/java java /home/ysoftman/jdk1.7.0_21/bin/java 1

sudo update-alternatives --install /usr/bin/javac javac /home/ysoftman/jdk1.7.0_21/bin/javac 1

sudo update-alternatives --install /usr/bin/javaws javaws /home/ysoftman/jdk1.7.0_21/bin/javaws 1

프로그래밍 게임 RoboCode

# 홈페이지 http://robocode.sourceforge.net/
# Robocode 는 내가 프로그래밍한 알고리즘이 게임에 반영되서 플레이가되는 프로그래밍 게임이다.
# Java 나 .Net 용 언어를 사용할 수 있으며 게임은 탱크를 컨트롤 하는 것이다.
# 대학교 초급 프로그래밍/알고리즘 등 과목에서 활용되면 좋을 듯 ㅎㅎ

# Java 해보기
# 설치하기 참고 http://robowiki.net/wiki/Robocode_Download_And_Install
# 기본적으로 C:\robocode 에 설치된다.
java -jar robocode-1.8.1.0-setup.jar

# 자체 에디터도 있지만 별로 좋지 않아서 eclipse 를 사용하도록 한다.
# eclipse 에 프로젝트에 lib 추가
# eclipse 프로젝트 properties -> Java Build Path -> Libraries -> Add External JARS -> C:\robocode\libs\robocode.jar

# robocode api 문서 http://robocode.sourceforge.net/docs/robocode/
# sample 소스를 참고해도 좋다.

////////////////
// ysoftman
// Robocode 테스트
////////////////
import java.awt.Color;
import robocode.*;

public class ysoftmanRobocode extends Robot
{
  public void run()
  {
    setBodyColor(Color.blue); // 탱크 색상
    setGunColor(Color.red); // 대포 색상
    setBulletColor(Color.red); // 대포알 색상

    while (true)
    {
      turnGunRight(360); // 대포 오른쪽으로 360도 회전
    }
  }
  // 적을 발견되면
  public void onScannedRobot(ScannedRobotEvent e)
  {
    // 거리가 짧으면 강하게 발사
    if (e.getDistance() < 20)
    {
      fire(3);
    }
    else
    {
      fire(1);
    }
  }
  // 우리가 포를 맞으면
  public void onHitByBullet(HitByBulletEvent e)
  {
    turnLeft(90); // 탱크 왼쪽 90도로 꺽기
    ahead(100); // 탱크 전진
  }
}

# 다음의 간단한 코드를 만들고 빌드하여 .class 만들고 C:\robocode\robots\ 에 위치시키거나
# 메뉴 Options -> Preferences -> Development -> Add -> .class 위치 를 추가한다.

# c:\robocode\robocode.bat 실행
# 메뉴 Battle -> New -> 자신이 만든 탱크와 상대편 탱크(샘플) 추가 -> Start Battle 로 시작한다.

스샷~


Java Tomcat Servlet 인코딩 설정

1. 톰캣 서버 환경파일 server.xml 의  Connector 태그 속성에 URIEncoding 을 추가한다.
톰캣홈/conf/server.xml  에서
<Connector port="8080" .... URIEncoding="EUC-KR">

2. 서블릿 소스(.java)에서 setCharacterEncoding() 을 사용한다.
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
        request.setCharacterEncoding("EUC-KR");
        response.setCharacterEncoding("EUC-KR");
}

Java jar 만들기

# 예를 들어 다음과 같이 ysoftman.java 컴파일 할 경우
# 컴파일 결과 다수의 .class 가 생성되면 jar 파일로 묶어 주는것이 좋다.
javac -classpath ../libs/abc.jar com/Test/ysoftman.java

# mainfest.txt 에 아래와 같이 시작 클래스와 라이브러리 파일등을 명시한다. 파일의 끝은 엔터(CR LF ) 값으로 해야 파싱이 된다.
Main-class: com.Test.ysoftman
Class-Path: ../libs/abc.jar

# jar 로 만들때 m 옵션을 주면 세부적인 옵션이 명시된 manifest 파일을 사용할 수 있다.
jar cvfm Test.jar manifest.txt com/Test/*.class

# 실행하면 정상 작동한다.
java -jar Test.jar

Java GC(Garbage Collection) 모니터링

//java 프로그램의 GC 모니터링를 하기 위해 JDK 의 jps 와 jstat 를 사용한다.

//jps 와 jstat 는 java, javac 가 있는 bin 디렉토리에 함께 존재한다.

//우선 자바 프로그램의 PID 를 파악하기 위해 jps 를 실행한다.

jps



//jps 로 알아낸 자바 프로그램 PID 에 대해서 jstat 로 GC 를 모니터링 할 수 있다.

//PID 12345를 1000ms(1초) 마다 GC 를 30 번 모니터링한다면 다음과 같다.

jstat -gc 12345 1000 30


Java JNI(Java Native Interface)

# JNI java 코드

# JNI(Java Native Interface) java 에서 사용할 C 코드

java 바이트코드인 JNITest.class 를 다음과 실행시킨다.(32bit java 가상머신을 사용)
java JNITest

참고로 JNI 사용할때 C코드(.dll) 디버깅 하려면...
Visual C++ 프로젝트에서 다음과 같이 설정한다.
속성 -> 디버깅 -> 명령 : C:\Program Files (x86)\Java\jdk1.7.0_15\bin\java.exe
속성 -> 디버깅 -> 명령인수 : JNITest
속성 -> 디버깅 -> 작업디렉터리 : JNITest 클래스가 위치한곳

이제 VC++ 에서 F5로 디버깅 시작~

Linux HDFS(Hadoop Distributed File System) 구성하기 및 Map Reduce 테스트

# ysoftman
# 분산 소프트웨어 플랫폼으로 대량의 데이터를 처리할때 사용
# 비슷한 플랫폼으로 구글의 GFS(분산 파일 시스템), MapReduce(분산 데이터 처리), BigTable(분산 데이터베이스)
# Hadoop 의 기본 아이디어인 MapReduce 개념을 Google 에서 논문으로 처음 소개
# Apache 검색엔진(Lucene & Nutch) 개발자에 의해 Hadoop 개발 시작
# Yahoo 에서 Hadoop 사용, Google 내 검색 처리를 위해서 MapReduce 기법 적용
# 2,000개의 노드들을 클러스터로 구성해 시연, 앞으로 10,000개의 노드들을 클러스터로 운영하는 것을 목표
# 안정적으로 PetaByte 단위의 자료를 저장하고 처리
# 일반 컴퓨터 클러스터 간의 데이터를 분산하고 처리
# 데이터를 분산시켜 데이터가 위치한 노드들을 병렬로 처리
# 자동으로 데이터 복사본을 유지하여 문제 발생시 재배치 수행
# Hadoop 의 구성 요소
# Hadoop Common : Hadoop 을 사용하는 모든 요서에서 공통으로 필요로 하는 요소
# HDFS(Hadoop Distributed File System) : 대량의 데이터를 분산저장하는 파일 시스템
# MapReduce : 대량의 데이터를 분산 처리할 수 있는 프레임워크
# 연관된 프로젝트
# Avro, Chukwa, HBase, Mahout, Pig, ZooKeeper

[Hadoop 설치]
32bit 일때(hadoop-0.19_32bit.tar.gz , jdk-6u10-linux-i586.bin , fuse-2.7.4.tar.gz) 파일을 기준
64bit 일때(hadoop-0.19_64bit.tar.gz , jdk-6u10-linux-x64.bin , fuse-2.7.3.tar.gz) 파일을 기준
1. root 상태에서 hadoop 계정을 만든다.(useradd hadoop, 홈디렉토리는 /home1/hadoop 이 된다.)
2. hadoop-0.19_32bit.tar.gz 압축을 /home1/hadoop 에 푼다.
3. jdk-6u10-linux-i586.bin 실행한다.(실행 안될 경우 chmod +x jdk-6u10-linux-x64.bin)
4. mv jdk1.6.0_10/ /usr/java/ (jdk 를 /usr/java/ 밑으로 옮긴다)
5. hadoop 계정의 .bashrc를 다음과 같이 만든다.

# .bashrc
# User specific aliases and functions
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
export JAVA_HOME=/usr/java/jdk1.6.0_10
export PATH=$JAVA_HOME/bin:$PATH

[hdfs 공간 만들기]
# 예) ysoftman 이라는 서버에 hdfs 공간 만들기
# hadoop 으로 로그인
cd ~/hadoop-0.19

# JAVA_HOME 환경변수가 설정되어 있으면 굳이 하지 않아도 된다.
vi conf/hadoop-env.sh
export JAVA_HOME=/usr/java/jdk1.6.0_10

# 최신버전에는 core-site.xml, hdfs-site.xml, mapred-site.xml 로 분할되었다.
vi conf/hadoop-site.xml
<configuration>
<property>
  <name>fs.default.name</name>
  <value>hdfs://ysoftman.com:9000</value>
</property>
<property>
  <name>dfs.name.dir</name>
  <value>/home1/hadoop/filesystem/name</value>
</property>
<property>
  <name>dfs.data.dir</name>
  <value>/data1,/data2</value>
</property>
<property>
  <name>dfs.http.address</name>
  <value>ysoftman.com:50070</value>
  <description>
    The address and the base port where the dfs namenode web ui will listen on.
    If the port is 0 then the server will start on a free port.
  </description>
</property>
<property>
  <name>mapred.job.tracker</name>
  <value>ysoftman.com:9001</value>
</property>
<property>
  <name>mapred.system.dir</name>
  <value>/home1/hadoop/filesystem/mapreduce/system</value>
</property>
<property>
  <name>mapred.local.dir</name>
  <value>/home1/hadoop/filesystem/mapreduce/local</value>
</property>
</configuration>

# HDFS 마스터 서버 명시
conf/master

# HDFS 슬레이브 서버 명시
conf/slaves

# masters 서버와 slaves서버 모두 데이터로 사용될 디렉토리의 권한을 hadoop으로 설정한다.
chown -R hadoop:hadoop /data1
chown -R hadoop:hadoop /data2

# hadoop file system 공간 포맷하기
bin/hadoop namenode -format

# jps 를 실행하여 NameNode SecondaryNameNode DataNode JobTracker TaskTracker 등이 나타나면 정상작동하는 것이다.
jps

# 마스터와 슬레이브 서버들간에 ssh 자동로그인 하도록 설정한다(ysoftman 포스트 참고)
# hdfs 중지하기
bin/stop-all.sh

# hdfs 가동하기(start-dfs.sh 와 start-mapred.sh 가 모두 실행된다.)
bin/start-all.sh

# ysoftman.com 이 10.10.10.1 이라면 다음의 주소로 hadoop cluster 정보를 확인 할 수 있다.
http://10.10.10.1:50070/

# ysoftman.com 이 10.10.10.1 이라면 다음의 주소로 hadoop map/reduce 작업 현황을 확인 할 수 있다.
http://10.10.10.1:50030/

#####



[hdfs 마운트]
# hdfs 공간을 만들었으면 그 hdfs 공간을 현재 시스템에서 마운트하여 사용한다.
# 예) server1 의 /home1/hdfs 에 만들기
# root 로 로그인해서
tar xvf fuse-2.7.4.tar.gz
configure
make && make install

# fuse 장치 권한 변경
chmod 777 /dev/fuse

# /etc/fuse.conf 파일생성해서 내용추가
vi /etc/fuse.conf
user_allow_other

# fuse
/sbin/modprobe fuse

# hdfs 를 마운트해서 사용할 디렉토디를 생성
mkdir /home1/hdfs
chown -R hadoop:nobody /home1/hdfs

# hadoop 권한에서 fuse 마운트 실행
su hadoop

cd /home1/hadoop/hadoop-0.19/src/contrib/fuse-dfs/src/
./fuse_dfs_wrapper.sh dfs://server1.ysoftman.com:9000 /home1/hdfs

# 만약 libjvm.so 파일이 없다고 나오면 아래의 경로를 /etc/ld.so.conf 에 추가하고 /sbin/ldconfig 실행
/usr/java/jdk1.6.0_10/jre/lib/i386/server/ (32bit OS)
/usr/java/jdk1.6.0_10/jre/lib/amd64/server/ (64bit OS)

[hdfs 마운트 후 작업폴더 설정]
# 예) /home1/hdfs 에 마운트 후 ocr 계정 디렉토리만들고 소유권 넘기기
# hadoop 로그인 상태에서마운트 된곳(/home1/hdfs)에서 작업폴더 만들기
mkdir ocr

# 이렇게 되면 소유자는 hadoop.hadoop 상태가 된다.
# 여기서 소유자 ocr 로 바꾸려면 아래와 같이 한다.(현재 hdfs 마운트되어 /home1/hdfs 가 루트디렉토리가 된다.)
~/hadoop-0.19/bin/hadoop fs -chown -R ocr:ocr /ocr

#####


[Map Reduce 테스트]
# MapReduce 예제 : 두개의 파일로 부터 word count
# 입력 파일 작성
cat > ysoftman1.txt
apple banana milk lemon
cat > ysoftman2.txt
lemon cheese apple coffee

# HDFS 로 복사하기(dfs : hdfs 사용, -put : 복사명령)
./bin/hadoop dfs -put ysoftman1.txt input/ysoftman1.txt
./bin/hadoop dfs -put ysoftman2.txt input/ysoftman2.txt

# hadoop 에 포함된 예제 프로그램 word count 실행
./bin/hadoop jar hadoop-0.20.0-dev-examples.jar wordcount input output

# word count 결과 확인(dfs 대신 fs (일반 file system 사용)을 사용해도 됨)
./bin/hadoop dfs -cat output/part-00000
apple   2
banana  1
cheese  1
coffee  1
lemon   2
milk    1

# mapreduce 작업 모든 상태보기
bin/hadoop job -list all

# mapreduce 로 작업중인 작업 강제 종료하기
bin/hadoop job -kill 작업ID

Windows Eclipse 처음 실행 시 에러 해결방법

Windows 환경에서 JDK 와 Eclipse 를 설치하고 처음 실행하면 아래와 같은 에러 메시지가 나오면서 실행이 안되는 경우가 있다.


이경우 virtual machine 경로가 설정되어 있지 않는 문제로 eclipse.ini 파일에 javaw.exe 경로(빨간색부분)를 추가해 주면 된다.

-startup
plugins/org.eclipse.equinox.launcher_1.0.200.v20090520.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-product
org.eclipse.epp.package.jee.product
--launcher.XXMaxPermSize
256M
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
-vm

C:\Program Files\Java\jdk1.6.0_16\bin\javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m