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

argo-workflow parameter json escape

# argo-workflow parameter 로 json 형태를 전달 받았을떄
# single quotation 으로 감싸지 않으면 " escape 가 되지 않는다.

# test 
# argo worfklow version: 3.4.4
# workflow
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: ysoftman-test
  namespace: ysoftman-workflow
spec:
  serviceAccountName: workflow-template
  entrypoint: ysoftman
  templates:
    - name: ysoftman
      steps:
        - - name: ysoftman
            template: print-data
            arguments:
              parameters:
                - name: data1
                  value: "{\"a\":\"apple     lemon\"}"
                - name: data2
                  value: '{"b":"banana"}'

    - name: print-data
      inputs:
        parameters:
          - name: data1
          - name: data2
      script:
        image: "alpine"
        command: [sh]
        source: |
          echo '{{inputs.parameters.data1}}'
          echo '{{inputs.parameters.data2}}'
          echo '{{inputs.parameters}}'
          # invalid JSON 
          echo "{{inputs.parameters.data1}}"
          echo "{{inputs.parameters.data2}}"
          echo "{{inputs.parameters}}"
          # invalid JSON 
          echo {{inputs.parameters.data1}}
          echo {{inputs.parameters.data2}}
          echo {{inputs.parameters}}
          sleep 1000

# workflow pod log 결과
{"a":"apple     lemon"}
{"b":"banana"}
[{"name":"data1","value":"{\"a\":\"apple     lemon\"}"},{"name":"data2","value":"{\"b\":\"banana\"}"}]
{a:apple lemon}
{b:banana}
[{name:data1,value:{"a":"apple lemon"}},{name:data2,value:{"b":"banana"}}]
{a:apple     lemon}
{b:banana}
[{name:data1,value:{"a":"apple     lemon"}},{name:data2,value:{"b":"banana"}}]

#####

# data3 의 값이 json 이고 필드값으로 yaml, xml 등이 escaped 로 된 복잡한 파라메터인 경우 다음과 같이 처리해도 올바른 JSON 으로 출력되지 않는다.
echo '{{inputs.parameters.data3}}' # /argo/staging/script 에러
echo {{inputs.parameters.data3}} # " 가 빠진 invalid JSON
echo -e {{inputs.parameters.data3}} # "가 빠지고 \n 등에서 /argo/staging/script 에러

# jq 가 포함된 이지미를 사용해 script 에 다음과 같이 환경변수를 파싱해서 사용했다.
echo "$ARGO_TEMPLATE" | jq -r '.inputs.parameters[] | select(.name=="data3").value' | jq -r .workflow_yaml > /tmp/data.yaml

pypi json response

# pip 대신 curl 등으로 pypi 저장소에 올라온 특정 패키지 리스트를 얻을 수 있다.
# https://pypi.org/simple/{패키지명}/

# 그런데 html 응답이다.
# 파싱이 용이한 json 응답을 받고 싶을때는 다음과 같이 요청하면 된다.
# https://pypi.org/pypi/{패키지명}/json

# pypi api reference

JSON number type range

# json number 타입의 값이 커지면 사용하는 프로그램에 따라 값이 달라 질 수 있다.
# 다음과 같은 json_sample.json 이 있을때,
{
    "strval": "ysoftman",
    "intval1": -123456789123456789,
    "intval2": 123456789123456789,
    "intval3": 123456789123456789123456789123456789,
    "floatval1": -1.123456789123456789,
    "floatval2": 1.123456789123456789123456789,
    "floatval3": 1.123456789123456789123456789123456789
}
# JSON number 스펙을 보면 범위에 제한은 없지만
# JSON 을 사용하는 대부분의 프로그램이 IEEE754 64bit 의 범위 제한이 있다.
IEEE754 64bit 표준에 따라

# 2^64(9223372036854775808 ~ 9223372036854775807) 까지 표시할 수 있다.
# 이 범위를 넘어가면 int 타입은 0, float 타입은 범위 내까지만 표현된다.
{
    StrVal: "ysoftman",
    IntVal1: -123456789123456789,
    IntVal2: 123456789123456789,
    IntVal3: 0,
    FloatVal1: -1.1234567891234568,
    FloatVal2: 1.1234567891234568,
    FloatVal3: 1.1234567891234568
}

