[Shell] bash version upgrade on Mac

[Shell] bash version upgrade on Mac
Mac에서 Bash 쉘 버젼을 4버젼으로 업그레이드 하기.

1. 현재 버젼 확인
> bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darw
2. brew 인스톨 하기.
- brew가 인스톨 되어 있지 않다면 다음 명령어로 인스톨 한다.
> sudo ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

3. bash 업그레이드 하기.
>  sudo brew update && brew install bash 

4. 버젼 확인하기.
> bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc. 
- 상기 내용을 보면 여전히 bash버젼은 3.2.57이다.
- 이것은 bash test가 여전히 3.X버젼을 가리키고 있기 때문이다. 이제 글로벌 변수인 $BASH_VERSION을 참조하도록 변경해보자.

5. 쉘 변경하기.
- 기존 bash는 /bin/bash였다. 이 쉘을 /usr/local/bin/bash로 변경하자.
> sudo /etc/shells
/usr/local/bin/bash    <-- 새로 설치된 bash 경로를 넣어준다. 
> chsh -s /usr/local/bin/bash
> chsh   <-- bash가 변경된 것을 확인할 수 있다.  
 - 이제 버젼을 확인해보면 바뀌어 있는것을 확인할 수 있다.

6. bash --version


# 확인해야할 사항 :
> echo $BASH_VERSION
BASH_VERSION: Undefined variable. 

Problem. 이 결과가  정상적으로 버젼을 알려주지 못하는 이유를 모르겠다.
--> 찾아서 해결하기.

Resolve.
--> 서버를 재시동 하니 $BASH_VERSION에 값이 설정되었음..

[영어] Go, Come, Get, Be 장소에 대한 동사

[영어] Go, Come, Get, Be 장소에 대한 동사
Go와 Come 

Go :
    어떤 사람이나 물건이 있는 장소에서 멀어져 가는 경우
    출발점을 중심으로함

Come :
    목적하는 방향으로 다가옴을 의미한다.
    도착점을 중심으로함

example )
Are you going to the party ?
    단순히 상대에게 파티에 갈 의사가 있는지 물어봄

Are you coming to the party ?
    파티에 나도 가는데 너도 가느냐?의 의미로 물어봄

He went home.
    회사나 특정 장소에서 집으로 막 나온 시점 (출발기준)

He came home.
    이미 집에와서 쉬고 있는 시점 (도달기준)


Get 
    get은 도착지로 갈때까지의 노력이나 과정을 포함한다.

example )
Could you tell me how to get to the nearest station?
    가까운 역에 도착하는 방법을 가르쳐 주시겠습니까? (가까운역에 어떻게 가나요?)

Can you go to the party this evening?
    단순히 파티에 갈 수 있느냐?의 의미

Can you get to the party this evening?
    어떠한 일이 있어도 파티에 갈 수 있느냐?의 의미

Be
    도착해서 도착지에 머물고 있음을 의미한다.

example )
Please be here at three.
    3시에 이곳에 있어주세요.

I'll come (back) here in a minute. (X)
I'll be (back) here in a minute. (O)
    곧 돌아오겠습니다.


[Spring] Transaction Propagation

[Spring] Transaction Propagation
Spring에서는 호출되는 메소드에 대한 트랜잭션 경계를 다음과 같이 지원한다.

1. MANDATORY :
    호출전에 트랜잭션이 반드시 존재해야 한다. 존재하지 않은경우 예외 방생