# jq 도 float 타입은 64bit 범위 까지만 지원한다.
# man jq : jq currently only has IEEE754 double-precision (64-bit) floating point number support 
# 하지만 정수형은 지수 형태로 최대한 표현된다.
# jq  . ./json_sample.json
{
  "strval": "ysoftman",
  "intval1": -123456789123456780,
  "intval2": 123456789123456780,
  "intval3": 1.2345678912345678e+35,
  "floatval1": -1.1234567891234568,
  "floatval2": 1.1234567891234568,
  "floatval3": 1.1234567891234568
}

# javascript JSON.parse() 도 jq 와 같은 결과
floatval1: -1.1234567891234568
floatval2: 1.1234567891234568
floatval3: 1.1234567891234568
intval1: -123456789123456780
intval2: 123456789123456780
intval3: 1.2345678912345678e+35
strval: "ysoftman"

redis cluster in kubernetes

# kubernetes(k8s) 노드가 다음과 같이 구성되어 있다고 가정하고 설치한다.
1 maser
3 worker

# 참고
https://kubernetes.io/ko/docs/concepts/workloads/controllers/statefulset/
https://kubernetes.io/ko/docs/tutorials/configuration/configure-redis-using-configmap/
https://github.com/sanderploegsma/redis-cluster


# redis-cluster.yaml 내용
apiVersion: v1
kind: Namespace
metadata:
  name: redis-cluster
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster
  labels:
    app: redis-cluster
data:
  fix-ip.sh: |
    #!/bin/sh
    CLUSTER_CONFIG="/data/nodes.conf"
    if [ -f ${CLUSTER_CONFIG} ]; then
      if [ -z "${POD_IP}" ]; then
        echo "Unable to determine Pod IP address!"
        exit 1
      fi
      echo "Updating my IP to ${POD_IP} in ${CLUSTER_CONFIG}"
      sed -i.bak -e "/myself/ s/[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/${POD_IP}/" ${CLUSTER_CONFIG}
    fi
    exec "$@"
  # | (newline 유지하는 멀티라인)
  # + (마지막 newline 유지)
  redis.conf: |+
    cluster-enabled yes
    cluster-require-full-coverage no
    cluster-node-timeout 15000
    cluster-config-file /data/nodes.conf
    cluster-migration-barrier 1
    appendonly no
    save ""
    protected-mode no
    requirepass "password123"
    masterauth "password123"

---

apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
  labels:
    app: redis-cluster
spec:
  ports:
  - port: 6379
    targetPort: 6379
    name: client
  - port: 16379
    targetPort: 16379
    name: gossip
  # clusterIP 로 k8s 클러스터내부에서만 접근 가능한 Service(pod묶음)을 제공하자.
  type: clusterIP
  # clusterIP 를 명시하지 않으면 Service 시작시 IP 가 자동할당된다.
  #clusterIP: None
  clusterIP: "10.10.10.123"
  selector:
    app: redis-cluster
---
# StatefulSet 은 Pod 집합인 Deployment 와 스케일
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  labels:
    app: redis-cluster
spec:
  serviceName: redis-cluster
  replicas: 4
  selector:
    matchLabels:
      app: redis-cluster
  template:
    metadata:
      labels:
        app: redis-cluster
    spec:
      containers:
      - name: redis
        image: redis:6.2-rc
        args: ["--requirepass", "password123"]
        ports:
        - containerPort: 6379
          name: client
        - containerPort: 16379
          name: gossip
        command: ["/conf/fix-ip.sh", "redis-server", "/conf/redis.conf"]
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - "redis-cli -h $(hostname) ping"
          initialDelaySeconds: 15
          timeoutSeconds: 5
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - "redis-cli -h $(hostname) ping"
          initialDelaySeconds: 20
          periodSeconds: 3
        env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        volumeMounts:
        - name: conf
          mountPath: /conf
          readOnly: false
        - name: data
          mountPath: /data
          readOnly: false
      volumes:
      - name: conf
        configMap:
          name: redis-cluster
          defaultMode: 0755
  volumeClaimTemplates:  #  PersistentVolumesClaims(PVC) 100MiB 요청(생성)해서 pod 가 내려가도 데이터는 유지될 수 있도록 한다.
  - metadata:
      name: data
      labels:
        name: redis-cluster
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Mi

# redis 클러스터 master, worker, statefulset, service 생성
kubectl apply -f redis-cluser.yaml

# configmap, statefulset, service 확인
kubectl describe cm --namespace redis-cluster
kubectl describe sts --namespace redis-cluster
kubectl describe svc --namespace redis-cluster

# statefulset 에서 PersistentVolumeClaim(PVC) 상태 확인
kubectl get pvc --namespace redis-cluster

# POD 및 서비스 상태 확인
kubectl get all --namespace redis-cluster

# 클러스터링 구성
# redis5 부터 redis-cli 에서 redis-trib.rb 의 기능을 사용할 수 있다.
# redis 클러스터 명령 참고
redis-cli --cluster help

# redis 동작중인 pod 파악
kubectl get pods --namespace redis-cluster | grep redis | awk '{print $1}' | head -1

# jsonpath output 을 app=redis 인 pod 들의 IP 파악
# 참고 https://kubernetes.io/docs/reference/kubectl/jsonpath/
kubectl get pods --namespace redis-cluster -l app=redis-cluster -o jsonpath='{range .items[*]}{.status.podIP}{":6379 "}{end}'

# pod ip:port 를 옵션으로 주어 클러스터링을 구성한다.
# cluster-replicas 복제(슬레이브) 개수 4개의 노드라면 2개 마스터, 2개 슬레이브가 된다.
kubectl --namespace redis-cluster \
exec -it redis-cluster-0 -- \
redis-cli --cluster create --cluster-replicas 1 -a "password123" \
$(kubectl --namespace redis-cluster get pods -l app=redis-cluster -o jsonpath='{range .items[*]}{.status.podIP}{":6379 "}{end}')
# Can I set the above configuration? (type 'yes' to accept): yes 입력

# redis cluster info 확인
kubectl --namespace redis-cluster exec -it redis-cluster-0 -- redis-cli -a "password123" cluster info

# redis cluster node 확인
kubectl --namespace redis-cluster exec -it redis-cluster-0 -- redis-cli -a "password123" -c cluster nodes

# redis-cluster-0 파드에서 redis-cli 로 clusterIP(고정) 에 접속해 테스트
kubectl --namespace redis-cluster exec -it redis-cluster-0 -- redis-cli -h 10.10.10.123 -p 6379 -c -a "password123"
10.10.10.123:6379> set aaa lemon
OK
10.10.10.123:6379> get aaa
"lemon"
10.10.10.123:6379> set bbb apple
-> Redirected to slot [5287] located at 10.10.123.100: 6379
OK
10.10.123.100:6379> get bbb
"apple"


####


# 노드 변경이 필요한 경우
# replicas=6 로 노드(pod) 6개로 늘린다.
# 기존보다 작으면 줄어든다. 줄일때는 노드 제거후 적용
kubectl --namespace redis-cluster scale statefulset redis-cluster --replicas=6

# 2추가된 노드에
# 10.10.10.10:6379 기존 존재하는 클러스터 노드에 마스터 노드 추가
kubectl --namespace redis-cluster \
exec -it redis-cluster-0 -- \
redis-cli -a "password123" --cluster add-node 10.10.10.11:6379 10.10.10.10:6379

# 10.10.10.11:6379 마스터의 슬레이브가 추가
kubectl --namespace redis-cluster \
exec -it redis-cluster-0 -- \
redis-cli -a "password123" --cluster add-node 10.10.10.12:6379 10.10.10.11:6379 --cluster-slave