2. NESTED :
    호출되는 메소드에 이미 트랜잭션이 걸려 있는경우 중첩된 트랜잭션이 실행된다.
    중첩된 트랜잭션은 메인 트랜잭션에 독립적으로 Commit/Rollback 될 수 있다.
    메인 트랜잭션이 있는경우 --> 중첩 트랜잭션 생성
    메인 트랜잭션이 없는경우 --> REQUIRED와 동일하게 신규 생성함
    (# 참고 : 벤더 의존적, 지원안될 수 있음)

3. NEVER :
    트랜잭션이 없는 상태에서 메소드가 실행 되어야 한다.
    트랜잭션이 걸려 있다면 예외 발생.

4. SUPPORTED :
    트랜잭션이 없는 상황에서 실행되어야 한다.
    트랜잭션이 있다면, 트랜잭션이 종료될때까지 대기한다.

5. REQUIRED :
    트랜잭션 상황에서 실행 되어야한다.
    진행중인 트랜잭션이 있다면 진행중인 트랜잭션 내에서 실행된다.
    없다면 새로운 트랜잭션을 생성한다.

6. REQUIRED_NEW : 
    신규 트랜잭션 내에서만 실행이 되어야한다.
    이미 트랜잭션이 실행중이라면 종료될때 까지 대기한다.

7. SUPPORTS :
    진행중인 트랜잭션이 없어도 실행이 된다.
    진행중인 트랜잭션이 있다면 해당 트랜잭션 내에서 실행이 된다.

[zookeeper] 주키퍼는 뭐하는 놈일까?

Zookeeper : 
    - 오픈소스로 만들어진 분산된 어플리케이션을 위한 분산 코디네이션 서비스를 제공한다.
    - 즉, 주키퍼는 클라이언트가 서로 공유하는 데이터를 관리해주는 역할을 해준다.

분산 코디네이션 : 
    - 분산된 시스템 간에 동기화 서비스 제공, 공유자원의 관리를 수행하는 시스템
    - 분산코디네이션 시스템을 갖추기가 매우 어렵다. 에러를 검출하거나, 레이스 컨디션 및 데드락 상황을 파악하는 기능과 같은 어려운 작업을 해준다.

zookeeper의 특징 
1. Simple
    공유된 네임스페이스를 통해서 분산 코디네이션을 실현한다. 이러한 네임스페이스는 일반적인 파일 시스템과 유사하게 동작하여 단순함을 제공한다.
    name space는 znode라고 불리는 데이터 저장소로 구성되어 있다.
    이러한 네임스페이스는 in-memory에 저장되며, 빠른 처리 속도를 제공한다.

2. replicated
    ensemble라고 불리는 호스트 셋을 스스로 복제한다.
 

    주키퍼 서비스는 각각에 대해서 서로 알수 있도록 구성된다.
    이들은 상태값, 트랜잭션 로그, 저장소의 스냅샷 정보들을 상호 공유한다.
    클라이언트는 서버에 접속해서 요청을 보내거나, 응답을 받고, 이벤트를 watch하거나 heat beats를 전송한다. 서버와의 커넥션이 끊어지면 클라이언트는 다른 살아있는 서버로 접속을 시도한다.

3. ordered
    주키퍼 서버는 각각의 업데이트 결과를 모든 주키퍼 트랜잭션에 반영한다.
    이러한 순차적인 작업은 고수준 추상화로 구현되어 있다.

4. fast
    주키퍼는 읽기 성능이 매우 빠르다. 읽기와 쓰기의 비율은 10:1 의 수준이다.


zookeeper의 데이터 모델

네임스페이스는 일반적인 파일시스템과 매우 유사하다. 네임스페이스는 (/) 로 계층구조로 관리된다.

Node

주키퍼는 파일시스템처럼 보인다. 차이점이 있다면 각 노드는 데이터를 가지며, 이 노드는 역시 자식 노드들을 가질 수 있는 구조이다.
파일이 디렉토리도 될 수 있는 구조이다.

주키퍼는 이러한 노드에 다음과 같은 정보를 저장한다.
- 상태정보
- 설정정보
- 정보에 대한 위치정보

znode :
    일반적으로 주키퍼에 네임스페이스에 저장되는 노드를 말한다.
    주키퍼 데이터 노드라고도 한다.
    데이터 변경 버젼관리, ACL변경, 타임스템프, 캐시 검증, 업데이트된 내용의 코디네팅등 대한 상태값을 저장한다.
    클라이언트가 데이터를 참조할때 버젼 정보도 함께 내려주는 역할을 한다.

Ephermeral node :
    세션이 유지되는 동안 존재하는 노드이다.
    세션이 종료되면 이 znode는 제거된다.
 
Conditional updates and Watches
주키퍼는 watches에 대한 개념을 제공한다.
클라이언트는 watch를 znode에 설정할 수 있다.
watch는 znode의 변경에 대해서 트리거되거나, 제거될 수 있다.
watch가 트리거 되면 클라이언트는 znode의 변경사실에 대한 패킷을 수신받는다.

제공하는 기능 :
- Sequential Consistency : 클라이언트로 부터 없데이트가 발생하면, 순차적으로 전송한다.
- Atomicity : 성공 혹은 실패만 존재한다, 중간상태는 존재하지 않는다.
- Single System Image : 클라이언트는 서비스에 대한 동일한 뷰만 보게 된다.
- Reliability : 한번 업데이트가 되면클라이언트가 그 내용을 업데이트 하지 않는 이상 영원히 지속된다.
- Timeliness : 클라이언트는 시스템의 특정 업데이트된 시간에 대해서 뷰를 보장한다.

클라이언트 API : 
주키퍼는 다음과 같은 매우 단순한 인터페이스를 제공한다.
- create : 트리내에 노드를 생성한다.
- delete : 노드를 삭제한다.
- exists : 노드가 존재하는지 검사한다.
- get data : 노드로 부터 데이터를 읽어들인다.
- set data : 노드에 데이터를 저장한다.
- get children : 노드의 자식 리스트를 조회한다.
- sync : 데이터가 전파 되기를 기다린다.

주키퍼는 뭐하는놈일까?
주키퍼 Stand alone 설치하기
주키퍼 단일머신 멀티 인스턴스 설치하기

from : https://zookeeper.apache.org/doc/trunk/zookeeperOver.html

[Zookeeper] 설치 동일 장비에 멀티 인스턴스

[Zookeeper] 설치 동일 장비에 멀티 인스턴스
1. 주키퍼 다운로드 
- 아래 주소를 참조하자.
http://uncle-bae.blogspot.com/2016/02/zookeeper-standalone.html

2. 멀티 인스턴스를 위한 디렉토리 생성 
> mkdir -p /usr/unclebae/server1
> mkdir -p /usr/unclebae/server2
> mkdir -p /usr/unclebae/server3

3. 각 디렉토리에서 다운받은 주키퍼 tar를 복사한다. 
> cp zookeeperXXX.jar /usr/unclebae/server1
> cp zookeeperXXX.jar /usr/unclebae/server2
> cp zookeeperXXX.jar /usr/unclebae/server3

4. 주키퍼 압축 풀기 
> cd /usr/unclebae/server1
> tar -xvf zookeeperXXX.jar

5. 주키퍼를 위한 데이터 디렉토리 생성 및 클러스터 이름 설정 
> mkdir -p /usr/unclebae/server1/datas
> mkdir -p /usr/unclebae/server2/datas
> mkdir -p /usr/unclebae/server3/datas

> vim /usr/unclebae/server1/datas/myid
파일이 열리면 다음 정보를 입력한다.
나머지 2번, 3번 서버도 동일하게 작업한다.
2번서버는 2, 3번서버는 3으로 설정한다.

1

6. 주키퍼 설정 파일을 생성한다.
각각 디렉토리의 conf/zoo.cfg를 생성하여 다음 내용을 입력한다.
>vim /usr/unclebae/server1/zookeeper/conf/zoo.cfg

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/Users/naver/Documents/00.TOOLS/solr_cluster/server1/datas/zookeeper
dataLogDir=/Users/naver/Documents/00.TOOLS/solr_cluster/server1/datas/zookeeper/logs
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1=localhost:2888:3888
server.2=localhost:2889:3889
server.3=localhost:2890:3890

server1과 server2, server3은 clientPort를 다음과 같이 다르게 지정해야한다.
clientPort=2181
clientPort=2182
clientPort=2183

클라이언트 클러스터링은 server.1, server.2, server.3 으로 myid에 지정한 1, 2, 3이 들어오게 한다.


7. 클러스터 테스트하기. 
bin/zkCli.sh -server localhost:2181 로 1번 서버에 접속한다.
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
znode를 생성한다.

[zk: localhost:2181(CONNECTED) 2] create /test-node test
Created /test-node
노드 확인하기.

[zk: localhost:2181(CONNECTED) 3] ls /
[test-node, zookeeper]

2번서버에도 zookeeper클라이언트로 접속하기.
bin/zkCli.sh -server localhost:2182로 서버에 접근한다.

[zk: localhost:2182(CONNECTED) 3] ls /
[test-node, zookeeper]

2번 서버에서도 1번서버에 생성한 test-node가 보인다. (즉, 복제가 된 것이다. )

주키퍼가 정상으로 설치 되었음을 확인한다.


주키퍼는 뭐하는놈일까?
주키퍼 Stand alone 설치하기
주키퍼 단일머신 멀티 인스턴스 설치하기





[Zookeeper] 설치 StandAlone

[Zookeeper] 설치 StandAlone
1. Zookeeper 다운로드 받기 
http://zookeeper.apache.org/releases.html

2. zookeeper 디렉토리를 만들고 해당 tar 파일 풀기. 
> tar -xvf zookeeperXXX.tar

3. Standalone 버젼 설치 
Standalone버젼은 단순히 conf/zoo.cfg 파일을 생성하고 다음 내용을 추가하면 된다.

tickTime=2000
dataDir=/var/lib/zookeeper
clientPort=2181
- tickTime :
    millisecond 단위의 시간이다.
    heartbeat과 최소 세션 타임아웃 시간으로 사용된다.
- dataDir :
    in-memory 데이터베이스 스냅샷을 저장하는 위치이다.
    지정하지 않는경우 메모리에 트랜잭션 업데이트 로그를 저장하게 된다.
- clientPort :
    클라이언트 접속을 Listen하는 포트

4. Zookeeper 실행하기.
> bin/zkServer.sh start

# 알아둘것 : 
zookeeper 스탠드얼론은 replication 을 하지 않는다. 그러므로 zookeeper 프로세스가 실패되면 서버가 다운로드 된다.
그러면 zookeeper가 관리하는 모든 클러스터 노드들은 동작하지 않는다.

5. Zookeeper에 접근하여 몇가지 작업 해보기 
5.1 Zookeeper에 접근하기
> bin/zkCli.sh -server 127.0.0.1:2181
5.2 help 명령
[zkshell: 0] help
ZooKeeper host:port cmd args
get path [watch]
ls path [watch]
set path data [version]
delquota [-n|-b] path
quit
printwatches on|off
create path data acl
stat path [watch]
listquota path
history
setAcl path acl
getAcl path
sync path
redo cmdno
addauth scheme auth
delete path [version]
deleteall path
setquota -n|-b val path

5.3 ls /
[zkshell: 8] ls /
[zookeeper]

5.4 znode생성해보기
[zkshell: 9] create /zk_test my_data
Created /zk_test

5.5 ls /
[zkshell: 11] ls /
[zookeeper, zk_test]

5.6 get /zk_test
[zkshell: 12] get /zk_test
my_data
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 5
mtime = Fri Jun 05 13:57:06 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0
dataLength = 7
numChildren = 0

5.7 zk_test 내의 스트링을 my_data --> junk로 바꾸기
[zkshell: 14] set /zk_test junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0
[zkshell: 15] get /zk_test
junk
cZxid = 5
ctime = Fri Jun 05 13:57:06 PDT 2009
mZxid = 6
mtime = Fri Jun 05 14:01:52 PDT 2009
pZxid = 5
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0
dataLength = 4
numChildren = 0

5.8 znode delete하기
[zkshell: 16] delete /zk_test
[zkshell: 17] ls /
[zookeeper]
[zkshell: 18]


주키퍼는 뭐하는놈일까?
주키퍼 Stand alone 설치하기
주키퍼 단일머신 멀티 인스턴스 설치하기


[ 자바] 이미지해싱하기

[ 자바] 이미지해싱하기

package com.unclebae.image.hash;

import java.io.*;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class ImageHash {

    public static final String HASHING_MD5 = "MD5";

    public String hashing(String imagePath) {

        if (imagePath == null) {
            return null;
        }

        MessageDigest md = null;

        try {
            md = MessageDigest.getInstance(HASHING_MD5);
        } catch (NoSuchAlgorithmException e) {
            System.out.printf("There is not hasing algorithm.");
            return null;
        }

        byte[] bytes = new byte[1024];
        int readBytes = 0;

        StringBuffer sb = new StringBuffer();
        try {
            InputStream resourceAsStream = new BufferedInputStream(new FileInputStream(new File(imagePath)));
            while((readBytes = resourceAsStream.read(bytes)) != -1) {
                md.update(bytes, 0, readBytes);
            }

            byte[] mdBytes = md.digest();

            for (byte bt : mdBytes) {
                sb.append(Integer.toString((bt & 0xff) + 0x100, 16).substring(1));
            }

            resourceAsStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }

        return sb.toString();
    }

    public static void main(String[] args) {
        ImageHash hash = new ImageHash();
        String hashing = hash.hashing("/Users/kido/Documents/사진/01.jpg");
       
        System.out.println("Hash Result : " + hashing);
    }
}