# 슬롯 재분배
# 새 마스터 노드가 추가 된경우 --cluster-use-empty-masters 사용
kubectl --namespace redis-cluster \
exec -it redis-cluster-0 -- \
redis-cli -a "password123" --cluster rebalance 10.10.10.10:6379 --cluster-use-empty-masters

# 노드 빼는 경우(10.10.10.10:6379 노드에 접속해서 aaaaabbbbb 노드들 삭제)
kubectl --namespace redis-cluster \
exec -it redis-clustqer-0 -- \
redis-cli -a "password123" --cluster del-node 10.10.10.12:6379 aaaaabbbbb


####


# confimap 삭제
kubectl delete cm redis-cluster --namespace redis-cluster

# PersistentVolumeClaim(PVC) 삭제
kubectl delete sts redis-cluster --namespace redis-cluster

# pvc 삭제
# kubectl get pvc 로 볼륨이름 파악
kubectl delete pvc 볼륨이름 --namespace redis-cluster
# 또는 전체 삭제하는 경우
kubectl delete pvc --all --namespace redis-cluster

# service 모두 삭제
kubectl delete service --all --namespace redis-cluster

# pod 모두 삭제
kubectl delete pods --all --namespace redis-cluster

# unknown state pod 가 삭제 안되는 경우
kubectl delete pods --all --grace-period=0 --force --wait=false --namespace redis-cluster

# 네임스페이의 모든 리소스 삭제(단 secret,configmap,roels등과 같은 특정 리소스는 명시적으로 삭제해야 한다.)
# all=pods,deployments,rs 등을 의미한다.
kubectl delete all --all --namespace redis-cluster

# namespace 삭제
kubectl delete ns redis-cluster

jq command

# 커맨드 라인으로 json data 를 grep 할때 jq 를 사용하면 편하다.

# 맥에서 설치
brew install jq

# centos 에서 설치
yum install jq

# jq 를 이용한 json data grep
# 다음 test.json 있을때
cat > test.json << zzz
{
  "name": "bundling",
  "version": "1.0.0",
  "description": "테스트",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack --watch",
    "build": "webpack -p"
  },
  "keywords": ["lemon", "orange", "apple"],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "webpack": "^3.10.0"
  },
  "aaa-bbb": "hypen-test",
  "aaa.bbb": "ccc",
  "aaa": { "bbb.ccc" : "ddd"},
  "arrayobj" : [
    {"name":"lemon", "price":200, "desc":"lemon_desc" },
    {"name":"apple", "price":300, "desc":"apple_desc" },
    {"name":"orange", "price":100, "desc":"orange_desc" }
  ]
}
zzz

# json 보기
jq . test.json

# json 여부 판단하기
# object, array 면 json
# number, string 등이면 json 이 아닌것으로 판단
jq type test.json

# script object 가져오기
jq .scripts test.json

# cat 과 파이프를 사용해도 된다.
# script object 가져오기
cat test.json | jq .scripts

# 키 이름만 가져오기
jq 'keys' test.json

# dependencies 아래 키 이름만 가져오기
jq '.dependencies|keys' test.json

# script.start 키 값 가져오기
jq .scripts.start test.json

# -r(--raw-output)을 사용하면 "aaa" -> aaa 로 "제거
jq -r .scripts.start test.json

# script 의 start 와 build 필드 값 가져오기
jq '.scripts | "\(.start) \(.build)"'  test.json

# keywords arrary 가져오기
jq .keywords test.json

# keywords 두번째 값 가져오기
jq ".keywords[1]" test.json

# keywords 0,1 원소 가져오기
jq ".keywords[:2]" test.json

# keywords 마지막 원소 가져오기
jq ".keywords[-1]" test.json

# keywords 값 순회하기
jq ".keywords[]" test.json

# keywords 원소 개수
jq ".keywords | length"  test.json

# keywords 와 arrayobj의 name 가져오기
jq '.keywords, .arrayobj[].name' test.json

# keywords 는 AA 필드명의 값으로 하는 오브젝트 와 arrayobj의 name은 BB 필드명의 값으로 해서 가져오기
jq '{"AA":.keywords}, {"BB":.arrayobj[].name}' test.json 

# AA 와 BB 를 하나의 오브젝트로 가져오기
jq '{"AA":.keywords, "BB":.arrayobj[].desc}' test.json

# 쉘 변수는 '$변수' 로 사용
var1="ysoftman"; jq '{"AA":.keywords, "BB":.arrayobj[].desc, "CC":"'${var1}'"}' test.json

# name 필드로 정렬(알파벳 오른 차순)
jq '.arrayobj | sort_by(.name)' test.json

# price 필드로 정렬(숫자 오름 차순)
jq '.arrayobj | sort_by(.price)' test.json

# sort_by 의 입력은 [](배열)이어야 한다.
# 입력 json 이 [] 아니라면 -s(--slurp)로 array 변경해서 처리한다.
jq '.arrayobj[]' test.json | jq -s 'sort_by(.price)'  

# 필드명에 . - 등이 있는 경우 ""안에 넣어야 한다.
# 참고로 https://jsonapi.org/format/#document-member-names 을 보면 . 은 필드명을 쓰지 말라고 한다.
jq '."aaa-bbb"' test.json
jq '."aaa.bbb"' test.json
jq '.aaa["bbb.ccc"]' test.json

# 오브젝트(mylist) 리스트 중 특정 필드(name)만 가져오기
jq ".mylist[]".name

# array 요소 중 name 필드값이 특정값인 경우만 가져오기
jq '.arrayobj[] | select(.name == "orange")' test.json

# array 요소 중 name 필드값이 "l" 이 포함된 경우만 가져오기
jq '.arrayobj[] | select(.name | contains ("l"))' test.json

# array 요소 중 name 필드값이 "l" 이 포함 안된 경우만 가져오기
jq '.arrayobj[] | select(.name | contains ("l") | not)' test.json

# addobj 추가하기
jq '. + {"addobj": {"field1": "added_field1", "field2": "added_field2"}}' test.json > test2.json

# author 와 main 필드 값 변경하기
jq '.author="ysoftman" | .main="main.js"' test.json > test2.json

# test2.json 에서 addobj.field2 삭제하기
jq 'del(.addobj.field1)' test2.json

# object list 만들기
echo '[]' | jq '.+[{"a":"aaa","a1":111},{"b":"bbb","b1":222}]'

#####

# mjson 으로 json pretty(indent,들여쓰기) 하기
# mjson 설치
sudo pip install mjson

# 들여쓰기 형태로 보기
echo '{"a":1,"b":2}' | mjson

#####

# jq-1.6 에서 다음과 같이 .[]로 사용하면 문법에러가 발생한다.
cat out.json | jq -r '.status.nodes.[]'
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.aaa.[]
jq: 1 compile error

# jq-1.6 에서는 다음과 같이 . 없이 사용해야 에러가 발생하지 않는다.
cat out.json | jq -r '.status.node[]'

# 참고로 jq-1.7.1 로 다운받아 실행하면 아래 2가지 방식 모두 된다.
wget https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux64
cat out.json | ./jq-linux64 -r '.status.nodes[]'
cat out.json | ./jq-linux64 -r '.status.nodes.[]'

#####

# interactive json viewer
# jq 쿼리문을 테스트할때 유용하다.

LogStash 사용하기

LogStash 는 Java 기반의 오픈소소 툴로 구조화되지 않은 일반 로그 데이터를 특정 필터로 가공하여 ElasticSearch 와 같은 검색 시스템에 전송해주는 일종의 로그 수집기다.
input - filter - output 의 파이프 라인 구조로 플러그인을 통해 다양한 데이터 가공 및 입출력이 가능하다.

# 설치
# Java(JDK or JRE) 설치가 되어 있어야 한다.
# 다운로드 후 압축 풀기
# https://www.elastic.co/downloads/logstash

# 윈도우 기준 설명
# 설정을 커맨드에 명시하여 실행하는 경우
# 표준 입력으로 데이터를 입력 받아 필터없이 표준 출력으로 데이터를 출력하는 설정
bin\logstash.bat -e 'input { stdin {} } output { stdout {} }'

# 설정 파일 만들기
vim logstash.conf
input {
# 파일 내용이 변경되는 경우
# file 의 필드 별 설정(@version 및 @timestamp 필드는 기본 적용)
file {
# type 필드 => 정해진 값은 없고 정해서 사용하면 됨
type => "textlog"

# tag 필드 => 태그를 달 수 있다.
tags => ["tag1", "tag2", "tag3"]

# 커스텀 필드를 추가 할 수 있다.
# hash(key=>value 형태)
add_field => {
"name" => "mypc"
"ip" => "127.0.0.1"
}

# path 필드 => 로그 파일이 있는 절대 경로 명시
path => "C:/ysoftman/*.log"

# 파일 처음부터 변경 부분 검색(디폴트 end)
start_position => "beginning"

# 파일 상태 체크 주기 설정 (디폴트1초)
stat_interval => 1

# 1시간으로 이전 수정된 파일은 수집에서 제외 (디폴트 86400 (하루))
ignore_older => 3600

# 인코딩 명시(기본 UTF-8 로 취급)
codec => plain {
charset => "EUC-KR"
}
}
}

filter {
grok {
# 메시지 필드에 test 나 testing 스트링이 있다면
match => { "message" => ["test" , "testing"] }

# 위 조건이 참이면 ysoftman 태그 추가
# 위 조건에 맞지 않으면 _grokparsefailure 태그가 자동으로 추가된다.
add_tag => [ "ysoftman" ]
}

# _grokparsefailure 태그가 있다면 drop (output 으로 전달되지 않는다.)
#if "_grokparsefailure" in [tags] {
# drop {}
#}

# _grokparsefailure 태그만 지우기
mutate {
remove_tag => ["_grokparsefailure"]
}
}

output {
# elasticsearch 서버의 주소 명시
elasticsearch {
# 해당 호스트로 전송
hosts => ["localhost:9200"]
}
# 디버깅을 위해 표준 출력 표시
stdout {
# rubydebug 형식의 보기 좋은 json 포맷으로 표시
codec => rubydebug
}
}


# 설정 파일 사용하여 실행하는 경우
bin\logstash.bat agent -f logstash.conf

# 이제 지정 경로의 파일에 변화가 있다면 변경된 내용이 elasticsearch 전송되고, 콘솔에 다음과 같이 출력된다.
{
       "message" => "ysoftman test message...\r",
      "@version" => "1",
    "@timestamp" => "2016-06-01T07:32:46.249Z",
          "path" => "C:/ysoftman/ysoftman.log",
          "host" => "ysoftman",
          "type" => "textlog",
        "name" => "mypc",
              "ip" => "127.0.0.1",
          "tags" => [
        [0] "tag1",
        [1] "tag2",
        [2] "tag3",
        [3] "ysoftman"
    ]
}

# ElasticSearch(Kibana) 를 통해 추가된 로그 확인해보기
http://localhost:5601

# 플러그인 관련
# 설치된 플러그인 버전정보 보기
bin\plugin.bat list --verbose

# 설치된 플러그인 모두 업데이트(잘못되면 logstash 다시 설치해야함)
bin\plugin.bat update

# 예) file 플러그인 설치하기
bin\plugin.bat install logstash-input-file

참고
https://www.elastic.co/guide/en/logstash/current/config-examples.html
https://www.elastic.co/guide/en/logstash/current/plugins-inputs-file.html
https://www.elastic.co/guide/en/logstash/current/plugins-filters-grok.html#plugins-filters-grok-match
https://www.elastic.co/guide/en/logstash/current/plugins-filters-drop.html
https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html

ElasticSearch 과 Kibana 사용하기

ElasticSearch 는 Java 로 만든 Apache Lucene(루씬)을 기반으로한 분산 검색엔진이다.
데이터를 JSON 형식으로 저장하여 스키마 프리하며 확장이 용이하며 검색 기능이 꽤 강력하여 여러곳에서 사용되고 있다.
Kibana 는 ElasticSearch 를 쉽게 사용할 수 있도록 도와주는 일종의 시각화 도구이다.

##########

# ElasticSearch 설치
# 기본적으로 Java 로 만든 루씬을 사용하기 때문에 Java 실행 환경이 우선되어야 한다.
# JAVA_HOME 환경 변수가 등록되어 있는지 확인하고 없으면 JDK 를 설치하자.
# https://www.elastic.co/downloads/elasticsearch  다운로드 후 압축만 풀어 사용하면 된다.
# Elastic 시리즈의 다른 제품도 많은데 ElasticSearch 와 연동하기 쉽다.
# windows에서는 elasticsearch-2.3.3.zip 기준
# 커맨드라인으로 서버 실행하기
bin\elasticsearch.bat
# 커맨드라인으로 실행하면 다음과 같이 자바 프로세스가 수행된다.
"c:\Program Files\Java\jdk1.7.0_21\bin\java"   -Xms256m -Xmx1g -Djava.awt.headless=true -XX:+UseCMSInitiatingOccupancyOnly -XX:+HeapDumpOnOutOfMemoryError -XX:+DisableExplicitGC -Dfile.encoding=UTF-8 -Djna.nosys=true  -Delasticsearch -Des-foreground=yes -Des.path.home="C:\elasticsearch-2.3.3" -cp "C:\elasticsearch-2.3.3/lib/elasticsearch-2.3.3.jar;C:\elasticsearch-2.3.3/ㅁlib/*" "org.elasticsearch.bootstrap.Elasticsearch" start
# 윈도우 서비스로 등록하기(삭제는 remove 옵션)
bin\service.bat install
# 서비스로 서버를 시작하면 다음과 같은 프로세스가 수행된다.
elasticsearch-service-x64.exe

# osx 에서는
brew install elasticsearch
brew services start elasticsearch

# centos 에서는(5.2.2 기준, java 필요시 yum install java)
curl -O "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.2.tar.gz"
tar zxvf elasticsearch-5.2.2.tar.gz
# restart
cat elasticsearch.pid | xargs kill
./elasticsearch-5.2.2/bin/elasticsearch -d -p elasticsearch.pid

# 설정 파일 수정
vi config\elasticsearch.yml
# osx 에서는 (brew info elasticsearch 로 config 경로 확인)
vi /usr/local/etc/elasticsearch/elasticsearch.yml
cluster.name: ysoftman-cluster1
network.host: 10.10.10.10
http.port: 9200

# 서버 확인
# 다음과 같이 접속해보면 json 형식으로 클러스터명과 버전을 확인할 수 있다.
http://10.10.10.10:9200/

# 플러그인 설치(centos 에서는 bin/elasticsearch-plugin 사용)
plugin.bat install --verbose analysis-icu
# elasticsearch 2.3.3 버전에서 아래 플러그인이 지원되지 않아 skip
#plugin.bat install --verbose Aconex/elasticsearch-head
#plugin.bat install --verbose lukas-vlcek/bigdesk

# 설치된 플러그인 리스트
plugin.bat list

##########

# Kibana 설치
# windows 에서는
https://www.elastic.co/downloads/kibana 다운로드 후 압축풀어 사용한다.

# 설정 파일
vi config/kibana.yml
# osx 에서는 (brew info kibana 로 config 경로 확인)
vi /usr/local/etc/kibana/kibana.yml
server.port: 5601
server.host: "10.10.10.11"
elasticsearch.url: "http://10.10.10.10:9200"

# 시작(ElasticSearch 디폴트 10.10.10.10:9200 로 연결)
bin\kibana.bat

# osx 에서는
brew install kibana
brew services start kibana

# centos 에서는(5.2.2 기준)
curl -O "https://artifacts.elastic.co/downloads/kibana/kibana-5.2.2-linux-x86_64.tar.gz"
tar zxvf kibana-5.2.2-linux-x86_64.tar.gz

# 혹시 열려 있는 kibana 프로세스 확인
ps -ef | grep '.*node/bin/node.*src/cli'

# restart(daemon 설치 포스트 참고)
daemon --name=kibana --pidfile="/home/ysoftman/kibana.pid" --stop
daemon --name=kibana --pidfile="/home/ysoftman/kibana.pid" --chdir="/home/ysoftman" --  "./kibana-5.2.2-linux-x86_64/bin/kibana"

# kibana 확인
http://10.10.10.11:5601/

# 추후 logstash 로 유입된 로그 데이터를 검색(Discover->검색명령)할 수 있다.
# elasticsearch 는
# DSL(Domain Specific Language)의 json 형태의 쿼리로 검색할 수 있고
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

# lucene 쿼리로도 검색할 수 있다.
https://www.elastic.co/guide/en/kibana/current/lucene-query.html

# 예제
# AND, OR, NOT 은 대문자로 써야하고 각각은 && || ! 로 쓸 수 있다.
# http.response.code 필드가 존재하고, 값은 200,204,302가 아닌것들 검색
(_exists_:http.response.code) AND NOT(http.response.code:200) AND NOT(http.response.code:204) AND NOT(http.response.code:302)

##########

# 테스트 해보기
# curl 바이러리 다운로드(윈도우 기준)
https://bintray.com/artifact/download/vszakats/generic/curl-7.49.0-win32-mingw.7z

# 환경변수 추가(윈도우 기준)
PATH=%PATH%;C:\curl-7.49.0-win32-mingw\bin

# 문서 추가(생성)
# 리눅스는 옵션값에 quote(')를 사용하지만 윈도우는 doublequote(")를 사용해야 한다.
curl -X PUT http://10.10.10.10:9200/2016-05-27/ysoftman/doc1 -d "
{
"no\":123456,
"name\":\"ysoftman\",
"etc\":\"melong\"
}
"

# 문서 조회(curl 대신 브라우저 URL 로 요청해도 된다.)
curl -X GET http://10.10.10.10:9200/2016-05-27/ysoftman/doc1

# 문서 검색(curl 대신 브라우저 URL 로 요청해도 된다.)
curl -X GET http://10.10.10.10:9200/2016-05-27/ysoftman/_search?q=name:ysoftman

# 문서 삭제
curl -X DELETE http://10.10.10.10:9200/2016-05-27/ysoftman/doc1

# 참고
https://www.elastic.co/downloads/elasticsearch
https://www.elastic.co/guide/en/elasticsearch/plugins/2.3/plugin-management.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html
https://curl.haxx.se/docs/httpscripting.html#Modify_method_and_headers
http://d2.naver.com/helloworld/273788

C++ JSON Library BenchMark

C++ 용 JSON 라이브러를 벤치마크한 블로그
http://lijoblogs.blogspot.com/2011/11/comparison-and-benchmark-of-c-json.html

C/C++ test

# loop

# 한글 utf-8 출력

# memset

# malloc() 과 calloc() 의 차이

# fopen의 text모드와 binary모드 차이

# STL int string 변환 

# switch 문안에서 변수선언과 동시에 초기화

# 한글 완성형 글자 출력하기

# bit field 테스트

# casting

# Windows 에서 32bit, 64bit 메모리 할당

# 정수형 상수 오버플로우

# 전위,후위 증(감) 연산

# libcurl test

# libjson test

# jsoncpp library 테스트

# linux RWLock test

# 한글 utf-8 출력

# time test

# string 스트림 사용시 첫번째 바이트가 \t \n \r 등 특수문자인 경우 빠지는 문제

# URL 인코딩/디코딩

# linux function test

# 정적 인스턴스와 동적 인스턴스의 차이

# C++ 미리 정의된 매크로

# 파일 헤더로 Unicode(utf-16) 와 utf-8 구분하기

# float, double 과 같은 부동소수점 타입 연산시 유의 사항


# random test

# 실인수(argument) 와 가인수(parameter) 구분

# strtok() 함수를 이용한 연속 토큰 추출

# Linux fork() 를 이용한 데몬 프로그램

# swap 방법들