confluent/etc/kafka 의 server.properties 를

server_01.properties, server_02.properties, server_03.properties 형식으로 복사 후

broker id 변경, 접속 주소 변경, kafka 로그 저장 주소 변경

broker.id = {인식숫자} 1, 2, 3, 4 같이 순번으로

listeners=PLAINTEXT://0.0.0.0:9092    / 0.0.0.0:9093    / 0.0.0.0:9094 형식으로 (외부/내부 접속 가능)

내부만 접속 시 localhost:9092 / localhost:9093 / localhost:9094

advertied.listeners=PLAINTEXT://{ec2 DNS}:9092 / 9093 / 9094

log.dirs=/home/ubuntu/kafka-logs-01 / 02 / 03

으로 변경

 

실행은 각각 실행

ex) confluent/bin/kafka-server-start confluent/etc/kafka/server.properties <- 위의 파일 순번대로

 

 

멀티 브로커 사용시 zookeeper.properties 그대로 사용하지 말고 zookeeper의 dataDir를 별도 구성  

'연구개발 > Kafka' 카테고리의 다른 글

Kafka ec2 외부 연결  (0) 2023.10.05

Java Source 상에는 ec2 의 외부 접속 아이피를 적용

예) 15.164.90.79:9092

 

 

ec2 내부와 외부를 모두 사용하기 위해서는

ec2 의 kafka 폴더의 etc 안 kafka 폴더에서 server.properties 

listeners=PLAINTEXT://0.0.0.0:9092

advertised.listener=PLAINTEXT://{여기에 ec2의 dns 주소를 쓰고}:9092

 

하면 끝..

 

'연구개발 > Kafka' 카테고리의 다른 글

kafka multi broker  (0) 2023.10.13

Pandas의 shift method는 DataFrame이나 Series에 적용해서 행의 위치를 일정 칸수씩 이동시킵니다.

 

바로 예시를 통해 알아봅시다.

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        7, 8, 9, 10,
        11, 12, 13,
        14, 15, 16
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_shifted = df_test.shift(-1)
print(df_shifted)
print(type(df_shifted))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     7
7      2    a  2050     8
8      2    b  2000     9
9      2    b  2200    10
10     3    a  3000    11
11     3    a  3100    12
12     3    b  3200    13
13     4    a  4200    14
14     4    b  4100    15
15     4    b  4150    16

    col1 col2    col3  col4
0    1.0    a  1100.0   2.0
1    1.0    a  1200.0   3.0
2    1.0    b  1300.0   4.0
3    1.0    b  1050.0   5.0
4    1.0    b  1100.0   6.0
5    2.0    a  2100.0   7.0
6    2.0    a  2050.0   8.0
7    2.0    b  2000.0   9.0
8    2.0    b  2200.0  10.0
9    3.0    a  3000.0  11.0
10   3.0    a  3100.0  12.0
11   3.0    b  3200.0  13.0
12   4.0    a  4200.0  14.0
13   4.0    b  4100.0  15.0
14   4.0    b  4150.0  16.0
15   NaN  NaN     NaN   NaN
<class 'pandas.core.frame.DataFrame'>

위 예시는 df_test라는 DataFrame을 생성한 후 이 DataFrame에 shift를 적용한 것입니다.

 

df_shifted를 보면 DataFrame의 모든 행의 값이 하나씩 위로 올라간걸 볼 수 있습니다.

 

하나씩 위로 올라간것은 shift의 인자로서 -1이 적혔기 때문이고, -1은 위쪽으로 한칸씩 옮기라는 뜻입니다.

현재 index보다 1씩 작은(-1) index의 위치로 옮기라는 것입니다.

 

그리고 index=15인 행은 다음 행이 없으니 NaN값으로 표시된 것을 알 수 있죠.

 

또한 shift가 적용된 대상이 DataFrame인 df_test이므로 return되는 데이터도 DataFrame입니다.

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        7, 8, 9, 10,
        11, 12, 13,
        14, 15, 16
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_shifted = df_test.shift(1)
print(df_shifted)
print(type(df_shifted))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     7
7      2    a  2050     8
8      2    b  2000     9
9      2    b  2200    10
10     3    a  3000    11
11     3    a  3100    12
12     3    b  3200    13
13     4    a  4200    14
14     4    b  4100    15
15     4    b  4150    16

    col1 col2    col3  col4
0    NaN  NaN     NaN   NaN
1    1.0    a  1000.0   1.0
2    1.0    a  1100.0   2.0
3    1.0    a  1200.0   3.0
4    1.0    b  1300.0   4.0
5    1.0    b  1050.0   5.0
6    1.0    b  1100.0   6.0
7    2.0    a  2100.0   7.0
8    2.0    a  2050.0   8.0
9    2.0    b  2000.0   9.0
10   2.0    b  2200.0  10.0
11   3.0    a  3000.0  11.0
12   3.0    a  3100.0  12.0
13   3.0    b  3200.0  13.0
14   4.0    a  4200.0  14.0
15   4.0    b  4100.0  15.0
<class 'pandas.core.frame.DataFrame'>

반면에 shift의 인자로 1을 전달하면 모든 행의 값이 아래쪽으로 1칸씩 밀린 것을 알 수 있습니다.

 

index=0인 행은 이전 행이 없으므로 NaN으로 표시되었습니다.

 

이렇게 몇 칸을 옮기고싶은지에 대한 숫자를 shift의 인자로서 전달하면 원하는 만큼 이동이 가능합니다.

 

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        6, 7, 8, 9,
        10, 11, 12,
        13, 14, 15
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_shifted = df_test.loc[:, 'col4'].shift(-1)
print(df_shifted)
print(type(df_shifted))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     6
7      2    a  2050     7
8      2    b  2000     8
9      2    b  2200     9
10     3    a  3000    10
11     3    a  3100    11
12     3    b  3200    12
13     4    a  4200    13
14     4    b  4100    14
15     4    b  4150    15

0      2.0
1      3.0
2      4.0
3      5.0
4      6.0
5      6.0
6      7.0
7      8.0
8      9.0
9     10.0
10    11.0
11    12.0
12    13.0
13    14.0
14    15.0
15     NaN
Name: col4, dtype: float64
<class 'pandas.core.series.Series'>

shift는 DataFrame의 하나의 행에만 적용할 수도 있습니다.

 

위 예시는 df_test의 col4에만 shift를 적용시켰습니다.

 

loc[:, 'col4']를 보면 column이름인 col4에 대괄호가 쳐져있지 않으므로 이것은 col4를 Series로 반환합니다.

 

따라서 위 예시에서 shift는 Series에 적용된 것과 같으므로 shift의 return값도 Series입니다.

 

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        6, 7, 8, 9,
        10, 11, 12,
        13, 14, 15
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_shifted = df_test.loc[:, ['col4']].shift(-1)
print(df_shifted)
print(type(df_shifted))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     6
7      2    a  2050     7
8      2    b  2000     8
9      2    b  2200     9
10     3    a  3000    10
11     3    a  3100    11
12     3    b  3200    12
13     4    a  4200    13
14     4    b  4100    14
15     4    b  4150    15

    col4
0    2.0
1    3.0
2    4.0
3    5.0
4    6.0
5    6.0
6    7.0
7    8.0
8    9.0
9   10.0
10  11.0
11  12.0
12  13.0
13  14.0
14  15.0
15   NaN
<class 'pandas.core.frame.DataFrame'>

이번엔 loc.[:, ['col4']] 처럼 column이름에 대괄호를 쳐서 loc가 DataFrame을 return하게 했습니다.

 

따라서 여기에 적용된 shift도 DataFrame에 대해 적용되는 것이므로 shift의 return값도 DataFrame입니다.

 

shift는 자신이 적용된 대상의 data type과 동일한 data type의 결과를 return합니다.

 

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        6, 7, 8, 9,
        10, 11, 12,
        13, 14, 15
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_group_shifted = df_test.groupby(by=['col1', 'col2'])[['col4']].shift(-1)
print(df_group_shifted)
print(type(df_group_shifted))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     6
7      2    a  2050     7
8      2    b  2000     8
9      2    b  2200     9
10     3    a  3000    10
11     3    a  3100    11
12     3    b  3200    12
13     4    a  4200    13
14     4    b  4100    14
15     4    b  4150    15

    col4
0    2.0
1    3.0
2    NaN
3    5.0
4    6.0
5    NaN
6    7.0
7    NaN
8    9.0
9    NaN
10  11.0
11   NaN
12   NaN
13   NaN
14  15.0
15   NaN
<class 'pandas.core.frame.DataFrame'>

shift는 groupby와 함께 사용될 수 있습니다.

 

위 예시를 보면 col1, col2를 기준으로 groupby를 하고 groupby된 col4에 shift를 적용합니다.

 

따라서 결과를 보면 shift가 동일한 col1, col2값을 가진 행들의 그룹 내에서 적용된 것을 볼 수 있습니다.

(index=0, 1, 2 행이 동일한 col1, col2 값을 가지고있으므로 index=0, 1, 2에 있는 col4값을 위쪽으로 한 칸씩 올린 모습을 볼 수 있습니다. index=2는 동일한 col1, col2값을 가진 다음 행이 없으므로 NaN으로 표시되는 것도 볼 수 있죠.)

 

 

 

 

 

 

 

import pandas as pd

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        6, 7, 8, 9,
        10, 11, 12,
        13, 14, 15
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)


df_test.loc[:, 'col5'] = df_test.groupby(by=['col1'])['col3'].shift(-2)
print(df_test)




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     6
7      2    a  2050     7
8      2    b  2000     8
9      2    b  2200     9
10     3    a  3000    10
11     3    a  3100    11
12     3    b  3200    12
13     4    a  4200    13
14     4    b  4100    14
15     4    b  4150    15

    col1 col2  col3  col4    col5
0      1    a  1000     1  1200.0
1      1    a  1100     2  1300.0
2      1    a  1200     3  1050.0
3      1    b  1300     4  1100.0
4      1    b  1050     5     NaN
5      1    b  1100     6     NaN
6      2    a  2100     6  2000.0
7      2    a  2050     7  2200.0
8      2    b  2000     8     NaN
9      2    b  2200     9     NaN
10     3    a  3000    10  3200.0
11     3    a  3100    11     NaN
12     3    b  3200    12     NaN
13     4    a  4200    13  4150.0
14     4    b  4100    14     NaN
15     4    b  4150    15     NaN

 

위같은 방식으로 groupby와 shift로 이동된 데이터를 원본 DataFrame의 어떤 column에 할당할 수도 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [
        1, 1, 1, 1, 1, 1,
        2, 2, 2, 2,
        3, 3, 3,
        4, 4, 4
    ],
    'col2': [
        'a', 'a', 'a', 'b', 'b', 'b',
        'a', 'a', 'b', 'b',
        'a', 'a', 'b',
        'a', 'b', 'b'
    ],
    'col3': [
        1000, 1100, 1200, 1300, 1050, 1100,
        2100, 2050, 2000, 2200,
        3000, 3100, 3200,
        4200, 4100, 4150
    ],
    'col4': [
        1, 2, 3, 4, 5, 6,
        6, 7, 8, 9,
        10, 11, 12,
        13, 14, 15
    ]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_rolling_sum_1 = df_test.groupby(by=['col1', 'col2'])[['col4']].rolling(2).apply(sum)
print(df_rolling_sum_1)
print(type(df_rolling_sum_1))

df_rolling_sum_2 = df_test.groupby(by=['col1', 'col2'])[['col4']].rolling(2).apply(sum).shift(-1)
print(df_rolling_sum_2)
print(type(df_rolling_sum_2))




-- Result
    col1 col2  col3  col4
0      1    a  1000     1
1      1    a  1100     2
2      1    a  1200     3
3      1    b  1300     4
4      1    b  1050     5
5      1    b  1100     6
6      2    a  2100     6
7      2    a  2050     7
8      2    b  2000     8
9      2    b  2200     9
10     3    a  3000    10
11     3    a  3100    11
12     3    b  3200    12
13     4    a  4200    13
14     4    b  4100    14
15     4    b  4150    15

              col4
col1 col2         
1    a    0    NaN
          1    3.0
          2    5.0
     b    3    NaN
          4    9.0
          5   11.0
2    a    6    NaN
          7   13.0
     b    8    NaN
          9   17.0
3    a    10   NaN
          11  21.0
     b    12   NaN
4    a    13   NaN
     b    14   NaN
          15  29.0
<class 'pandas.core.frame.DataFrame'>

              col4
col1 col2         
1    a    0    3.0
          1    5.0
          2    NaN
     b    3    9.0
          4   11.0
          5    NaN
2    a    6   13.0
          7    NaN
     b    8   17.0
          9    NaN
3    a    10  21.0
          11   NaN
     b    12   NaN
4    a    13   NaN
     b    14  29.0
          15   NaN
<class 'pandas.core.frame.DataFrame'>

shift는 rolling과도 같이 사용될 수 있습니다.

 

위 예시를 보면 col1, col2를 기준으로 그룹화된 DataFrame의 col4에 2개 행(현재행, 그 이전행)에 대해 rolling sum을 진행한 것이 df_rolling_sum_1이고,

 

여기에 shift를 추가로 적용한게 df_rolling_sum_2입니다.

 

이 두 결과를 비교해보면 데이터는 똑같으나 shift(-1)이 적용된 결과는 동일한 group(=동일한 col1, col2 값을 가진 행들) 내에서 col4의 rooling sum 값이 한줄씩 위로 옮겨긴걸 볼 수 있습니다.

 

 

 

 

 

 

 

 

import pandas as pd

dict_test = {
    'col1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    'col2': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b'],
    'col3': [1000, 1200, 1100, 1050, 1300, 900, 1500, 2000, 1800, 1600]
}

df_test = pd.DataFrame(dict_test)
print(df_test)

df_rolling_sum = df_test.groupby(by=['col2'])[['col3']].rolling(2).apply(sum).shift(-1)
df_rolling_sum = df_rolling_sum.reset_index(drop=False, inplace=False)
print(df_rolling_sum)
print(type(df_rolling_sum))

df_test.loc[:, 'new_col3'] = df_rolling_sum.loc[:, 'col3']
print(df_test)
print(type(df_test))




-- Result
   col1 col2  col3
0     1    a  1000
1     2    a  1200
2     3    a  1100
3     4    a  1050
4     5    b  1300
5     6    b   900
6     7    b  1500
7     8    b  2000
8     9    b  1800
9    10    b  1600

  col2  level_1    col3
0    a        0  2200.0
1    a        1  2300.0
2    a        2  2150.0
3    a        3     NaN
4    b        4  2200.0
5    b        5  2400.0
6    b        6  3500.0
7    b        7  3800.0
8    b        8  3400.0
9    b        9     NaN
<class 'pandas.core.frame.DataFrame'>

   col1 col2  col3  new_col3
0     1    a  1000    2200.0
1     2    a  1200    2300.0
2     3    a  1100    2150.0
3     4    a  1050       NaN
4     5    b  1300    2200.0
5     6    b   900    2400.0
6     7    b  1500    3500.0
7     8    b  2000    3800.0
8     9    b  1800    3400.0
9    10    b  1600       NaN
<class 'pandas.core.frame.DataFrame'>

위 예시는 rolling sum과 shift를 적용한 결과를 df_test의 new_col3라는 새로운 컬럼에 할당하고 있는 예시입니다.

 

보시면 rolling sum + shift(-1)의 결과로 생성된 df_rolling_sum의 col3의 값이 df_test의 new_col3에 그대로 할당된것을 볼 수 있죠.

'Program > Python' 카테고리의 다른 글

pycharm pytest error  (0) 2023.11.16
graphviz 설치 후 오류 (Anaconda)  (0) 2018.08.10
ubuntu Jupyter  (0) 2018.07.13
numpy axis  (0) 2018.07.13
docker 한글설정  (0) 2018.07.07

sudo spctl --master-disable

 

cd data_directory

 

mongod --dbpath=data/db

 

new window

mongo

 

sudo spctl --master-enable

'연구개발 > MONGO' 카테고리의 다른 글

[MongoDB] Replication and Repica Sets 만들기  (0) 2014.09.02
MongoDB : Ubuntu Server에서 MongoDB replication 설정  (0) 2014.09.02
Mongostat  (0) 2014.04.08
mongo db 설정  (0) 2012.12.18

react-native: 웹 개발자가 한달만에 앱 출시하기

사례

  • 페이스북
  • 인스타그램
  • 디스코드
  • 케이크
    • 앱개발자 1명
    • 안드로이드 & iOS 개발기간 1달
    • 매달 정기 업데이트
    • 기존 앱 개발 방식이었다면 가능했을까?

선택의결과

  • 투입한 개발 리소스 ↓ = 최종 결과물의 퀄리티 ↑
  • 플랫폼간 공유 코드 ↑ = QA & 유지 보수 비용 ↓

빠른 개발 -> 코드 공유 -> 쉬운 개선

React Native는 단 기간에 프로덕션 레벨의 크로스 플랫폼 앱을 만들어야 할 때 고려할 수 있는 여러 선택지 중 가장 가성비가 좋은 프레임워크다.

react-native 완벽한 이해

React Component -> React Native -> Bridge -> Android, iOS

Threading Structure

Bridge 특징

1. Asynchronous

AS-IS Native 동기화 호출: 완료 시점까지 Javascript 처리 대기

TO-BE Native 비동기 호출: 완료 시점까지 Javascript 처리 진행

2. Serializable

AS-IS 독립적으로 운영되는 두 영역 간의 데이터 공유: 많은 관리 이슈 발생

TO-BE 직렬화 된 메시지 교환: 간결해진 구조 대신 성능 저하 발생

3. Batched

AS-IS Native 호출마다 직렬화와 역직렬화의 과정에서 부하 발생

TO-BE 큐에 넣어 5ms 단위로 일괄 처리하는 방식으로 성능 개선

Bridge 모니터링

  • MessageQueue 모니터링 방법

import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue'; MessageQueue.spy(true); MessageQueue.spy((info) => console.log("I'm spying!", info));

react-native의 발전방향

Facebook의 개선 방향

  1. New Threading model
  2. New async rendering capabilities
  3. Faster and more lightweight bridge

Cake 프로젝트에 얻은 노하우 &

EXPO(CRNA) 사용 자제

  1. 시작만 쉽고 모든 게 어려워짐
  2. 기본으로 제공하는 기능은 많지만 앱이 너무 커짐 (기본 25~30MB)
  3. 추가적인 Native 모듈을 설치할 수 없음 (제일 큰 이유!)

속 편하게 처음부터 빌드 방식(react-native-cli)으로 시작해라

효율적인 작업 순서

기본적인 작업 (레이아웃, 데이터 연동) -> 복잡한 애니메이션 & 인터랙션 확인 -> iOS에 특화된 UX 작업

중간에 안드로이드에서 확인하지 않으면 나중에 놀랄 수 있음!

Import 경로 지옥 탈출

상대경로 말고 절대경로를 사용하고 싶다면 babel-plugin-root-import를 적용

Optional Chaining

// AS-IS if(data && data.items && data.items.length > 2) { drawList(data); } // TO-BE if(data?.items?.length > 2) { drawList(data); }

Optional chaining operator 사용으로 쉽게 Null Safety 코딩! (0.56 버전부터 가능)

Lock dependencies

잘못된 라이브러리 업데이트는 고통을 불러옴

버전 고정하는 방법

  1. 설치마다 고정 버전으로 설치하기

$ npm install --save --save-exact react-native-fbsdk $ yarn add --exact react-native-fbsdk

  1. 전역 기본 옵션으로 설정하기

$ npm config set save-exact=true

Flow는 처음부터 꼭 사용해라

Flow를 적용해서 타입을 정의하면 파라미터 타입 오류의 사전 감지가 가능

  1. 코드 진단
  2. 자동 완성
  3. 타입 힌트
  4. 빠른 함수 이동

요즘은 타입스크립트도 지원이 많이 되어서 괜찮음

컴파일된 번들 파일 확인

자신이 짠 코드를 babel로 어떻게 변환되는지 확인해보는 것도 의미 있음

$ npm -g install js-beautify

$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output index.android.bundle $ js-beautify index.android.bundle > index.android.bundle.js

성능을 고려한 정적 이미지 사용

AS-IS Javascript packager가 동작하는 방식: Bundle 파일 생성 -> 모듈 ID로 치환

TO-BE App Resources 사용하기

  1. 기존 Native 개발 방식(Xcode asset catalogs / Android drawable folder)으로 추가
  2. 크기 속성을 꼭 정의

성능을 고려한 리모트 이미지 사용

내장 Image 컴포넌트의 문제

  1. Flickering
  2. Cache misses
  3. Low performances

// SDWebImage (iOS) / Glide (Android) 라이브러리 사용으로 문제점 개선 $ npm install react-native-fast-image

JavaScriptCode의 동작 오류

  • Remote Debug 모드는 크롬의 V8 엔진 사용 (JavaScriptCore 엔진은 Date 처리에 문제가 많으므로 moment.js 라이브러리 사용)
  • 플랫폼 간에도 다르게 동작할 수 있음 (안드로이드는 오래된 버전의 JavaScriptCore 엔진 사용중임)

플랫폼별 컴포넌트 스타일링

  • 재정의 방식으로 스타일 정의하기

import StyleSheet from './PlatformStyleSheet'; const styles = StyleSheet.create({ title: { fontSize: 16, ios: { fontSize: 18 }, android: { fontSize: 17, color: 'red' } } });

import { Platform, StyleSheet } from 'react-native'; const PlatformStyleSheet = { create(styles) { const platformStyles = {}; for (const key in styles) { const { ios, android, ...style } = styles[key]; (ios || android) && Object.assign(style, Platform.select({ios, android})); platformStyles[key] = style; } return StyleSheet.create(platformStyles); }, } export default PlatformStyleSheet;

편리한 Style 자동완성

  • atom-react-native-style 패키지 설치

안드로이드 Text 위 아래 패딩 제거

  • includeFontPadding 스타일 속성 끄기 (iOS와 동일하게 TextView의 ascent, descent 기준으로 출력)

공용 Text 컴포넌트 사용하기

class Text extends PureComponent { static defaultStyle = Platform.select({ ios: { fontFamily: 'AppleSDGothicNeo-Regular' }, android: { fontFamily: 'sans-serif', includeFontPadding: false } }); render() { const { children, style, ...props } = this.props; return <Text {...props} allowFontScaling={false} style={[Text.defaultStyle, style]}> {children} </Text>; } }

터치 영역 확장하기

  • hitSlop으로 최소한 44dp의 터치 영역을 보장해주세요.

<TouchableWithourFeedback hitSlop={{top: 7, right: 7, bottom: 7, left: 7}}> <View .../> </TouchableWithourFeedback>

놓치기 쉬운 최초 화면 렌더링

  • render() 함수가 최초에 한 번 실행된다는 걸 잊기 쉬움
  • render() -> componentDidMount() -> render()
  • 출력 여부 상태 값으로 불필요한 초기 렌더링 제거

화면에 보이지 않지만 동작하는 코드

  • 타이머/이벤트 리스너 사용 시 꼭 제거

개발자 도구

  • react-native: Perf Monitor(iOS)
  • Xocde: View Hierarchy Debugger
  • Android Studio: Profiler

60 FPS 보장하기

효율적인 애니메이션 사용

  • Javascript Driver 동작 순서

requestAnimationFrame 함수 실행 -> 값 계산 후 View.setNativeProps 함수 실행 -> Bridge로 전달 -> UI 업데이트

  • Native Driver 동작 순서

메인 쓰레드에서 프레임마다 실행 -> 계산된 값으로 직접 View 업데이트 호출 -> UI 업데이트

Animated.timing(this._animation, { toValue: 1, duration: 1000, useNativeDriver: true, // add this }).start();

무거운 코드의 올바른 실행 시점

  • 애니메이션과 인터랙션이 끝난 후로 실행 지연

반복되는 애니메이션이 있다면 등록한 코드가 실행되지 않거나 실행 시점의 문제 발생

  • 다음 프레임으로 실행 지연

현재 프레임의 다른 실행을 보장해서 앱 반응성 개선

import { InteractionManager } from 'react-native'; componentDidMount() { InteractionManager.runAfterInteractions(() => { this.doExpensiveAction(); }); } handleOnPress() { requestAnimationFrame(() => { this.doExpensiveAction(); }); }

FlatList 성능 개선

  • getItemLayout 속성 사용

높이가 고정된 구성이라면 레이아웃의 크기를 매번 계산하지 않아서 성능 개선

<FlatList getItemLayout={(data, index) => { { length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index } )} />

효율적인 레퍼런스 사용

  1. String Refs

Deprecated된 방식으로 사용하지 마세요.

// 레퍼런스 할당 <TextInput ref={'inputField'} /> // 레퍼런스 사용 this._refs.inputField.focus();

  1. Callback Refs

컴포넌트에 인라인 함수를 사용하는 건 좋지 않아요.

// 레퍼런스 할당 <TextInput ref={ component => this._inputField = component } /> // 레퍼런스 사용 this._inputField.focus();

  1. React.createRef()

React 16.3 버전부터 제공하는 효율적인 방식을 사용하세요.

// 레퍼런스 생성 this._inputFieldRef = React.createRef(); // 레퍼런스 할당 <TextInput ref={this._inputFieldRef} /> // 레퍼런스 사용 this._inputFieldRef.current.focus();

Google Play API Level 26 정책 대응

  • 유지보수되지 않는 라이브러리의 빌드 설정

android { compileSdkVersion 23 buildToolsVersion "23.0.1" defaultConfig { minSdkVersion 16 targetSdkVersion 22 } }

  • 프로젝트 설정을 사용하는 빌드 설정

def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } android { compileSdkVersion safeExtGet('compileSdkVersion', 27) buildToolsVersion safeExtGet('buildToolsVersion', '27.0.3') defaultConfig { minSdkVersion safeExtGet('minSdkVersion', 16) targetSdkVersion safeExtGet('targetSdkVersion', 26) } }

안드로이드 APK 최적화

  1. Split APK
  • CPU 별로 불필요한 코드 제거
  • 중복된 JavaScriptCore 라이브러리의 제거로 APK 크기 3~4 MB 감소

// android/app/build.gradle def enableSeparateBuildPerCPUArchitecture = true

  1. Proguard 적용

// android/app/build.gradle def enableProguardInReleaseBuilds = true

  1. shrinkResources 옵션 사용 금지
  2. console.* 코드 제거

$ npm install --save-dev babel-plugin-transform-remove-console

// .babelrc { "env": { "production": { "plugins": ["transform-remove-console"] } } }

  1. 불필요한 localized resource 제거

// android/app/build.gradle android { defaultConfig { resConfigs "en", "ko" } }

  1. 이미지 최적화

TinyPNG, OptiPNG

앱 크기에 대한 걱정은 오해

네비게이션 모듈 선택

  • react-navigation (JS 구현체)
  • react-native-navigation (Native 구현체)
  • Native 구현체가 JS 구현체보다 성능이 좋으니 무조건 앞선다는 글에 현혹되지 마세요.
  • 원하는 수준의 커스터마이징과 트러블 대응이 가능한 모듈을 선택하세요.

복잡한 애니메이션은 Lottie

  • 이제 디자이너한테 복잡한 애니메이션도 다 된다고 자신 있게 말하세요.

Adobe After Effects로 작업한 애니메이션을 JSON 형식으로 export하면 끝

<LottieView source={require('./animation.json')} autoPlay loop />

출처

  • 발표자료: 링크
  • 발표자: 스노우 이성민 개발자님

도움되는 링크

'Program > ReactNative And Expo' 카테고리의 다른 글

ReactNative Setting  (0) 2020.05.08

npm install -g react-native-cli

or

npm install -g expo-cli

 

 

프로젝트 생성

react-native init [프로젝트명]

or

expo init [프로젝트명]

 

cd [프로젝트명]

 

=== react-native

npm start ==> 프로젝트 시작

 

또 다른 창에 (실행했는데 에러난다면)

android/app/src/main 폴더에서 assets 폴더 생성

 

react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res

 

--platform android : 안드로이드 빌드

--dev false: 릴리즈 모드로 빌드

--entry-file index.js : index.js를 시작으로 번들링 할 것

--bundle-output *** : 번들결과 파일 위치 및 파일명 설정

--assets-dest *** : 리소스 경로 설정

 

끝나면

react-native run-android ==> simulator 가 뜬다

 

 

==== expo

yarn start 

 

 

 

 

빌드는?

 

번들링 생성 시

cd android

./gradlew bundleRelease

 

or

cd android && ./gradlew bundleRelease

 

여러번 빌드하다보면 번들링 결과가 여러번 생성되므로 정리해주자.

cd android && ./gradlew clean && ./gredlew bundleRelease

 

 

apk 생성해야한다면 assembleRelease 

cd android && ./gradlew assembleRelease

 

 

빌드 후 android/app/build/outputs에 결과 파일 생성

 

 

 

release 버전으로 구동 테스트할 때는 --variant=release 옵션을 넣고 실행하면 된다.

react-native run-android --variant=release

 

빌드 옵션 상세 ./gradlew bundleRelease 의 상세

react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res

 

--platform android : 안드로이드 빌드

--dev false: 릴리즈 모드로 빌드

--entry-file index.js : index.js를 시작으로 번들링 할 것

--bundle-output *** : 번들결과 파일 위치 및 파일명 설정

--assets-dest *** : 리소스 경로 설정

 

'eyes-movies '개인정보처리방침')은(는) 개인정보보호법에 따라 이용자의 개인정보 보호 및 권익을 보호하고 개인정보와 관련한 이용자의 고충을 원활하게 처리할 수 있도록 다음과 같은 처리방침을 두고 있습니다.

('개인정보처리방침') 은(는) 회사는 개인정보처리방침을 개정하는 경우 웹사이트 공지사항(또는 개별공지)을 통하여 공지할 것입니다.

○ 본 방침은부터 2020년 1월 1일부터 시행됩니다.

 

1. 개인정보의 처리 목적 ('개인정보처리방침')은(는) 개인정보를 다음의 목적을 위해 처리합니다. 처리한 개인정보는 다음의 목적이외의 용도로는 사용되지 않으며 이용 목적이 변경될 시에는 사전동의를 구할 예정입니다.

가. 홈페이지 회원가입 및 관리

회원 가입의사 확인, 회원제 서비스 제공에 따른 본인 식별·인증, 회원자격 유지·관리, 제한적 본인확인제 시행에 따른 본인확인, 서비스 부정이용 방지, 만14세 미만 아동 개인정보 수집 시 법정대리인 동의 여부 확인, 각종 고지·통지, 고충처리, 분쟁 조정을 위한 기록 보존 등을 목적으로 개인정보를 처리합니다.

 

나. 민원사무 처리

민원인의 신원 확인, 민원사항 확인, 사실조사를 위한 연락·통지, 처리결과 통보 등을 목적으로 개인정보를 처리합니다.

 

다. 재화 또는 서비스 제공

서비스 제공, 청구서 발송, 콘텐츠 제공, 맞춤 서비스 제공 등을 목적으로 개인정보를 처리합니다.

 

라. 마케팅 및 광고에의 활용

신규 서비스(제품) 개발 및 맞춤 서비스 제공, 이벤트 및 광고성 정보 제공 및 참여기회 제공 , 인구통계학적 특성에 따른 서비스 제공 및 광고 게재 , 서비스의 유효성 확인, 접속빈도 파악 또는 회원의 서비스 이용에 대한 통계 등을 목적으로 개인정보를 처리합니다.




2. 개인정보 파일 현황



3. 개인정보의 처리 및 보유 기간

 ('개인정보처리방침')은(는) 법령에 따른 개인정보 보유·이용기간 또는 정보주체로부터 개인정보를 수집시에 동의 받은 개인정보 보유,이용기간 내에서 개인정보를 처리,보유합니다.

② 각각의 개인정보 처리 및 보유 기간은 다음과 같습니다.



4. 개인정보의 제3자 제공에 관한 사항

 ('개인정보처리방침')은(는) 정보주체의 동의, 법률의 특별한 규정 등 개인정보 보호법 제17조 및 제18조에 해당하는 경우에만 개인정보를 제3자에게 제공합니다.

 (eyes-movies은(는) 다음과 같이 개인정보를 제3자에게 제공하고 있습니다.



5. 개인정보처리 위탁

 ('개인정보처리방침')은(는) 원활한 개인정보 업무처리를 위하여 다음과 같이 개인정보 처리업무를 위탁하고 있습니다.

 (eyes-movies '개인정보처리방침')은(는) 위탁계약 체결시 개인정보 보호법 제25조에 따라 위탁업무 수행목적 외 개인정보 처리금지, 기술적․관리적 보호조치, 재위탁 제한, 수탁자에 대한 관리․감독, 손해배상 등 책임에 관한 사항을 계약서 등 문서에 명시하고, 수탁자가 개인정보를 안전하게 처리하는지를 감독하고 있습니다.

③ 위탁업무의 내용이나 수탁자가 변경될 경우에는 지체없이 본 개인정보 처리방침을 통하여 공개하도록 하겠습니다.

6. 정보주체와 법정대리인의 권리·의무 및 그 행사방법 이용자는 개인정보주체로써 다음과 같은 권리를 행사할 수 있습니다.

① 정보주체는 eyes-movies에 대해 언제든지 개인정보 열람,정정,삭제,처리정지 요구 등의 권리를 행사할 수 있습니다.
② 제1항에 따른 권리 행사는eyes-movies에 대해 개인정보 보호법 시행령 제41조제1항에 따라 서면, 전자우편, 모사전송(FAX) 등을 통하여 하실 수 있으며 eyes-movies은(는) 이에 대해 지체 없이 조치하겠습니다.
③ 제1항에 따른 권리 행사는 정보주체의 법정대리인이나 위임을 받은 자 등 대리인을 통하여 하실 수 있습니다. 이 경우 개인정보 보호법 시행규칙 별지 제11호 서식에 따른 위임장을 제출하셔야 합니다.
④ 개인정보 열람 및 처리정지 요구는 개인정보보호법 제35조 제5항, 제37조 제2항에 의하여 정보주체의 권리가 제한 될 수 있습니다.
⑤ 개인정보의 정정 및 삭제 요구는 다른 법령에서 그 개인정보가 수집 대상으로 명시되어 있는 경우에는 그 삭제를 요구할 수 없습니다.
⑥ eyes-movies은(는) 정보주체 권리에 따른 열람의 요구, 정정·삭제의 요구, 처리정지의 요구 시 열람 등 요구를 한 자가 본인이거나 정당한 대리인인지를 확인합니다.



7. 처리하는 개인정보의 항목 작성

 (eyes-movies '개인정보처리방침')은(는) 다음의 개인정보 항목을 처리하고 있습니다.



8. 개인정보의 파기('개인정보처리방침')은(는) 원칙적으로 개인정보 처리목적이 달성된 경우에는 지체없이 해당 개인정보를 파기합니다. 파기의 절차, 기한 및 방법은 다음과 같습니다.

-파기절차
이용자가 입력한 정보는 목적 달성 후 별도의 DB에 옮겨져(종이의 경우 별도의 서류) 내부 방침 및 기타 관련 법령에 따라 일정기간 저장된 후 혹은 즉시 파기됩니다. 이 때, DB로 옮겨진 개인정보는 법률에 의한 경우가 아니고서는 다른 목적으로 이용되지 않습니다.

-파기기한
이용자의 개인정보는 개인정보의 보유기간이 경과된 경우에는 보유기간의 종료일로부터 5일 이내에, 개인정보의 처리 목적 달성, 해당 서비스의 폐지, 사업의 종료 등 그 개인정보가 불필요하게 되었을 때에는 개인정보의 처리가 불필요한 것으로 인정되는 날로부터 5일 이내에 그 개인정보를 파기합니다.



9. 개인정보 자동 수집 장치의 설치•운영 및 거부에 관한 사항

① eyes-movies 은 개별적인 맞춤서비스를 제공하기 위해 이용정보를 저장하고 수시로 불러오는 ‘쿠기(cookie)’를 사용합니다. ② 쿠키는 웹사이트를 운영하는데 이용되는 서버(http)가 이용자의 컴퓨터 브라우저에게 보내는 소량의 정보이며 이용자들의 PC 컴퓨터내의 하드디스크에 저장되기도 합니다. 가. 쿠키의 사용 목적 : 이용자가 방문한 각 서비스와 웹 사이트들에 대한 방문 및 이용형태, 인기 검색어, 보안접속 여부, 등을 파악하여 이용자에게 최적화된 정보 제공을 위해 사용됩니다. 나. 쿠키의 설치•운영 및 거부 : 웹브라우저 상단의 도구>인터넷 옵션>개인정보 메뉴의 옵션 설정을 통해 쿠키 저장을 거부 할 수 있습니다. 다. 쿠키 저장을 거부할 경우 맞춤형 서비스 이용에 어려움이 발생할 수 있습니다.

10. 개인정보 보호책임자 작성


① eyes-movies( ‘개인정보처리방침) 은(는) 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호책임자를 지정하고 있습니다.


▶ 개인정보 보호책임자
성명 :조대환
직책 :CTO
직급 :CTO
연락처 :01092090179, head1tonbs@gmail.com,
※ 개인정보 보호 담당부서로 연결됩니다.

② 정보주체께서는 eyes-movies(‘개인정보처리방침) 의 서비스(또는 사업)을 이용하시면서 발생한 모든 개인정보 보호 관련 문의, 불만처리, 피해구제 등에 관한 사항을 개인정보 보호책임자 및 담당부서로 문의하실 수 있습니다. eyes-movies(‘개인정보처리방침) 은(는) 정보주체의 문의에 대해 지체 없이 답변 및 처리해드릴 것입니다.



11. 개인정보 처리방침 변경

①이 개인정보처리방침은 시행일로부터 적용되며, 법령 및 방침에 따른 변경내용의 추가, 삭제 및 정정이 있는 경우에는 변경사항의 시행 7일 전부터 공지사항을 통하여 고지할 것입니다.



12. 개인정보의 안전성 확보 조치 ('개인정보처리방침')은(는) 개인정보보호법 제29조에 따라 다음과 같이 안전성 확보에 필요한 기술적/관리적 및 물리적 조치를 하고 있습니다.

1. 개인정보 취급 직원의 최소화 및 교육
개인정보를 취급하는 직원을 지정하고 담당자에 한정시켜 최소화 하여 개인정보를 관리하는 대책을 시행하고 있습니다.

2. 내부관리계획의 수립 및 시행
개인정보의 안전한 처리를 위하여 내부관리계획을 수립하고 시행하고 있습니다.

3. 개인정보의 암호화
이용자의 개인정보는 비밀번호는 암호화 되어 저장 및 관리되고 있어, 본인만이 알 수 있으며 중요한 데이터는 파일 및 전송 데이터를 암호화 하거나 파일 잠금 기능을 사용하는 등의 별도 보안기능을 사용하고 있습니다.

4. 개인정보에 대한 접근 제한
개인정보를 처리하는 데이터베이스시스템에 대한 접근권한의 부여,변경,말소를 통하여 개인정보에 대한 접근통제를 위하여 필요한 조치를 하고 있으며 침입차단시스템을 이용하여 외부로부터의 무단 접근을 통제하고 있습니다.

5. 비인가자에 대한 출입 통제
개인정보를 보관하고 있는 물리적 보관 장소를 별도로 두고 이에 대해 출입통제 절차를 수립, 운영하고 있습니다.

import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
tf.compat.v1.disable_eager_execution()

# config = tf.compat.v1.ConfigProto()
# config.gpu_options.per_process_gpu_memory_fraction = 0.1
# set_session(tf.compat.v1.Session(config=config))


config = tf.compat.v1.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.1
tf.compat.v1.keras.backend.set_session(tf.compat.v1.Session(config=config))

설치 환경은

Anaconda3 python 3.5



증상

conda install graphviz 로 설치하고

프로그램을 수행하면 아래와 같이 뜬다


No module named graphviz


원인

conda install 하면 graphviz 폴더를 

~/Anaconda3/Library/bin/ 로 설치를 한다

문제는 python interpreter 가 이 위치를 읽지 못한다는 것


해결

graphviz 폴더를 복사해서

~/Anaconda3/Lib/site-packages 하위로 복사해준다


결과

No module 문제는 해결 된다

----------------------------------------------------------------


증상

 [dot, ~]가 excutable  하지 않다고 나옴



원인

 graphviz download 사이트에 들어가 찾아보면

 더이상 자동으로 PATH를 잡아주지 않는다고

 dot 명령이 바로 실행 되도록 알아서 PATH를 잡으라고 한다


해결

~\Anaconda3\Lib\site-packages\graphviz 를

PATH에 추가한다


결과

코드가 실행된다 

만약 실행이 안되면 창을 다 닿았다가 다시 실행해보자

그래도 안되면 pip install graphviz 를 해보자 

(사실 설치중에 conda install 과 pip install 이 된 상태여서 이게 결함인지는 모르겠다)



출처: http://livetoday.tistory.com/entry/graphviz-설치-후-오류-Anaconda [Hero]

'Program > Python' 카테고리의 다른 글

pycharm pytest error  (0) 2023.11.16
Dataframe shift  (0) 2022.12.23
ubuntu Jupyter  (0) 2018.07.13
numpy axis  (0) 2018.07.13
docker 한글설정  (0) 2018.07.07

로그 파일 업데이트 되는 내용을 보려면 tail을 사용하면 된다.

tail -f log.txt

이렇게 하면 log.txt파일에 새로 추가된 내용이 화면에 출력된다.

ssh로 원격에 있는 서버의 로그 파일도 볼 수 있다.

ssh user@host "tail -f /locaion/to/log/file"

서버가 두대여서 터미널 창 두개 열어놓고 보고 있었는데 현진한테 물어보니 multitail을 사용하면 된다고 한다. 찾아보니 관련 글도 많다.

일단 맥에는 multitail이 없으니 brew install multitail로 설치한다.

그러고 위의 링크에 나와있는대로 해보면 화면이 분할되어서 로그파일이 나온다.

multitail -l 'ssh user@host1 "tail -f /var/log/apache2/error.log"' -l 'ssh user@host2 "tail -f /var/log/apache2/error.log"'

상하좌우 화면 분할도 자유롭고 보고있는 파일명도 아래에 표시되어서 훨씬 알아보기 쉽다.

'연구개발 > Ubuntu' 카테고리의 다른 글

jenkins (젠킨스) 설치  (0) 2017.07.06
우분투 계정 관리  (0) 2017.06.13
한글  (0) 2016.05.22
[Ubuntu] 시간 동기화 - ntpdate  (0) 2014.12.12
ubuntu mysql 삭제  (0) 2014.10.27

Jupyter를 사용하면 뭐가 좋아지나?

  • 웹브라우저에서 모든 작업이 이루어져 편리해진다.
  • 코딩과 문서화 작업을 한꺼번에 할 수 있다.
  • 매일 일기 쓰듯이 코딩 연습을 할 수 있게 자연스럽게 습관이 든다.
  • 재미있어진다.

어떻게 사용하나?

  • 온라인에서 서비스를 제공해 주는 곳에 가서 이용해도 된다.
  • 하지만 나의 데스크탑에 로컬로 설치해서 마음대로 환경을 설정해 가면서 쓰는것이 더 좋다.
  • 작업한 노트북들은 Github에 push하면서 백업 효과를 노리자.

Jupyter Notebook 설치 및 환경셋팅

  • 시스템 자체의 부하가 크지 않기 때문에 한 번 같이 올려본다.
  • 자신의 서버/컴퓨터에서 Jupyter 서비스를 온라인으로 제공하게 되면, 자신이 사용하는 PC 마다 일일이 따로따로 설치해 줘야 하는 불편함에서 벗어날 수 있다.
  • Python, Julia, Octave, Bash 커널 등을 넣어서 함께 제공하기로 한다.
  • 본 환경구축 레시피는 다음 환경에서 테스트했다.
    • 우분투 16.04 계열 리눅스 머신

Anaconda3 설치

  • Anaconda 패키지를 설치하는게 가장 손쉽다.
  • Anaconda 패키지에는, python과 과학기술용 각종 라이브러리들, 그리고 Jupyter 핵심 부분이 기본적으로 포함되어 있으며, 일반적인 python의 패키지 관리자인 pip 말고 전용 패키지 관리자인 conda도 들어있다.
  • 다운로드 사이트 : https://www.continuum.io/downloads#linux
  • 위 사이트에서 다운로드 할 버전의 주소를 복사한 다음, 아래와 같이 wget으로 NAS에 다운로드 받아도 된다.
  • 다운로드 받은 설치파일을 실행한다.
bash Anaconda3-4.2.0-Linux-x86_64.sh
  • 설치할 때 마지막에 bash 설정에 경로를 추가할지를 묻는데, 당연히 추가하도록 yes 해 준다.
  • 이제 Anaconda 패키지는 모두 ~/anaconda3 경로에 설치되어 있을 것이다. sudo 권한으로 설치한 것이 아니므로, 자신이 마음대로 삭제할 수도 있다는 점을 유의한다. 또한 앞으로 새로 추가할 패키지들 역시 sudo 권한이 불필요할 것이다.

Anaconda3 업데이트 및 셋팅

  • Anaconda의 Python 패키지들을 전부 최신버전으로 업데이트하려면 다음 명령을 쓰면 된다.
conda update conda
conda update anaconda

Jupyter를 위한 Python 환경 생성

  • 고립된 Python 환경을 생성하여면 다음과 같은 식으로 하면 된다. 본 예에서는 JUPYTER라는 이름의 Python 환경을 만들고, 그 환경을 Activate 시키는 것이다.
conda create --name JUPYTER ipython
source activate JUPYTER

Jupyter 설치

  • 기본적인 패키지는 이미 Anaconda에 들어가 있지만, 확실히 하기 위해 Jupyter 설치 명령을 준다.
conda install jupyter

Jupyter Notebook에 설치 가능한 커널

Julia 커널 설치

  • Julia 언어를 시스템에 설치하고, 이것을 Jupyter에서도 사용할 수 있도록 커널을 설치해 보자.
  • 저장소를 등록하고, 설치.
sudo add-apt-repository ppa:staticfloat/juliareleases
sudo add-apt-repository ppa:staticfloat/julia-deps
sudo apt-get update
sudo apt-get install julia
  • 기본적인 Julia 패키지 설치
julia

실행한 후, Julia 안에서 다음 명령을 넣어서 Julia 언어에서 사용할 확률이 가장 높은 모듈들을 추가 설치한다.

Pkg.init()
Pkg.add("Jewel")
Pkg.add("Images")
Pkg.add("PyPlot")
Pkg.add("IJulia")
Pkg.update()
quit()
  • 패키지 설치 도중에 빌드 에러가 발생할 경우, 다음과 같이 의존성 있는 것들을 추가 설치해 주면 해결될 확률이 높다. (어떤 모듈의 경우에는 설치하면서 동시에 Build 작업이 진행되는 경우가 있다.)
sudo apt-get install build-essential cmake

GNU Octave 커널 설치

  • 이번에는 GNU Octave를 시스템에 설치하고, 이것을 Jupyter에서도 사용할 수 있도록 커널을 설치해 보자.
  • 저장소를 등록하고, 설치.
sudo add-apt-repository ppa:octave/stable
sudo apt-get update
sudo apt-get install octave
  • Octave 잘 실행되는지 확인
octave-cli
  • Octave GUI 실행 확인
octave
  • Octave GUI 실행 실패시 조치 (QT 설정파일 소유권을 root에서 현재 사용자로 변경) : 현행 배포한의 버그.
sudo chown -hR 계정:계정 ~/.config/octave
  • 커널 설치 (sudo 불필요)
pip install octave_kernel
python -m octave_kernel.install

Bash 커널 설치

  • 이번에는 Bash를 시스템에 설치하고, 이것을 Jupyter에서도 사용할 수 있도록 커널을 설치해 보자.
  • 커널 설치
pip install bash_kernel
python -m bash_kernel.install

C 커널 설치

  • 이번에는 C 언어를 Jupyter에서도 사용할 수 있도록 커널을 설치해 보자. C 컴파일러는 이미 시스템에 gcc로 설치되어 있으므로 컴파일러는 별도로 설치할 필요가 없다.
  • 참고 : https://github.com/brendan-rius/jupyter-c-kernel
  • C 커널 설치
pip install jupyter-c-kernel
  • 커널스펙 설정
cd ~
git clone https://github.com/brendan-rius/jupyter-c-kernel.git
mkdir ~/.local/share/jupyter/kernels/c_spec
cp ./jupyter-c-kernel/c_spec/kernel.json ~/.local/share/jupyter/kernels/c_spec/kernel.json

설치된 커널들 이상없는지 확인하기

  • 아래 명령은 치면, 위에서 설치했던 커널들의 목록을 볼 수 있다.
jupyter kernelspec list

Jupyter Notebook 작업 디렉토리 생성

  • 아무데서나 실행할 수는 없으므로, 작업할 디렉토리를 따로 만들어주는게 보안상 좋겠다. 이왕이면 Github와 연동시키기 좋도록 한다.
mkdir ~/github/My-Jupyter-Notebooks
  • Github 리모트 저장소와 연결하는 절차의 설명은 생략한다.

Jupyter Notebook을 외부망에서 접속 가능하도록 설정하기

jupyter notebook --generate-config
  • 그러면 /home/dong/.jupyter/jupyter_notebook_config.py 파일이 새로 생겨난 것을 확인.
  • 한편, 로그인을 위한 패스워드 해쉬코드를 만든다. 이와 관련된 기본적인 파이썬 함수가 있으므로, 파이썬 상태에서 이 함수를 이용해서 해쉬코드를 만든다. 우선 터미널에 python 쳐서 파이썬 REPL로 들어간 다음,
from notebook.auth import passwd
passwd()

위와 같이 명령을 때려주면 비밀번호를 치라고 나오는데 확인차 2번 쳐 주면 해쉬코드로 된 비밀번호 코드가 나온다. 해쉬코드를 긁어다 복사해 두거나 메모해 둔다. 그리고 python 콘솔을 빠져나오려면

exit()
  • 설정 프로파일을 편집기로 열어서 내용 확인. (대략 500줄을 좀 넘어가는 코드이고, 대부분 주석)
nano /home/계정/.jupyter/jupyter_notebook_config.py
  • 편집기에서 다음 내용으로 해당 부분을 수정해 준다. 이중에서 포트 번호는 원하는걸로 바꾸면 되지만, 여기서는 8888로 하자. 각 행의 맨 앞에 주석기호 #의 유무를 잘 비교해서 확인하자.
c.NotebookApp.ip = '*'
c.NotebookApp.port = 8888
c.NotebookApp.notebook_dir = u'/home/계정/github/My-Jupyter-Notebooks'
c.NotebookApp.open_browser = False
`
* 그리고, 비밀번호 해쉬코드도 다음과 같은 형식으로 넣어준다.
`
c.NotebookApp.password = u'sha1:67c9e6어쩌구저쩌구71089e11aed'
  • 완료되었으면 해당 편집기를 저장하고 종료.
  • 서버 환경에 따라 방화벽으로 막혀 있을 수 있으므로 해당 포트를 뚫어준다.
sudo ufw allow 8888

Jupyter Notebook 실행 테스트

  • 다음 명령을 주면 실행된다.
jupyter notebook
  • 자동으로 웹브라우저가 실행되지 않도록 하려면 이렇게 한다.
jupyter notebook --no-browser
  • 특정한 디렉토리를 루트로 삼아 실행되도록 하려면 이렇게 한다.
jupyter notebook --notebook-dir='디렉토리경로'
  • 이제 외부 컴퓨터의 웹브라우저로 다음 주소를 쳐서 들어가지는지 확인.

비밀번호 로그인, 설치된 커널의 활성화 여부 등을 확인한다.

  • 이상없이 잘 되면, 서버 터미널에서 Ctrl+cy를 쳐서 종료한다.

부팅할 때 자동으로 Jupyter Notebook 실행되도록 설정

  • 개인 서버에서 돌리려면 이런식으로 자동 스타트 설정을 해 주면 편리할 것이다.
  • 쉘 스크립트를 편집해서 만든다.
nano ~/Start_Jupyter.sh

한 다음 다음 내용을 써 넣고 저장 후 종료.

#!/bin/bash
/home/계정/anaconda3/bin/jupyter notebook &
  • 만든 쉘 스크립트를 실행 가능하도록 속성을 준다.
chmod +x ~/Start_Jupyter.sh
  • 다음과 같이 rc.local 파일을 열어서 편집한다.
sudo nano /etc/rc.local
  • 다음 내용을 추가한 후 저장하고 편집기 종료.
sudo -u 계정 /home/계정/Start_Jupyter.sh
  • 서버 재부팅
sudo reboot now
  • 만일 제대로 작동을 안한다면 다음 명령을 줘 본다. (참고)
sudo systemctl enable rc-local.service

Jupyter Notebook Extensions 설치

  • Anaconda를 이용해 설치된 Jupyter Notebook에는 Anaconda 자체적인 Extension이 이미 설치되어 있다. 별다른 조치 없이 슬라이드샷으로 프리젠테이션 해 주는 기능 등이 있어 편리하다. (참고)
  • 다만 여기서는 표준적인 Jupyter Notebook Extensions를 추가로 설치 시도한다.
  • 참고 : https://github.com/ipython-contrib/jupyter_contrib_nbextensions
conda install -c conda-forge jupyter_contrib_nbextensions
  • 단, 이 익스텐션은 64비트 버전만 제공되고 32비트 버전은 제공되지 않는다. 자신의 서버/컴퓨터가 32비트라면 사용할 수 없다.

Jupyter Notebook Themes 설치

  • 여러가지 방식으로 개발된 테마들이 있지만, 다음의 것이 가장 심플하고 설치 자체도 쉬운 것 같다.
  • jupyterthemes : https://github.com/dunovank/jupyter-themes
  • 설치는 다음 한 줄이면 끝난다.
pip install jupyterthemes
  • 설치 후 적용 가능한 테마를 보기 위해 jt -l을 쳐 주면 다음과 같이 4가지 테마가 나온다.
onedork
grade3
oceans16
chesterish
  • 이 중에서 grade3가 바탕이 흰 색의 테마이고, 나머지는 어두운 색이다. 시험삼아 다음 명령을 하나씩 줘 보자.
jt -t grade3 -T -N
  • 원상복귀 하려면 jt -r을 주면 된다고 하는데, 해 봐도 원상복귀가 안된다! ㅠㅠ
  • 강제로 원상복귀 시키려면, 원래의 오리지널 css 파일을 만들어서 집어넣어주면 될 것이다.
  • ~/.jupyter/custom/custom.css 파일을 만들고 편집기로 다음 내용을 집어넣으면 원래 오리지널 테마로 복원된다.
.rendered_html pre, .rendered_html code, pre, .CodeMirror, .prompt {
  font-family: 나눔고딕코딩, Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;;
}
.rendered_html pre,
.rendered_html code {
    font-family: Consolas,"Andale Mono WT","Andale Mono","Lucida Console","Lucida Sans Typewriter","DejaVu Sans Mono","Bitstream Vera Sans Mono","Liberation Mono","Nimbus Mono L",Monaco,"Courier New",Courier,monospace;
	background-color: #f5f5f5;
}
.rendered_html pre {
	padding: 8.5px;
	border: 1px solid #ccc;
	border-radius: 2px;
}
.rendered_html p > code,
.rendered_html ul li code {
    border: solid 1px #e1e4e5;
    color: #E74C3C;
    padding: 0 5px;
    overflow-x: auto;
}
blockquote {
	background-color: #fcf2f2;
	border-color: #dFb5b4;
	border-left: 5px solid #dfb5b4;
	padding: 0.5em;
}

Jupyter Lab

  • 이제까지 설치해서 사용하는 환경은 바로 ‘Jupyter Notebook’이다.
  • 그런데 이 UI가 마음에 안 드는지, 한 그룹에서 새롭게 Jupyter Lab을 개발하고 있다.

JupyterLab

  • 현재 알파 릴리즈되어 설치해서 작동 시켜볼 수도 있다.
  • 다만 아직 완전하게 기능구현,최적화,버그 등을 모두 잡은 상태는 아닌 것 같다.
  • 다만 아마 1~2년 정도 지나서는 Notebook에서 Lab 환경으로 이행할 것으로 보인다.
  • JupyterLab 레포지토리
  • 개인적으로 사용해 보니 확실히 Notebook 보다 더 편리하고 기능이 더 많다.
  • conda-forge 패키지 저장소에서도 제공하고 있기 때문에 설치 방법은 간단하다.
conda install -c conda-forge jupyterlab
  • 설치 후, 다음 명령으로 실행한다.
julia lab
  • 그러면 주소는 다음과 같이 나온다.
  • 기존의 Notebook 환경이 그립다면 주소를 이렇게 바꾸면 된다.
  • 아마 당분간은 이렇게 Lab과 Notebook을 공존시키다가, Lab이 충분히 성숙되면 Notebook은 별도로 떨어뜨리기로 계획되어 있다고 한다.

결론

  • 이제 Jupyter에서 Python, C, Octave, Julia, Bash 등을 마음대로 사용할 수 있게 되었으니 가지고 놀면 된다.


'Program > Python' 카테고리의 다른 글

Dataframe shift  (0) 2022.12.23
graphviz 설치 후 오류 (Anaconda)  (0) 2018.08.10
numpy axis  (0) 2018.07.13
docker 한글설정  (0) 2018.07.07
file "/usr/bin/pip" line 9, in <module>  (0) 2018.07.03


[[1 2 3]

[4 5 6]]


np.sum(a, axis=0) : [5 7 9]

np.sum(a, axis=1) : [6 15]

'Program > Python' 카테고리의 다른 글

graphviz 설치 후 오류 (Anaconda)  (0) 2018.08.10
ubuntu Jupyter  (0) 2018.07.13
docker 한글설정  (0) 2018.07.07
file "/usr/bin/pip" line 9, in <module>  (0) 2018.07.03
[OpenCV] face detection  (0) 2018.06.28
● interactive mode 로 도커 이미지 실행.
아래 명령을 사용하여 우분투 이미지를 실행하여 현재 locale 을 확인한다.
현재 도커 레포지토리를 통해 배포되는 대부분의 우분투 이미지는 locale 설정이 안되어 있을것이다.
(외국 애들은 한글이나 일본어, 중국어 따윈 관심 없을테니...)
docker run -it [IMAGE] /bin/bash
[zany@dione ~]$ docker run -it -u root ubuntu:base /bin/bash
[root@510a1395b315 ~]# locale
LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=


[root@510a1395b315 ~]# locale -a
C
C.UTF-8
POSIX

[root@510a1395b315 ~]# ls /usr/share/i18n/locales/
ls: cannot access '/usr/share/i18n/locales/': No such file or directory
locale 명령을 입력해보면, POSIX 로 표기될 것이고
locale -a 명령으로 사용 가능한 locale 목록을 보면 위 결과와 같이 몇개 안나올 것이다.
/usr/share/i18n/locales 디렉토리는 존재하지도 않는다.

echo '한글' 명령으로 tty 에서 한글이 되는지 확인하지도 못한다.
echo '한글' 이라는 명령어 자체도 입력 못할테니...

● 우분투 패키지 매니저로 locales 설치
locale 이 있어야 설정을 하든 말든 할테니...
일단 우분투 패키지 매니저(apt-get)를 통해 locales 패키지를 설치하자 (아래 명령)
apt-get upgrade 는 OS 에 설치된 패키지를 업그레이드 할 것이니 필요치 않으면 빼도 무방하다.
apt-get clean && apt-get update && apt-get upgrade && apt-get install locales
[root@510a1395b315 ~]# apt-get clean && apt-get update && apt-get upgrade && apt-get install locales
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]
Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
Get:3 http://security.ubuntu.com/ubuntu xenial-security/universe Sources [51.1 kB]
Get:4 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]

... 어쩌구 저쩌구 생략 ... 

Selecting previously unselected package locales.
(Reading database ... 13279 files and directories currently installed.)
Preparing to unpack .../locales_2.23-0ubuntu9_all.deb ...
Unpacking locales (2.23-0ubuntu9) ...
Setting up locales (2.23-0ubuntu9) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
Generating locales (this might take a while)...
Generation complete.
정상적으로 처리되었으면, /usr/share/i18n/locales/ 디렉토리에 locale 파일들이 생겼을 것이다.
ls 명령으로 /usr/share/i18n/locales/ 디렉토리의 내용을 보자.
ls /usr/share/i18n/locales/
[root@510a1395b315 ~]# ls /usr/share/i18n/locales/
C            bs_BA           en_ZM       ga_IE@euro          li_BE         ps_AF             tk_TM
POSIX        byn_ER          en_ZW       gd_GB               li_NL         pt_BR             tl_PH
aa_DJ        ca_AD           eo          gez_ER              lij_IT        pt_PT             tn_ZA
aa_ER        ca_ES           eo_US       gez_ER@abegede      ln_CD         pt_PT@euro        tr_CY
aa_ER@saaho  ca_ES@euro      es_AR       gez_ET              lo_LA         quz_PE            tr_TR
aa_ET        ca_ES@valencia  es_BO       gez_ET@abegede      lt_LT         raj_IN            translit_circle
af_ZA        ca_FR           es_CL       gl_ES               lv_LV         ro_RO             translit_cjk_compat
ak_GH        ca_IT           es_CO       gl_ES@euro          lzh_TW        ru_RU             translit_cjk_variants
am_ET        ce_RU           es_CR       gu_IN               mag_IN        ru_UA             translit_combining
an_ES        ckb_IQ          es_CU       gv_GB               mai_IN        rw_RW             translit_compat
anp_IN       cmn_TW          es_DO       ha_NG               mg_MG         sa_IN             translit_font
ar_AE        crh_UA          es_EC       hak_TW              mhr_RU        sat_IN            translit_fraction
ar_BH        cs_CZ           es_ES       he_IL               mi_NZ         sc_IT             translit_hangul
ar_DZ        csb_PL          es_ES@euro  hi_IN               mk_MK         sd_IN             translit_narrow
... 생략 ...
apt-get install locales 명령시 자동으로 locale-gen 명령이 수행되지만,
/usr/share/i18n/locales 디렉토리가 아직 보이지 않으면 locale-gen 명령을 별도로 수행해보자.
locales 패키지를 설치하여도 사용 가능한 locale 을 확인해보면 아직 원하는 것이 나오지 않는다.
locale -a
[root@510a1395b315 ~]# locale -a
C
C.UTF-8
POSIX

● locale 생성 / 등록
localedef 명령을 이용하여 필요한 locale 을 컴파일해준다.
-i 옵션은 inputfile 을 의미하며
-f 옵션은 문자셋을 의미한다.
localedef 명령 후, locale -a 명령으로 사용 가능한 locale 을 확인해보면 새로 추가한 2개의 항목이 보일 것이다.
localedef -i ko_KR -f UTF-8 ko_KR.UTF-8
localedef -i en_US -f UTF-8 en_US.UTF-8
locale -a
[root@510a1395b315 ~]# localedef -i ko_KR -f UTF-8 ko_KR.UTF-8
[root@510a1395b315 ~]# localedef -i en_US -f UTF-8 en_US.UTF-8
[root@510a1395b315 ~]# locale -a
C
C.UTF-8
POSIX
en_US.utf8
ko_KR.utf8

● locale 관련 패키지 재설정 (optional)
dpkg-reconfigure 명령으로 locale 설정을 다시 해준다.
아래 명령어를 실행하면 2가지를 묻는다.
1. 어떤 locale 을 사용할 것이냐?
2. 시스템 환경을 위한 기본 locale 을 뭘로 할꺼냐?
dpkg-reconfigure locales
[root@510a1395b315 ~]# dpkg-reconfigure locales
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LANG = "ko_KR.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
Configuring locales
-------------------

Locales are a framework to switch between multiple languages and allow users to use their language, country, characters,
collation order, etc.

Please choose which locales to generate. UTF-8 locales should be chosen by default, particularly for new installations.
Other character sets may be useful for backwards compatibility with older systems and software.

  1. All locales                      162. es_CL ISO-8859-1               323. mni_IN UTF-8
  2. aa_DJ ISO-8859-1                 163. es_CL.UTF-8 UTF-8              324. mr_IN UTF-8
  3. aa_DJ.UTF-8 UTF-8                164. es_CO ISO-8859-1               325. ms_MY ISO-8859-1
  4. aa_ER UTF-8                      165. es_CO.UTF-8 UTF-8              326. ms_MY.UTF-8 UTF-8
  5. aa_ER@saaho UTF-8                166. es_CR ISO-8859-1               327. mt_MT ISO-8859-3
  6. aa_ET UTF-8                      167. es_CR.UTF-8 UTF-8              328. mt_MT.UTF-8 UTF-8
  7. af_ZA ISO-8859-1                 168. es_CU UTF-8                    329. my_MM UTF-8
  8. af_ZA.UTF-8 UTF-8                169. es_DO ISO-8859-1               330. nan_TW UTF-8
  9. ak_GH UTF-8                      170. es_DO.UTF-8 UTF-8              331. nan_TW@latin UTF-8
  10. am_ET UTF-8                     171. es_EC ISO-8859-1               332. nb_NO ISO-8859-1
  ... 생략 ...

(Enter the items you want to select, separated by spaces.)

Locales to be generated: 290

  ... 생략 ...

This will select the default language for the entire system. If this system is a multi-user system where not all users are
able to speak the default language, they will experience difficulties.

  1. None  2. C.UTF-8  3. ko_KR.UTF-8
Default locale for the system environment: 3
ko_KR.UTF-8 이 290 번 이어서 290 으로 입력 하였으나,
OS 버전에 따라 다를 수 있으니 목록에서 적절한 번호를 골라 입력한다.

● .bashrc 에 LANG 환경값 추가
LANG 환경값을 .bashrc 에 등록해준다.
export LANG=ko_KR.UTF-8

● 도커 커밋 후... 재실행.. 확인.
현재 도커를 커밋하고 종료 후 재실행하여 locale 이 정상적으로 적용되었는지 확인하자.
도커를 커밋하지 않으면 변경 내용이 이미지에 기록되지 않으니 꼭 커밋하고 재실행해서 확인하자.
docker commit -p [CONTAINER] [REPOSITORY[:TAG]]
[zany@dione ~]$ docker commit -p 510a1395b315 ubuntu:base
sha256:65afd6c09559b1001316c067b075e3a73c5aa02132752a9e184b0dedf2be2097
[root@a0610820dc88 ~]# locale
LANG=ko_KR.UTF-8
LANGUAGE=
LC_CTYPE="ko_KR.UTF-8"
LC_NUMERIC="ko_KR.UTF-8"
LC_TIME="ko_KR.UTF-8"
LC_COLLATE="ko_KR.UTF-8"
LC_MONETARY="ko_KR.UTF-8"
LC_MESSAGES="ko_KR.UTF-8"
LC_PAPER="ko_KR.UTF-8"
LC_NAME="ko_KR.UTF-8"
LC_ADDRESS="ko_KR.UTF-8"
LC_TELEPHONE="ko_KR.UTF-8"
LC_MEASUREMENT="ko_KR.UTF-8"
LC_IDENTIFICATION="ko_KR.UTF-8"
LC_ALL=
[root@a0610820dc88 ~]# echo '한글'
한글
[root@a0610820dc88 ~]#


'Program > Python' 카테고리의 다른 글

ubuntu Jupyter  (0) 2018.07.13
numpy axis  (0) 2018.07.13
file "/usr/bin/pip" line 9, in <module>  (0) 2018.07.03
[OpenCV] face detection  (0) 2018.06.28
[OpenCV] 영상 얼굴 인식 (face detection)  (0) 2018.06.28


도커 명령어 익히기 ( + 우분투 설치 )


도커 명령어

옵션설명
-ddetached mode (백그라운드 모드)
-pHost와 컨테이너의 Port를 연결 (fowarding)
-vHost와 컨테이너의 Directory 연결 (마운트)
-e컨테이너 내에서 사용할 환경변수 설정
-it-i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션
--rm프로세스 종료시 컨테이너 자동 제거
--link컨테이너 연결[컨테이너명:별칭]
--name컨테이너 이름 설정



도커 실행중인지 확인 docker version

C:\Users\bactoria>docker version
Client:
 Version:       18.03.0-ce
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    0520e24
 Built: Wed Mar 21 23:06:28 2018
 OS/Arch:       windows/amd64
 Experimental:  false
 Orchestrator:  swarm

Server:
 Engine:
  Version:      18.03.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   0520e24
  Built:        Wed Mar 21 23:14:32 2018
  OS/Arch:      linux/amd64
  Experimental: false

C:\Users\bactoria>



우분투 이미지 다운로드 docker pull ubuntu:16.04

C:\Users\bactoria>docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
22dc81ace0ea: Pull complete
1a8b3c87dba3: Pull complete
91390a1c435a: Pull complete
07844b14977e: Pull complete
b78396653dae: Pull complete
Digest: sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
Status: Downloaded newer image for ubuntu:16.04

C:\Users\bactoria>



이미지 확인하기 docker images

C:\Users\bactoria>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f975c5035748        2 weeks ago         112MB

C:\Users\bactoria>



우분투 컨테이너 실행하기 docker run -it --name myUbuntu ubuntu:16.04 /bin/bash

C:\Users\bactoria>docker run -it --name myUbuntu ubuntu:16.04 /bin/bash
root@27db33196683:/#



리눅스 접속 확인하기 ls

root@27db33196683:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@27db33196683:/#



우분투 컨테이너 종료하기 exit

root@27db33196683:/# exit
exit

C:\Users\bactoria>



실행중인 컨테이너 확인하기 docker ps

C:\Users\bactoria>docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

C:\Users\bactoria>



모든 컨테이너 확인하기 docker ps -a

C:\Users\bactoria>docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
be76370e89aa        ubuntu:16.04        "/bin/bash"         45 seconds ago      Exited (0) 15 seconds ago                       myUbuntu

C:\Users\bactoria>



종료된 우분투 컨테이너 실행하기 docker start myUbuntu

C:\Users\bactoria>docker start myUbuntu
myUbuntu

C:\Users\bactoria>



우분투 컨테이너 접속하기 docker attach myUbuntu + Enter X2

C:\Users\bactoria>docker attach myUbuntu
root@be76370e89aa:/#
root@be76370e89aa:/#



우분투 컨테이너 빠져나가기 Ctrl+p + Ctrl+q
(컨테이너 종료하지 않음)

root@be76370e89aa:/#
root@be76370e89aa:/# read escape sequence

C:\Users\bactoria>



실행중인 모든 컨테이너 확인하기 docker ps

C:\Users\bactoria>docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
be76370e89aa        ubuntu:16.04        "/bin/bash"         5 minutes ago       Up 3 minutes                            myUbuntu

C:\Users\bactoria>



우분투 컨테이너 종료하기 docker stop myUbuntu

C:\Users\bactoria>docker stop myUbuntu
myUbuntu

C:\Users\bactoria>



이미지 제거하기 docker rmi ubuntu:16.04
(삭제안됨)

C:\Users\bactoria>docker rmi ubuntu:16.04
Error response from daemon: conflict: unable to remove repository reference "ubuntu:16.04" (must force) - container be76370e89aa is using its referenced image f975c5035748

C:\Users\bactoria>



컨테이너 제거하기 docker rm myUbuntu
(이미지 제거하려면 컨테이너 먼저 제거해야 함)

C:\Users\bactoria>docker rm myUbuntu
myUbuntu

C:\Users\bactoria>



컨테이너 제거 확인 docker ps -a
(삭제되어서 없어졌을거임)

C:\Users\bactoria>docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

C:\Users\bactoria>



이미지 보기 docker images

C:\Users\bactoria>docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              16.04               f975c5035748        2 weeks ago         112MB

C:\Users\bactoria>



이미지 삭제하기 docker rmi ubuntu:16.04

C:\Users\bactoria>docker rmi ubuntu:16.04
Untagged: ubuntu:16.04
Untagged: ubuntu@sha256:e348fbbea0e0a0e73ab0370de151e7800684445c509d46195aef73e090a49bd6
Deleted: sha256:f975c50357489439eb9145dbfa16bb7cd06c02c31aa4df45c77de4d2baa4e232
Deleted: sha256:0bd983fc698ee9453dd7d21f8572ea1016ec9255346ceabb0f9e173b4348644f
Deleted: sha256:08fe90e1a1644431accc00cc80f519f4628dbf06a653c76800b116d3333d2b6d
Deleted: sha256:5dc5eef2b94edd185b4d39586e7beb385a54b6bac05d165c9d47494492448235
Deleted: sha256:14a40a140881d18382e13b37588b3aa70097bb4f3fb44085bc95663bdc68fe20
Deleted: sha256:a94e0d5a7c404d0e6fa15d8cd4010e69663bd8813b5117fbad71365a73656df9

C:\Users\bactoria>



무에서 유를 창조하고

다시 무로 돌아갔다.

안보고 우분투 컨테이너 생성까지 가즈아~



Issues

  • 컨테이너 attach 안될때
    컨테이너 restart 하고나서 다시 attach 붙이자.
    ( attach 명령 후 엔터 한번 더눌러 줘야함. )


  • 도커이미지 갑자기 날라갈때
    이건 hyper에 vm이랑 관련된거같은데.. 자세히 몰겠음. 한번씩 맛탱이가 가던데


  • docker version에서 Server가 안뜰 때
    hyper-V 관리자를 열어 가상머신이 실행중인지 확인


'연구개발 > Etc..' 카테고리의 다른 글

mac port kill  (0) 2024.01.31
운영체제 개론  (0) 2017.05.29
지표 관련 용어  (0) 2016.08.22
unity key  (0) 2016.05.07
RAID 1+0 과 0+1의 차이점  (0) 2011.07.11

vi /usr/bin/pip


from pip import main
if __name__ == '__main__':
    sys.exit(main())

요렇게 변경


from pip import __main__ 
if __name__ == '__main__':
    sys.exit(__main__._main())


'Program > Python' 카테고리의 다른 글

numpy axis  (0) 2018.07.13
docker 한글설정  (0) 2018.07.07
[OpenCV] face detection  (0) 2018.06.28
[OpenCV] 영상 얼굴 인식 (face detection)  (0) 2018.06.28
numpy 배열 쪼개기  (0) 2018.01.05

import numpy as np

import cv2


face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')


img = cv2.imread('redvelvet.png')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)


faces = face_cascade.detectMultiScale(gray, 1.3, 5)


for (x,y,w,h) in faces:

    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)

    roi_gray = gray[y:y+h, x:x+w]

    roi_color = img[y:y+h, x:x+w]

    eyes = eye_cascade.detectMultiScale(roi_gray)

    for(ex,ey,ew,eh) in eyes:

        cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)


cv2.imshow('img',img)

cv2.waitKey(0)

cv2.destroyAllWindows()




https://blog.naver.com/limitsinx/221137914300

'Program > Python' 카테고리의 다른 글

docker 한글설정  (0) 2018.07.07
file "/usr/bin/pip" line 9, in <module>  (0) 2018.07.03
[OpenCV] 영상 얼굴 인식 (face detection)  (0) 2018.06.28
numpy 배열 쪼개기  (0) 2018.01.05
2. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31


import cv2

cap = cv2.VideoCapture('testvideo.divx')

face_pattern = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

while True:

          ret, frame = cap.read()

          gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

          faceList = face_pattern.detectMultiScale(gray, 1.5)

          for (x, y, w, h) in faceList:

                  cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 3)

          cv2.imshow('image', frame)

          if cv2.waitKey(1) & 0xFF == ord('q'):

                 break

cap.release()

cv2.destroyAllWindows()



'Program > Python' 카테고리의 다른 글

file "/usr/bin/pip" line 9, in <module>  (0) 2018.07.03
[OpenCV] face detection  (0) 2018.06.28
numpy 배열 쪼개기  (0) 2018.01.05
2. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31
1. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31

http://symplog.tistory.com/266

'연구개발 > DBA' 카테고리의 다른 글

oracle mssql linked server  (0) 2018.04.17
select 처리순서  (0) 2017.08.02
Microsoft Windows DistributedCOM 오류 로그  (0) 2016.03.23
mssql 권한설정  (0) 2016.03.16
tempdb 분리  (0) 2016.03.15

https://blogs.msdn.microsoft.com/dbrowne/2013/10/02/creating-a-linked-server-for-oracle-in-64bit-sql-server/



This post is a walkthrough of creating a Linked Server to Oracle from 64bit SQL Server.  There's lots of information on doing this on the web, but much of it is out-of-date.

First, install the correct Oracle drivers.  You want the latest version of the Oracle Data Access Components (ODAC), and you want the XCopy deployment.  They are available here:

64-bit Oracle Data Access Components (ODAC) Downloads

http://www.oracle.com/technetwork/database/windows/downloads/index-090165.html

One you download and unzip this into a folder run the following command from that folder:

C:\Users\dbrowne\Downloads\ODAC121010Xcopy_x64>.\install.bat oledb c:\oracle\odac64 odac64 true

Then you need to add two folders to your system path: c:\oracle\odac64 and c:\oracle\odac64\bin


Then you must reboot for the system path change to be visible by services like SQL Server.

After reboot you're ready to create and test the linked server.

First configure the Oracle OleDB provider to run inside the SQL Server process, and configure it to accept parameters.

exec master.dbo.sp_MSset_oledb_prop 'ORAOLEDB.Oracle', N'AllowInProcess', 1 
exec master.dbo.sp_MSset_oledb_prop 'ORAOLEDB.Oracle', N'DynamicParameters', 1 

Then create the linked server definition.  Instead of a TNSNames alias, use an EZConnect identifier.  Here I'm specifying an IP address and a SID to connecto to an Oracle Express instance running on a VM:

 

exec sp_addlinkedserver N'MyOracle', 'Oracle', 'ORAOLEDB.Oracle', N'//172.16.8.119/xe', N'FetchSize=2000', ''

 

exec master.dbo.sp_serveroption @server=N'MyOracle', @optname=N'rpc out', @optvalue=N'true'
exec sp_addlinkedsrvlogin @rmtsrvname='MyOracle', @useself=N'FALSE', @rmtuser=N'system', @rmtpassword='xxxxxx'     

Now you're ready to test.  We configured the linked server for 'rpc out' so we can send a simple passthrough query to test connectivity:

exec ('select 1 a from dual') at MyOracle

That's it.





exec master.dbo.sp_MSset_oledb_prop 'ORAOLEDB.Oracle', N'AllowInProcess', 1 



exec master.dbo.sp_MSset_oledb_prop 'ORAOLEDB.Oracle', N'DynamicParameters', 1 




exec sp_addlinkedserver N'MyOracle', 'Oracle', 'ORAOLEDB.Oracle', N'//192.168.10.80:1521/myora', N'FetchSize=5000', ''



exec master.dbo.sp_serveroption @server=N'MyOracle', @optname=N'rpc out', @optvalue=N'true'




exec sp_addlinkedsrvlogin @rmtsrvname='MyOracle', @useself=N'FALSE', @rmtuser=N'system', @rmtpassword='head1ton' 



exec ('select 1 a from dual') at MyOracle

'연구개발 > DBA' 카테고리의 다른 글

Mysql Mssql linked server  (0) 2018.04.17
select 처리순서  (0) 2017.08.02
Microsoft Windows DistributedCOM 오류 로그  (0) 2016.03.23
mssql 권한설정  (0) 2016.03.16
tempdb 분리  (0) 2016.03.15

hsplit(array, number) 수평으로 쪼개기

vsplit(array, number) 수직으로 쪼개기

dsplit(array, number) 깊게 쪼개기

split(array, number, axis) 쪼개기 axis=0 수직으로 axis=1 수평으로



dsplit 쪼개기



'Program > Python' 카테고리의 다른 글

[OpenCV] face detection  (0) 2018.06.28
[OpenCV] 영상 얼굴 인식 (face detection)  (0) 2018.06.28
2. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31
1. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31
np.newaxis  (0) 2017.12.28

앞에 설명한 것에 이어서  인제 앞에서 짠것과 같은 코드를 DeviceFarm에 올리는 방법에 대해 설명하겠다. 그냥 지금 프로젝트를 압축해서 올리면 DeviceFarm에서는 돌아가지 않는다. Maven 프로젝트로 만들어줘야 한다. Maven을 잘 모르더라도 겁먹을 필요는 없다. 그냥 설명하는 대로 잘 따라하면 제대로 동작한다. 


그리고 아직 AWS DeviceFarm에 대해 더 자세히 알고 싶으면 http://docs.aws.amazon.com/devicefarm/latest/developerguide/devicefarm-dg.pdf 

에 접속해서 저 PDF를 꼼꼼히 읽어보길 바란다. 

여기서는 Working with Appium Java TestNG for Android and Device Farm 이부분만을 보면된다. 

혹시라도 완성된 다른코드를 보고 싶으면 사람을 위해 

https://github.com/awslabs/aws-device-farm-appium-tests-for-sample-app

이 코드를 보고 참고해서 만들면 된다. 


우선 Maven 프로젝트를 만들어준다. 툴을 Eclipse이다. 





빨간색 표시된 곳을 눌러 MavenProject를 만들어 준다. 

그리고 그냥 다 Next를 눌러 완성 시킨 후 pom.xml을 우선 셋팅해준다. 



<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>


<groupId>com.acme</groupId>

<artifactId>acme-android-appium</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>


<dependencies>

<dependency>

<groupId>org.testng</groupId>

<artifactId>testng</artifactId>

<version>6.8.8</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>io.appium</groupId>

<artifactId>java-client</artifactId>

<version>3.1.0</version>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-jar-plugin</artifactId>

<version>2.6</version>

<executions>

<execution>

<phase>package</phase>

<goals>

<goal>test-jar</goal>

</goals>

</execution>

</executions>

</plugin>

<plugin>

<groupId>org.apache.maven.plugins</groupId>

<artifactId>maven-dependency-plugin</artifactId>

<version>2.10</version>

<executions>

<execution>

<id>copy-dependencies</id>

<phase>package</phase>

<goals>

<goal>copy-dependencies</goal>

</goals>

<configuration>

<outputDirectory>${project.build.directory}/dependency-jars/</outputDirectory>

</configuration>

</execution>

</executions>

</plugin>

<plugin>

<artifactId>maven-assembly-plugin</artifactId>

<version>2.5.4</version>

<executions>

<execution>

<phase>package</phase>

<goals>

<goal>single</goal>

</goals>

<configuration>

<finalName>zip-with-dependencies</finalName>

<appendAssemblyId>false</appendAssemblyId>

<descriptors>

<descriptor>src/main/assembly/zip.xml</descriptor>

</descriptors>

</configuration>

</execution>

</executions>

</plugin>

</plugins>

</build>


 

</project>



위와 같이 설정을 해준 후 src안에 main 과 test패키지를 만들어준다. 그 이후 main 안에는 assembly안에 zip.xml파일을 만들어준다. 


zip.xml의 내용은 

<assembly

    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0http://maven.apache.org/xsd/assembly-1.1.0.xsd">

  <id>zip</id>

  <formats>

    <format>zip</format>

  </formats>

  <includeBaseDirectory>false</includeBaseDirectory>

  <fileSets>

    <fileSet>

      <directory>${project.build.directory}</directory>

      <outputDirectory>./</outputDirectory>

      <includes>

        <include>*.jar</include>

      </includes>

    </fileSet>

    <fileSet>

      <directory>${project.build.directory}</directory>

      <outputDirectory>./</outputDirectory>

      <includes>

        <include>/dependency-jars/</include>

      </includes>

    </fileSet>

  </fileSets>

 

</assembly>

와 같다. 


 



위와 같은 구조로 만들어 준 후 page, 와 test는 테스트 코드들이다. 저것과 꼭 똑같이 할필요는 없다. 그냥 테스트 코드를 저 위치에 test패키지안에 넣어주면 된다. 주의할점은 selenium의 라이브러리 값들을 maven이 가져오는 depedency들에게 맞춰서 다시 임포트 해줘야한다. 


이후에는 cmd 창에가서 mvn package install 를 해주면 target에 pom에 설정해두었던 대로 폴더들이 생성된다. 

 


여기서 중요한 것은 zip-with-depedencies 파일이다. 이것을 deviceFarm에 올려주면 된다. 

DeviceFarm에 테스트를 설정하는 것은 매우 간단하므로 굳이 설명하지 않겠다. 


이것보다 더 나은 방법도 있을 수 있다. 그러나 나처럼 삽질하시는 분들이 없으면 하는 마음에 포스트를 작성해보았다. 그나마 삽질하시는 분들에게 조금이나마 도움이되었으면한다. 


이번에 내가 있던 스타트업에서 안드로이드 어플을 런칭할 기회가 생겨 테스트를 위해 AWS DeviceFarm 을 이용하여 테스트를 해볼 기회가 생겼다. 안드로이드 기기를 실제로 Device와 OS 버전을 전부 맞춰서 일일이 테스트하기란 거의 불가능에 가깝다. 그래서 자동화 테스트툴 Appium , Calabash, uiAutomator등이 나오게 되었고 DeviceFarm은 이런 자동화테스트 툴을 이용하여 실제 디바이스에서 테스트하는 것을 간단한 조작 만으로 가능하게 해주었다. 


그 과정이 한글로된 문서들이 없어서 힘들어할 사람들을 위해 내가 삽질했던 부분들을 다른 분들은 좀 더 편하게 작업하시라고 포스트를 할려고한다. 


먼저 Appium을 설치해야한다. 그리고 자신이 만들 프로젝트에 Selenium 라이브러리를 추가해주어야한다. 먼저 Appium 을 설치하는 방법이다. 


일단 이동영상을 먼저 보면 어떻게 설치하고 돌려야하는지 대충 감이 잡힌다. 

 

https://www.youtube.com/watch?v=FJ_GwSApOpo



그리고 SlideShare에서 가장 Appium에 대해 잘 설명되어있는 슬라이드를 올린다. 이 두가지를 먼저 보면 Appium을 어떻게 써야하고 무엇인지 대충 감이 잡힌다. 

일단 죄송하게도 내 컴퓨터가 맥이라 맥을 기준으로 설명을 한다. Window도 크게 다르지 않다. 


http://appium.io/ 로 일단 접속하여 Appium을 다운로드한다. 








핑크색으로 표시된 부분을 누르면 다운로드를 받을 수 있다. 다운로드를 받은 후 해야할 일은 Path들이 잘 설정 되어있는지 보아야한다. 그 방법은 간단하다. Appium을 실행 시켜 청진기 버튼을 누르면 간단하게 테스트 할 수 있다. 



Iphone Test는 신경쓰지 않아도 된다. 지금은 안드로이드 테스트를 해야하니까. 보통 Mac에서의 자바 경로는 저곳이다. JAVA_HOME과 ANDROID_HOME path는 무조건 설정을 해줘야한다.( 설정하는 방법을 검색해도 모르겠으면 댓글을 남겨주면 설명하는 블로그를 새로 올리겠습니다.)

이렇게 설정 테스트를 맞췄으면 인제 프로젝트를 생성해보면 된다. 

나는 Eclipse를 가지고 테스트를 하였다. 미리 테스트하고 싶은 apk파일로 만들어놓아야한다. 

아 그전에 테스트 코드를 어떻게 만들어야할지 모르는 사람들을 위해 github에 좋은 코드가 있어서 소개한다.

https://github.com/testvagrant/AppiumDemo

보통 찾아보면 있는 코드들(Main에 그냥 다때려받는) 과는 달리 이 코드는 상당히 깔끔하게 정리가 되어있다. 
이 코드를 보았으면 프로젝트를 만들 때 주의 할 점은 아까 위에서 소개한 동영상을 참고하면 프로젝트 라이브러리들을 쉽게 설정할 수 있다. 요점은 selenium의 버전이 최신버전이면 굳이 testng 라이브러리를 넣지 않아도 된다. selenium안에서 testng가 포함되어 있다. 

코드에 대한 설명은 더 하지 않겠다. 왜냐하면 설정하는 방법을 설명하는 것이기 때문에 (코드에대한 질문이 있으면 따로 질문해주면 답변해드리겠습니다. )

테스트 코드가 다 완성되었다는 가정하에 인제 애뮬레이터를 먼저 켜놓아야한다. 나는 Genymotion을 사용하였다.(설치 방법도 간단하고 기본 애뮬레이터보다 속도가 훨씬 빠르다.) 애뮬레이터를 켠 후 Appium을 실행시킨후 Launch를 누른다. (Appium의 대한 셋팅은 안드로이드 디자인의 아이콘을 누르면 설정할 수 있다. Package명과 시작시 Activity를 설정해주었다. 나머지는 자신에 맞게 설정해주면된다. )  그 이후 이클립스에서 프로젝트를 Run -> TestNG로 실행하면 테스트 코드가 수행되는 모습을 볼 수 있다. 

내가 좀 찾았던 힌트를 몇개 드리면 테스트 코드에서 디바이스의 backButton은 driver.navigate().back(); 메소드를 사용하면 백버튼을 구현할 수 있다. Appium testng 테스트 코드는 안드로이드 apk의 코드를 읽어 파싱하여 테스트 코드를 실행시키기 때문에 코드를 읽을 수 있는 안드로이드의 ID값이나 Text 이름 아니면 xpath값을 설정해주어야한다. xpath값을 찾는 방법을 모르는 사람을 위해 내가 찾은 방법을 설명하자면 테스트 코드가 실제로 돌아갈때 Appium에서 돋보기 버튼을 누르면 해당화면을 찍어 xpath값을 알아낼 수 있다. 그러나 이 값이 모든 디바이스에서 동일하지 않기 때문에 여러 디바이스에서 테스트하는 경우라면 id 값을 가져오거나 실제로 List 클래스를 구현하여 읽는것이 가장 낫다. 

다음번에는 AWS DeviceFarm에 실제로 테스트하기 위해 프로젝트를 셋팅하는 방법에 대해 포스팅하겠다. 


pyInstaller라는 게 있다.

http://www.pyinstall.org/


64비트에서도 잘 작동한다.


> python setup.py install 로 설치한다.


사용 시)

EXE로 만들기를 원하는 파이썬 스크립트를 찾아 CONSOLE에서 명령 실행

> pyinstaller.exe xxx.py


단일 파일로 만들 때는 -F 옵션 추가

> pyinstaller.exe -F xxx.py


GUI 프로그램의 경우, 실행 시 CONSOLE창을 숨기고 싶다면 --noconsole 옵션 추가

> pyinstaller.exe -F --noconsole xxx.py



'Program > Python' 카테고리의 다른 글

[OpenCV] 영상 얼굴 인식 (face detection)  (0) 2018.06.28
numpy 배열 쪼개기  (0) 2018.01.05
1. python3 py파일 exe 실행파일 만들기  (0) 2017.12.31
np.newaxis  (0) 2017.12.28
python matplotlib 한글깨짐  (0) 2017.12.28

py2exe는 python2 만 지원하는 것으로 알고 있고

python3에는 cx_freeze 라는 모듈을 사용해야한다.


cx_freeze - http://cx-freeze.sourceforge.net

py2exe - http://www.py2exe.org


> pip install cx_freeze


Setup.py 파일로 만들어서 실행 파일로 실행


import sys

import os

from cx_Freeze import setup, Executable


os.environ['TCL_LIBRARY'] = "c:/python/tcl/tcl8.6"

os.environ['TK_LIBRARY'] = "c:/python/tcl/tk8.6"


setup(name = "parser",

options={"build_exe": {"packages": ["tkinter", "matplotlib"],

"include_files": ['clienticon.ico']}},

version = "1.0",

description = "Parser",

author = "head1ton",

executables = [Executable("parser.py")])

만약 윈도우 GUI 프로그램인 경우 executables의 옵션을 입력해주어야 한다.

executables = [Executable("imgtk.py", base="Win32GUI")])


Setup.py 실행

> python setup.py build


설치파일로 만들 수도 있다.

> python setup.py bdist_msi

dist 폴더에 설치파일 생성.


참고 - http://sh1n2.tistory.com/123



1. AWS EC2 접속


2. AMI 버전 확인

$ grep . /etc/*-release

/etc/os-release:NAME="Amazon Linux AMI"

/etc/os-release:VERSION="2017.03"

/etc/os-release:ID="amzn"

/etc/os-release:ID_LIKE="rhel fedora"

/etc/os-release:VERSION_ID="2017.03"

/etc/os-release:PRETTY_NAME="Amazon Linux AMI 2017.03"

/etc/os-release:ANSI_COLOR="0;33"

/etc/os-release:CPE_NAME="cpe:/o:amazon:linux:2017.03:ga"

/etc/os-release:HOME_URL="http://aws.amazon.com/amazon-linux-ami/"

/etc/system-release:Amazon Linux AMI release 2017.03


3. Java 1.8 설치

$ java -version

java version "1.7.0_151"

OpenJDK Runtime Environment (amzn-2.6.11.0.74.amzn1-x86_64 u151-b00)

OpenJDK 64-Bit Server VM (build 24.151-b00, mixed mode)


$ sudo yum install java-1.8.0


$ sudo yum remove java-1.7.0


$ java -version

openjdk version "1.8.0_141"

OpenJDK Runtime Environment (build 1.8.0_141-b16)

OpenJDK 64-Bit Server VM (build 25.141-b16, mixed mode)


4. Scala 설치

$ wget https://downloads.lightbend.com/scala/2.12.3/scala-2.12.3.tgz

$ tar xzvf scala-2.12.3.tgz


$ sudo su -

# cd /home/ec2-user/

# mv scala-2.12.3 /usr/local/scala

# exit


$ sudo vi /etc/profile


export PATH=$PATH:/usr/local/scala/bin


$ source /etc/profile


$ scala -version

Scala code runner version 2.12.3 -- Copyright 2002-2017, LAMP/EPFL and Lightbend, Inc.


5. Spark 설치

* 주의 사항 : AWS t2.large 인스턴스 정도가 되어야 정상 동작함 (t2.small에서는 Spark Streaming 정상 동작 하지 않음)

$ wget https://d3kbcqa49mib13.cloudfront.net/spark-2.2.0-bin-hadoop2.7.tgz

$ tar xvzf spark-2.2.0-bin-hadoop2.7.tgz


$ sudo su -

# cd /home/ec2-user/

# mv spark-2.2.0-bin-hadoop2.7 /usr/local/spark

# exit


$ sudo vi /etc/profile


export PATH=$PATH:/usr/local/spark/bin


$ source /etc/profile

$ spark-shell


6. Kafka 설치 및 데몬 실행

$ wget http://apache.mirror.cdnetworks.com/kafka/0.11.0.0/kafka_2.11-0.11.0.0.tgz

$ tar xzvf kafka_2.11-0.11.0.0.tgz

$ ln -s kafka_2.11-0.11.0.0 kafka


$ bin/zookeeper-server-start.sh -daemon config/zookeeper.properties

$ bin/kafka-server-start.sh -daemon config/server.properties


7. MongoDB 설치 및 서비스 실행

$ sudo su

# vi /etc/yum.repos.d/mongodb-org-3.4.repo


[mongodb-org-3.4]

name=MongoDB Repository

baseurl=https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.4/x86_64/

gpgcheck=1

enabled=1

gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc


# yum install -y mongodb-org

# service mongod start

# mongo

# exit


8. Redis 설치 및 서비스 실행

$ sudo yum -y update

$ sudo yum -y install gcc make


$ sudo wget http://download.redis.io/redis-stable.tar.gz

$ tar xvzf redis-stable.tar.gz

$ cd redis-stable

$ sudo make install


$ sudo mkdir -p /etc/redis /var/lib/redis /var/redis/6379

$ sudo cp redis.conf /etc/redis/6379.conf

$ sudo vi /etc/redis/6379.conf


daemonize yes

logfile /var/log/redis_6379.log

dir /var/redis/6379


$ sudo wget https://raw.githubusercontent.com/saxenap/install-redis-amazon-linux-centos/master/redis-server

$ sudo mv redis-server /etc/init.d

$ sudo chmod 755 /etc/init.d/redis-server

$ sudo vi /etc/init.d/redis-server


REDIS_CONF_FILE="/etc/redis/6379.conf"


$ sudo chkconfig --add redis-server

$ sudo chkconfig --level 345 redis-server on

$ sudo service redis-server start


9. Node.js 개발 환경 구축

$ sudo yum install git-core

$ sudo yum install nodejs npm --enablerepo=epel


$ npm -v

1.3.6

$ sudo npm update -g npm

$ npm -v

5.3.0

$ npm install


$ sudo npm cache clean -f

$ sudo npm install -g n

$ sudo n 6.11.1

$ node -v

v0.10.48


재접속


$ node -v

v6.11.1


10. Maven 개발 환경 구축

$ sudo yum install java-1.8.0-openjdk-devel.x86_64

$ sudo alternatives --config java

$ sudo alternatives --config javac

$ javac -version

javac 1.8.0_141


$ sudo wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo

$ sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo

$ sudo yum install -y apache-maven

$ mvn -v

Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-10T16:41:47+00:00)

Maven home: /usr/share/apache-maven

Java version: 1.7.0_151, vendor: Oracle Corporation

Java home: /usr/lib/jvm/java-1.7.0-openjdk-1.7.0.151.x86_64/jre

Default locale: en_US, platform encoding: UTF-8

OS name: "linux", version: "4.9.38-16.35.amzn1.x86_64", arch: "amd64", family: "unix"


------------------

<참고자료>

리눅스 버전 확인

https://zetawiki.com/wiki/%EB%A6%AC%EB%88%85%EC%8A%A4_%EC%A2%85%EB%A5%98_%ED%99%95%EC%9D%B8,_%EB%A6%AC%EB%88%85%EC%8A%A4_%EB%B2%84%EC%A0%84_%ED%99%95%EC%9D%B8

AMI에 JDK 1.8 설치

http://blog.naver.com/PostView.nhn?blogId=typez&logNo=221020775376&redirect=Dlog&widgetTypeCall=true

스칼라 및 스파크 설치

http://www.w3ii.com/ko/apache_spark/apache_spark_installation.html

카프카 설치

http://www.popit.kr/kafka-%EC%9A%B4%EC%98%81%EC%9E%90%EA%B0%80-%EB%A7%90%ED%95%98%EB%8A%94-%EC%B2%98%EC%9D%8C-%EC%A0%91%ED%95%98%EB%8A%94-kafka/

https://blog.knoldus.com/2017/04/19/installing-and-running-kafka-on-aws-instance-centos/

몽고디비 설치

http://chichi.space/2017/05/12/%ED%95%9C%EB%B2%88%EC%97%90-%EB%81%9D%EB%82%B4%EB%8A%94-AWS-EC2%EC%97%90-MongoDB-%EC%84%A4%EC%B9%98%ED%95%98%EA%B3%A0-%EB%B3%B4%EC%95%88%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0/

레디스 설치

http://mygumi.tistory.com/133

웹 프론트 개발 환경 구축

http://tbang.tistory.com/123

Node.js 최신 버전 설치

http://goosia.com/?p=85

NPM 최신 버전 설치

https://askubuntu.com/questions/562417/how-do-you-update-npm-to-the-latest-version

$ npm -v
2.15.1
$ sudo npm update -g npm
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
npm@3.10.9 /usr/local/lib/node_modules/npm
$ npm -v
3.10.9

Maven 설치

http://bhargavamin.com/how-to-do/install-jenkins-on-amazon-linux-aws/

sudo yum install -y git  java-1.8.0-openjdk-devel aws-cli

sudo alternatives --config java

sudo wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo

sudo sed -i s/\$releasever/6/g /etc/yum.repos.d/epel-apache-maven.repo

sudo yum install -y apache-maven

mvn –v

AWS EC2 t2.micro Swap 할당하는 방법

https://m.blog.naver.com/PostView.nhn?blogId=sory1008&logNo=220808623133&proxyReferer=https%3A%2F%2Fwww.google.co.kr%2F

$ dd if=/dev/zero of=/swapfile bs=1M count=1024 $ mkswap /swapfile $ swapon /swapfile $ echo "/swapfile swap swap defaults 0 0" >> /etc/fstab



출처: http://nashorn.tistory.com/623 [나숑의 법칙]

'연구개발 > Linux' 카테고리의 다른 글

VirtualEnv Wrapper를 이용한 파이썬 가상환경 설정  (0) 2017.04.05
centos fdisk  (0) 2017.03.30
ubuntu 방화벽  (0) 2016.03.14
zabbix mail setting  (0) 2016.03.03
swap  (0) 2016.03.02

import numpy as np
x = np.array([
[[2, 3, 1, 0],[12, 13, 11, 10],[22, 23, 21, 20]],
[[32, 33, 31, 30],[42, 43, 41, 40],[52, 53, 51, 50]]
])
print('x:', x)
print('x.shape:', x.shape)

X1 = x[:, np.newaxis, 1] # 모든 행에서 1열 값을 가져오고(행이됨), 축을 추가한다(열이됨)
print('X1:', X1)
print('X1.shape:', X1.shape)

X2 = x[:, 1, np.newaxis] # x[:, np.newaxis, 1]과 동일
print('X2:', X2)
print('X2.shape:', X2.shape)

X3 = x[1, np.newaxis, :] # 1행에서 모든 열값을 가져온다 (축추가로 열값이됨)
print('X3:', X3)
print('X3.shape:', X3.shape)

X4 = x[1, :, np.newaxis] # 1행에서 모든 열값을 가져온다 ( 축 추가로 행값이됨 )
print('X4:', X4)
print('X4.shape:', X4.shape)

X5 = x[:, np.newaxis] # 차원추가? 열추가?
print('X5:', X5)
print('X5.shape:', X5.shape)


from matplotlib import font_manager, rc
font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)



import numpy as np
import re
from nltk.corpus import stopwords
stop = stopwords.words('english')
def tokenizer(text):
text = re.sub('<[^>]*>', '', text)
emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower())
text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
tokenized = [w for w in text.split() if w not in stop]
return tokenized

# generator 함수 stream_docs를 정의해서 한 번에 문서 하나를 읽어들이고 반환시키도록 한다.
def stream_docs(path):
with open(path, 'r', encoding='utf-8') as csv:
next(csv)
for line in csv:
text, label = line[:-3], int(line[-2])
yield text, label

# 테스트로 movie_data.csv 파일의 첫 번째 문서를 읽어보자
print(next(stream_docs(path='movie_data.csv')))

# stream_docs 함수로부터 문서 스트림을 읽어들이고 size파라미터에 특정 문서의 숫자를 반환하는
# get_minibatch 함수를 정의
def get_minibatch(doc_stream, size):
docs, y = [], []
try:
for _ in range(size):
text, label = next(doc_stream)
docs.append(text)
y.append(label)
except StopIteration:
return None, None
return docs, y

from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.linear_model import SGDClassifier
vect = HashingVectorizer(decode_error='ignore', n_features=2**21, preprocessor=None, tokenizer=tokenizer)
clf = SGDClassifier(loss='log', random_state=1, n_iter=1)
doc_stream = stream_docs(path='movie_data.csv')

import pyprind
pbar = pyprind.ProgBar(45)
classes = np.array([0, 1])
for _ in range(45):
X_train, y_train = get_minibatch(doc_stream, size=1000)
if not X_train:
break
X_train = vect.transform(X_train)
clf.partial_fit(X_train, y_train, classes=classes)
pbar.update()

X_test, y_test = get_minibatch(doc_stream, size=5000)
X_test = vect.transform(X_test)
print('Accuarcy: %.3f' % clf.score(X_test, y_test))

clf = clf.partial_fit(X_test, y_test)

'''
머신러닝 모델을 웹 어플리케이션에 임베트하는 방법으로
데이터를 실시간으로 학습하는 방법을 익혀보자.
'''

# 피팅된 사이킷런 에스티메이터 직렬화
import pickle
import os

dest = os.path.join('movieclassifier', 'pkl_objects')
if not os.path.exists(dest):
os.makedirs(dest)

pickle.dump(stop, open(os.path.join(dest, 'stopwords.pkl'), 'wb'), protocol=4)
pickle.dump(clf, open(os.path.join(dest, 'classifier.pkl'), 'wb'), protocol=4)

# vectorizer.py
from sklearn.feature_extraction.text import HashingVectorizer
import re
import os
import pickle

cur_dir = os.path.dirname(__file__)
stop = pickle.load(open(os.path.join(cur_dir, 'pkl_objects', 'stopwords.pkl'), 'rb'))

def tokenizer(text):
text = re.sub('<[^>]*>', '', text)
emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower())
text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
tokenized = [w for w in text.split() if w not in stop]
return tokenized

vect = HashingVectorizer(decode_error='ignore', n_features=2**21, preprocessor=None, tokenizer=tokenizer)


import pickle
import re
import os
#from vectorizer import vect
clf = pickle.load(open(os.path.join('pkl_objects', 'classifier.pkl'), 'rb'))


import numpy as np
label = {0:'negative', 1:'positive'}
example = ['I love this movie']
X = vect.transform(example)
print('Prediction: %s\nProbaility: %.2f%%' % (label[clf.predict(X)[0]], np.max(clf.predict_proba(X))*100))


pbar.py
import pyprind
import pandas as pd
import os
pbar = pyprind.ProgBar(50000)
labels = {'pos':1, 'neg':0}

df = pd.DataFrame()
'''
for s in ('test', 'train'):
for l in ('pos', 'neg'):
path = './aclImdb/%s/%s' % (s, l)
for file in os.listdir(path):
with open(os.path.join(path, file), 'r', encoding='utf-8') as infile:
txt = infile.read()
df = df.append([[txt, labels[l]]], ignore_index=True)
pbar.update()

df.columns = ['review', 'sentiment']

import numpy as np
np.random.seed(0)
df = df.reindex(np.random.permutation(df.index))
df.to_csv('./movie_data.csv', index=False)
'''
df = pd.read_csv('./movie_data.csv')
print('df.head(3):\n', df.head(3))
# pbar 실행

# 단어를 피처 벡터로 변환
import pandas as pd
import numpy as np
df = pd.DataFrame()
df = pd.read_csv('./movie_data.csv')
print('df.head(3):\n', df.head(3))

from sklearn.feature_extraction.text import CountVectorizer
count = CountVectorizer()
docs = np.array([
'The sun is shining',
'The weather is sweet',
'The sun is shining and the weather is sweet'
])
bag = count.fit_transform(docs)

print(count.vocabulary_)
print(bag.toarray())

'''
nd는 문서의 전체 개수, df(d,t)는 용어 t를 포함하는 문서 d의 개수
'''
from sklearn.feature_extraction.text import TfidfTransformer
tfidf = TfidfTransformer()
np.set_printoptions(precision=2)
print(tfidf.fit_transform(count.fit_transform(docs)).toarray())

print(df.loc[0, 'review'][-50:])

import re
def preprocessor(text):
text = re.sub('<[^>]*>', '', text)
emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text)
text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
return text

print(preprocessor(df.loc[0, 'review'][-50:]))
print(preprocessor("</a>This :) is :( a test :-)!"))

# 모든 영화 리뷰에 적용
df['review'] = df['review'].apply(preprocessor)

# 문서를 토큰으로 처리하기
def tokenizer(text):
return text.split()
print('tokenizer:\n', tokenizer('running like running and thus they run'))

from nltk.stem.porter import PorterStemmer
porter = PorterStemmer()

def tokenizer_porter(text):
return [porter.stem(word) for word in text.split()]

print('tokenizer_porter("runners like running and thus they run"):\n'
, tokenizer_porter('runners like running and thus they run'))

'''
불용어(stop-word) : 모든 종류의 텍스트에서 공통으로 많이 사용되는 단어들로 문서의 다른 종류들을 구별하는 데
유용할 만한 정보를 거의 가지고 있지 않은 (혹은 아주 조금만 가지고 있는) 경우를 말한다.
불용어의 예로는 is, and, has 같은 것들이 있다.
'''
import nltk
nltk.download('stopwords')

from nltk.corpus import stopwords
stop = stopwords.words('english')
[print(w) for w in tokenizer_porter('a runner likes running and runs a lot')[-10:] if w not in stop]

# 문서 분류를 위한 로지스틱 회귀 모델 훈련
X_train = df.loc[:25000, 'review'].values
y_train = df.loc[:25000, 'sentiment'].values
X_test = df.loc[25000:, 'review'].values
y_test = df.loc[25000:, 'sentiment'].values

# GridSearchCV 오브젝트를 사용하여 5-폴드(5-fold) 충화 교차검증을
# 사용하는 이번 로지스틱 회귀 모델에 대한 최적의 파라미터 세트를 찾아보자
from sklearn.grid_search import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(strip_accents=None, lowercase=False, preprocessor=None)
param_grid = [{'vect__ngram_range': [(1,1)],
'vect__stop_words': [stop, None],
'vect__tokenizer': [tokenizer, tokenizer_porter],
'clf__penalty': ['l1', 'l2'],
'clf__C': [1.0, 10.0, 100.0]},
{'vect__ngram_range': [(1,1)],
'vect__stop_words': [stop, None],
'vect__tokenizer': [tokenizer, tokenizer_porter],
'vect__use_idf': [False],
'vect__norm': [None],
'clf__penalty': ['l1', 'l2'],
'clf__C': [1.0, 10.0, 100.0]}]
lr_tfidf = Pipeline([('vect', tfidf),
('clf', LogisticRegression(random_state=0))])
gs_lr_tfidf = GridSearchCV(lr_tfidf, param_grid, scoring='accuracy', cv=5, verbose=1, n_jobs=1)
gs_lr_tfidf.fit(X_train, y_train)
print('Best parameter set : %s ' % gs_lr_tfidf.best_params_)

print('CV Accuracy: %.3f' % gs_lr_tfidf.best_score_)
clf = gs_lr_tfidf.best_estimator_
print('Test Accuracy: %.3f' % clf.score(X_test, y_test))
import numpy as np
import re
from nltk.corpus import stopwords
stop = stopwords.words('english')
def tokenizer(text):
text = re.sub('<[^>]*>', '', text)
emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text.lower())
text = re.sub('[\W]+', ' ', text.lower()) + ' '.join(emoticons).replace('-', '')
tokenized = [w for w in text.split() if w not in stop]
return tokenized

# generator 함수 stream_docs를 정의해서 한 번에 문서 하나를 읽어들이고 반환시키도록 한다.
def stream_docs(path):
with open(path, 'r', encoding='utf-8') as csv:
next(csv)
for line in csv:
text, label = line[:-3], int(line[-2])
yield text, label

# 테스트로 movie_data.csv 파일의 첫 번째 문서를 읽어보자
print(next(stream_docs(path='./machinelearning/movie_data.csv')))

# stream_docs 함수로부터 문서 스트림을 읽어들이고 size파라미터에 특정 문서의 숫자를 반환하는
# get_minibatch 함수를 정의
def get_minibatch(doc_stream, size):
docs, y = [], []
try:
for _ in range(size):
text, label = next(doc_stream)
docs.append(text)
y.append(label)
except StopIteration:
return None, None
return docs, y

from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.linear_model import SGDClassifier
vect = HashingVectorizer(decode_error='ignore', n_features=2**21, preprocessor=None, tokenizer=tokenizer)
clf = SGDClassifier(loss='log', random_state=1, n_iter=1)
doc_stream = stream_docs(path='./machinelearning/movie_data.csv')

import pyprind
pbar = pyprind.ProgBar(45)
classes = np.array([0, 1])
for _ in range(45):
X_train, y_train = get_minibatch(doc_stream, size=1000)
if not X_train:
break
X_train = vect.transform(X_train)
clf.partial_fit(X_train, y_train, classes=classes)
pbar.update()

X_test, y_test = get_minibatch(doc_stream, size=5000)
X_test = vect.transform(X_test)
print('Accuarcy: %.3f' % clf.score(X_test, y_test))

clf = clf.partial_fit(X_test, y_test)


고가용성(HA) :  서버와 네트워크, 프로그램 등의 정보 시스템이 상당히 오랜 기간 동안 지속적으로 정상 운영이 가능한 성질로

고(高)가용성이란 "가용성이 높다"는 뜻으로서, "절대 고장 나지 않음"을 의미한다.

고가용성은 흔히 가용한 시간의 비율을 99%, 99.9% 등과 같은 퍼센티지로 표현하는데, 1년에 계획 된 것 제외 5분 15초 이하의 장애시간을 허용한다는 의미의 파이브 나인스(5 nines), 즉 99.999%는 매우 높은 수준으로 고품질의 데이터센터에서 목표로 한다고 알려져 있다.

하나의 정보 시스템에 고가용성이 요구된다면, 그 시스템의 모든 부품과 구성 요소들은 미리 잘 설계되어야 하며, 실제로 사용되기 전에 완전하게 시험되어야 한다.

고가용성 솔루션(HACMP)을 이용하면, 각 시스템 간에 공유 디스크를 중심으로 집단화하여 클러스터로 엮어지게 만들 수 있다. 동시에 다수의 시스템을 클러스터로 연결할 수 있지만 주로 2개의 서버를 연결하는 방식을 많이 사용한다. 만약 클러스터로 묶인 2개의 서버 중 1대의 서버에서 장애가 발생할 경우, 다른 서버가 즉시 그 업무를 대신 수행하므로, 시스템 장애를 불과 몇 초만에 복구할 수 있다.


위와 같은 목적을 가지고 MySQL에서도 HA구성을 하게 되는데, 대표적으로 MHA(MasterHA)와 MySQL Fabric, MtoM이 있다.

제가 MySQL을 HA로 구성한 방법은 MHA이다.

MySQL Fabric보다 나아서라기보다는 기존의 MySQL 장비에 추가적인 작업 없이 HA를 구성할 수 있었으면 하고

MtoM은 IP에 대한 부분이 IP스위치가 어렵고 MHA는 자동으로 IP가 변경할 수 있기에 MHA로 구성을 해 보았다.


구성은 IP도 할당해야하고 대수도 여러대 필요하기 때문에 AWS에서 테스트를 해보았다.

호스트명

IP

bastion_server

172.31.2.124

mha_manager

172.31.13.97

my_master

172.31.9.88, 172.31.0.79

my_slave1

172.31.6.249

my_slave2

172.31.4.175

bastion_server는 AWS로 들어가는 진입통로이다. 나는 AWS를 접근할 때 처음 통로를 Bastion_server로 놓고 해당 서버에만

EIP를 주어 접속할 수 있게 해놓았다. 그리고 bastion_server에 pem파일을 올려 모든 서버는 bastion_server를 통해

접근하도록 설정되어 있다.

mha_manager는 모든 my_master의 장애를 모니터링하고 장애시 my_slave2가 master로써 승격되고 my_slave1은 기존 my_master에서 my_slave2에 동기화된다.  (bastion_server는 굳이 구성할 때 없어도 되는 서버이다.)







1. 기본 모듈 설치

[manager/master/slave1/slave2]

MHA Perl 모듈로 동작하기 때문에 펄 관련 모듈 설치

yum install -y perl-DBD-MySQL

yum install -y perl-Config-Tiny

yum install -y perl-Params-Validate

yum install -y perl-Parallel-ForkManager

yum install -y perl-Log-Dispatch

yum install -y perl-Time-HiRes

yum install -y perl-ExtUtils-MakeMaker

yum install -y perl-CPAN

 

#perl -MCPAN -e "install Config::Tiny"

#perl -MCPAN -e "install Log::Dispatch"

#perl -MCPAN -e "install Parallel::ForkManager"


2. MHA 노드 설치

[manager/master/slave/slave2]

https://code.google.com/p/mysql-master-ha/wiki/Downloads?tm=2/

mha4mysql-node-0.56.tar.gz download

mha4mysql-manager-0.56.tar.gz download


bastion_server 접속

sftp -o IdentityFile=/key_pair/XXXX.pem ec2-user@172.31.9.88

put mha4mysql-node-0.56.tar.gz

 

sftp -o IdentityFile=/key_pair/XXXX.pem ec2-user@172.31.6.249

put mha4mysql-node-0.56.tar.gz

 

sftp -o IdentityFile=/key_pair/XXXX.pem ec2-user@172.31.4.175

put mha4mysql-node-0.56.tar.gz

 

sftp -o IdentityFile=/key_pair/XXXX.pem ec2-user@172.31.13.97

put mha4mysql-node-0.56.tar.gz

put mha4mysql-manager-0.56.tar.gz

 

tar xvzf mha4mysql-node-0.56.tar.gz

cd mha4mysql-node-0.56

perl Makefile.PL

make

make install


3. MHA 매니저 설치

[manager]

mha_manager서버에 mha4mysql-manager 파일 설치

mkdir /data/mha_manager

cd /data/mha_manager

tar xvzf mha4mysql-manager-0.56.tar.gz

cd mha4mysql-manager-0.56

perl Makefile.PL

==> Auto-install the 1 mandatory module(s) from CPAN? [y] y

 

make

Would you like to configure as much as possible automatically? [yes]

CPAN build and cache directory? [/root/.cpan]

Download target directory? [/root/.cpan/sources]

Directory where the build process takes place? [/root/.cpan/build]

Always commit changes to config variables to disk? [no]

Cache size for build directory (in MB)? [100]

Let the index expire after how many days? [1]

Cache metadata (yes/no)? [yes]

Use CPAN::SQLite if available? (yes/no)? [no]

Policy on installing 'build_requires' modules (yes, no, ask/yes,

ask/no)? [yes]

Always try to check and verify signatures if a SIGNATURE file is in

the package and Module::Signature is installed (yes/no)? [no]

Generate test reports if CPAN::Reporter is installed (yes/no)? [no]

Do you want to rely on the test report history (yes/no)? [no]

Which YAML implementation would you prefer? [YAML]

Do you want to enable code deserialisation (yes/no)? [no]

<make>

Where is your make program? [/usr/bin/make]

 <bzip2>

Where is your bzip2 program? [/usr/bin/bzip2]

 <gzip>

Where is your gzip program? [/bin/gzip]

 <tar>

Where is your tar program? [/bin/tar]

Would you like to configure as much as possible automatically? [yes]

Would you like me to automatically choose some CPAN mirror

sites for you? (This means connecting to the Internet) [yes]

 

make install


4. SSH 설정

[manager/master/slave1/slave2]

모든 IP에 서로 SSH 접근이 가능하도록 추가해준다.

(AWS에서는 security_group에 22번 포트를 열어줌으로써 아래와 같은 작업이 불필요하다.)

vi /etc/hosts.allow

# for MHA

sshd: 172.31.2.124,172.31.1.164,172.31.4.134,172.31.4.134,172.31.0.79


[master/slave1/slave2]

MHA구성으로 사용한 시스템계정 생성

useradd -g mysql -d /home/mhauser -m -s /bin/bash mhauser

cat /etc/passwd | grep mhauser

 

passwd mhauser

패스워드 설정


[manager]

mha_manager 서버에도 시스템계정 생성

groupadd mysql

useradd -r -g mysql mysql

useradd -g mysql -d /home/mhauser -m -s /bin/bash mhauser

cat /etc/passwd | grep mhauser

 

passwd mhauser

 

[manager/master/slave1/slave2]

mhauser에 대한 SSH key파일 설정

su - mhauser

ssh-keygen

Generating public/private rsa key pair.

Enter file in which to save the key (/home/mhauser/.ssh/id_rsa):

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/mhauser/.ssh/id_rsa.

Your public key has been saved in /home/mhauser/.ssh/id_rsa.pub.

The key fingerprint is:

XXXX mhauser@bastion_server

 

cat /home/mhauser/.ssh/id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+Y1teVMIZF3K9X8LjEoHYpV9EFAusugbpXQB3pub8kZ

mhauser@bastion_server

 

 

manager, master, slave1, slave2 서버의 id_rsa.pub 파일을 각각 복사해 서버의 authorized_keys

파일에 붙여 넣는다.

 

cat /root/.ssh/authorized_keys

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+… mhauser@mha_manager

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDWqz+… mhauser@my_master

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCaeQE+… mhauser@my_slave1

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCg6QU… mhauser@my_slave2

 

 

[manager/master/slave/slave2]

해당 서버에 SSH 접속을 원활하게 하기 위해 /etc/hosts파일에 아래와 같이 내용을 추가한다.

그리고 .ssh 디렉토리 내의 파일에 대한 모든 권한을 변경한다.

(root계정으로 실행)

vi /etc/hosts

172.31.2.124

172.31.2.124 bastion_server

172.31.13.97

172.31.13.97 mha_manager

172.31.9.88

172.31.9.88  my_master

172.31.0.79

172.31.0.79 my_master

172.31.6.249

172.31.6.249 my_slave1

172.31.4.175

172.31.4.175 my_slave2

 

cd .ssh/

chmod 600 *

 

접속테스트(mhauser로 접속한 상태에서 테스트)

각 서버마다 접속해서 아래와 같이 전부 접속 테스트를 해준다.

ssh 172.31.2.124 hostname

ssh 172.31.13.97 hostname

ssh 172.31.9.88 hostname

ssh 172.31.0.79 hostname

ssh 172.31.6.249 hostname

ssh 172.31.4.175 hostname

 

아래와 같은 메시지가 나오면 yes를 누른다.

다음에 실행 시해당 IP 호스트명만 출력된다.

[mhauser@my_slave2 .ssh]$ ssh 172.31.4.175 hostname

The authenticity of host '172.31.4.175 (172.31.4.175)' can't be established.

ECDSA key fingerprint is 49:c7:ae:1c:90:1a:b1:a1:d1.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '172.31.4.175' (ECDSA) to the list of known hosts.

my_slave2

[mhauser@my_slave2 .ssh]$ ssh 172.31.4.175 hostname

my_slave2

 

[master/slave1/slave2]

sudo 권한에 변경작업을 해준다.

root계정 접속

 

visudo

#Default requiretty

 

mhauser ALL=(ALL) NOPASSWD:/sbin/ifconfig

 

[master]

my_master 서버에 서비스로 쓰이는 IP 하나를 할당해준다.

vip 할당

ifconfig eth0:0 172.31.0.79 netmask 255.255.0.0 broadcast 172.31.0.255 up

5. DB접속 계정 생성

[master/slave1/slave2]

MHA 매니저 서버(배스천)에서는 모든 DB서버의 MySQL에 접속할 수 있어야 한다.

/mysql/bin/mysql -uroot -p

grant all on *.* to mhauser@'172.31.2.124' identified by 'XXXXXXXX';

grant all on *.* to mhauser@'172.31.13.97' identified by 'XXXXXXXX';

grant all on *.* to mhauser@'172.31.0.79' identified by 'XXXXXXXX';

grant all on *.* to mhauser@'172.31.9.88' identified by 'XXXXXXXX';

grant all on *.* to mhauser@'172.31.6.249' identified by 'XXXXXXXX';

grant all on *.* to mhauser@'172.31.4.175' identified by 'XXXXXXXX';


[master/slave2]

master의 repl 계정 권한을 마스터 대체서버(slave2)에도 동일하게 적용

GRANT REPLICATION SLAVE, REPLICATION CLIENT

ON *.* TO 'repl'@'172.31.6.249' IDENTIFIED BY PASSWORD 'XXXXXXXX';

GRANT REPLICATION SLAVE, REPLICATION CLIENT

ON *.* TO 'repl'@'172.31.4.175' IDENTIFIED BY PASSWORD 'XXXXXXXX';

flush privileges;



6. MHA 설정

* master 대체 slave서버의 주의사항

- mysqlbinlog 버전이 5.1이상이어야 한다. master의 binlog가 row 포맷이면 mysqlbinlog 5.1부터는

  분석이 가능하다. 만약 5.1보다 낮으면 동기화시 row포맷을 사용해서는 안된다.

- DB서버의 binlog에 접근할 수 있게 디렉토리 권한을 설정해야 한다.

   (저는 mhauser를 mysql 그룹으로 묶어서 mysql이 접근가능한 디렉토리는 mhauser도 접근 가능하게 하였다.)

- 새로운 master가 될 slave에 binlog가 횔성화 되어 있어야 한다.(log-bin)

   (저는 log-bin 뿐만 아니라 log-bin=경로/파일명 이렇게하여 마스터와 동일한 경로와 파일명이 생기도록 하였다.)

- binlog와 relay log의 필터 규칙이 모든 MySQL DB군에서 동일해야 한다.

  즉, binlog에 대해 binlog-db-db나 replicate-ignore-db와 같은 필터 규칙이 정의되어 있다면 모든 MySQL은

  동일하게 해줘야 한다.

새로운 master가 될 slave에 read_only로 읽기 전용으로만 해두는 것이 나중에 교체시 문제를 최소화 시킬 수 있다.


[manager]

MHA를 사용하기 위한 디렉토리 생성

mkdir /data/mha_log                              ## mha 로그파일 저장

mkdir /data/mha_app                             ## mha 실행시 failover 프로그램 저장

mkdir /data/mha_scripts                           ## mha 스크립트 저장

chown mhauser:mysql /data/mha_log

chown mhauser:mysql /data/mha_app

chown mhauser:mysql /data/mha_scripts


7. MHA 매니저 서버 설정파일

* 싱글모드로 설정하여 테스트를 진행하였다.

1) 싱글모드

vi /etc/mha-manager.cnf

[server default]

user=mhauser

password=XXXXXXXX

repl_user=repl

repl_password=XXXXXXXX

 

## mha manager 실행파일이 생길 폴더 지정

manager_workdir=/data/mha_app

## 로그파일 지정

manager_log=/data/mha_log/mha4mysql.log

 

## mysql서버에 실행파일이 생길 폴더 지정

remote_workdir=/data/mha_app

## binlog 파일 폴더 지정

master_binlog_dir=/mysql/var

 

## mysql서버의 mysql 실행파일 폴더 지정

client_bindir=/mysql/bin

## mysql서버의 mysql 라이브러리가 저장되어 있는 폴더 지정

client_libdir=/mysql/lib

ignore_fail=2

 

[server1]

hostname = 172.31.9.88                     ## my_master ip

candidate_master=1

 

[server2]

hostname = 172.31.4.175                  ## replace slave2 ip

candidate_master=1

 

[server3]

hostname = 172.31.6.249                   ## slave1 ip

no_master=1


2) 다중모드

[manager]

vi /etc/mha-manager.cnf

[server default]

user=mhauser

password=XXXXXXXX

ssh_user=mhauser

 

master_binlog_dir=/mysql/var

remote_workdir=/data/mha_app

secondary_check_script= masterha_secondary_check -s remote_host1 -s remote_host2

ping_interval=3

master_ip_failover_script=/data/mha_script/master_ip_failover

shutdown_script=/data/mha_script/power_manager

report_script=/data/mha_script/send_master_failover_mail


vi /etc/my_master.cnf

[server_default]

manager_workdir=/data/mha_app

manager_log=/data/mha_log/mha4mysql.log

 

[server1]

hostname = 172.31.9.88                     ## my_master ip

candidate_master=1

 

[server2]

hostname = 172.31.4.175                  ## replace slave2 ip

candidate_master=1

 

[server3]

hostname = 172.31.6.249                   ## slave1 ip

no_master=1


[master]

할당된 IP 설정을 확인한다.

 

ifconfig

eth0      Link encap:Ethernet  HWaddr 02:8C:A2: 

          inet addr:172.31.9.88  Bcast:172.31.15.255  Mask:255.255.240.0

          inet6 addr: fe80::8c:a2ff:fe61:c841/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

          RX packets:106222 errors:0 dropped:0 overruns:0 frame:0

          TX packets:77495 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:112547338 (107.3 MiB)  TX bytes:11160527 (10.6 MiB)

 

eth0:0    Link encap:Ethernet  HWaddr 02:8C: 

          inet addr:172.31.0.79  Bcast:172.31.0.255  Mask:255.255.0.0

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

 

lo        Link encap:Local Loopback 

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:65536  Metric:1

          RX packets:65 errors:0 dropped:0 overruns:0 frame:0

          TX packets:65 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1

          RX bytes:10938 (10.6 KiB)  TX bytes:10938 (10.6 KiB)

 

 


활성화

ifconfig eth0:0 172.31.0.79 netmask 255.255.0.0 broadcast 172.31.0.255 down


8. MHA모니터링 시작하기

mha 기동

cd /data/mha4mysql-manager-0.56/bin

nohup masterha_manager --conf=/etc/mha-manager.cnf < /dev/null > /data/mha_log/mha4mysql.log 2>&1 &


중단

/data/mha/mha4mysql-manager-0.56/bin/masterha_stop --conf=/etc/mha_manager.cnf


masterha_check_status로 masterha_manager 모니터링

 

./masterha_check_status --conf=/etc/mha-manager.cnf

mha-manager (pid:18325) is running(0:PING_OK), master:172.31.1.164

 

 


ssh접속이 정상적으로 이루어지는지 확인

 

masterha_check_ssh --conf=/etc/mha-manager.cnf

Thu Jan  5 08:02:14 2017 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.

Thu Jan  5 08:02:14 2017 - [info] Reading application default configuration from /etc/mha-manager.cnf..

Thu Jan  5 08:02:14 2017 - [info] Reading server configuration from /etc/mha-manager.cnf..

Thu Jan  5 08:02:14 2017 - [info] Starting SSH connection tests..

Thu Jan  5 08:02:15 2017 - [debug]

Thu Jan  5 08:02:16 2017 - [debug]   ok.

Thu Jan  5 08:02:16 2017 - [info] All SSH connection tests passed successfully.

 

 


리플리케이션 상태 모니터링

./masterha_check_repl --conf=/etc/mha-manager.cnf

MySQL Replication Health is OK.

 

 


호스트 정보 관리(IP추가)

./masterha_conf_host --command=add --conf=/etc/mha-manager.cnf --hostname=XXX.XXX.XXX.XXX

옵션 : --command=(add/delete)


[slave2]

slave2에 릴레이로그는 mysql 설치시 적용후 자동삭제하게 되어 있다.

master 대체 서버이기 때문에 릴레이로그를 purge하는 것을 중단하고 크론탭에 새벽에 자동 삭제할 수

있게 걸어 놓는다.

/mysql/bin/mysql -uroot -p

set global relay_log_purge=0

릴레이로그 삭제 설정

vi /etc/crontab

0 5 * * * /usr/local/bin/purge_relay_logs --user=root --disable_relay_log_purge >> /data/mha_log/purge_relay_logs.log 2>&1

 

 


9. 스크립트 생성

1) 스위치오버 시 vip도 자동으로 스위치 오버하는 스크립트 생성(root계정으로 실행)

cd /data/mha4mysql-manager-0.56/samples/scripts

cp master_ip_online_change master_ip_online_change.org

chown mhauser:mysql master_ip_online_change

vi master_ip_online_change

## Drop application user so that nobody can connect. Disabling per-session binlog beforehand

## $orig_master_handler->disable_log_bin_local();

## print current_time_us() . " Drpping app user on the orig master..\n";

## FIXME_xxx_drop_app_user($orig_master_handler);

 

## Creating an app user on the new master

      ## print current_time_us() . " Creating app user on the new master..\n";

      ## FIXME_xxx_create_app_user($new_master_handler);

      ## $new_master_handler->enable_log_bin_local();

      ## $new_master_handler->disconnect();

## =========================================================

## vip Change

if ( $new_master_ip eq "172.31.1.164") {

        system("/bin/sh /mysql/mha/scripts/change_vitual_ip_slave_to_master.sh");

}

elsif ( $new_master_ip eq "172.31.15.118") {

        system("/bin/sh /mysql/mha/scripts/change_vitual_ip_master_to_slave.sh");

}

else {}

## ========================================================

 

cd /data/mha_scripts/

vi change_virtual_ip_master_to_slave.sh

#!/bin/sh

 

ssh mhauser@172.31.15.118 sudo /sbin/ifconfig eth0:0 down

ssh mhauser@172.31.1.164 sudo /sbin/ifconfig eth0:0 172.31.0.79 netmask 255.255.0.0 broadcast 172.31.0.255 up

 

vi change_virtual_ip_slave_to_master.sh

#!/bin/sh

 

ssh mhauser@172.31.4.175 sudo /sbin/ifconfig eth0:0 down

ssh mhauser@172.31.9.88 sudo /sbin/ifconfig eth0:0 172.31.0.79 netmask 255.255.0.0 broadcast 172.31.0.255 up

 

vi /etc/mha-manager.cnf

master_ip_online_change_script=/data/mha_scripts/master_ip_online_change

 

 

 

2) 페일오버 시 vip도 자동으로 페일오버하는 스크립트

cd /data/mha4mysql-manager-0.56/samples/scripts

cp master_ip_failover /data/mha_scripts/

cd /data/mha_scripts/

chown mhauser:mysql master_ip_failover

 

vi master_ip_failover

## Creating an app user on the new master

## print "Creating app user on the new master..\n";

## FIXME_xxx_create_user( $new_master_handler->{dbh} );

## $new_master_handler->enable_log_bin_local();

## $new_master_handler->disconnect();

 

      ## Update master ip on the catalog database, etc

      #IXME_xxx;

## vip change

system("/bin/sh /data/mha_scripts/change_virtual_ip.sh");

 

vi change_virtual_ip.sh

#!/bin/sh

 

ssh mhauser@172.31.9.88 sudo /sbin/ifconfig eth0:0 down # master DB server vip down

ssh mhauser@172.31.4.175 sudo /sbin/ifconfig eth0:0 172.31.0.79 netmask 255.255.0.0 broadcast 172.31.0.255 up

 

vi /etc/mha-manager.cnf

master_ip_failover_script=/data/mha_scripts/master_ip_failover

 

cd /data/mha_scripts

chown mhauser:mysql *

 

 

 

10. 테스트

1) 상태확인

[master]

my_master 서버는 read 전용이 아니며 아래와 같은 master 상태값을 가지고 있다.

mysql> show variables like 'read_only';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| read_only     | OFF   |

+---------------+-------+

1 row in set (0.01 sec)

 

mysql> show master status;

+------------------+----------+--------------+--------------------------------------------------+-------------------+

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB                       | Executed_Gtid_Set |

+------------------+----------+--------------+--------------------------------------------------+-------------------+

| mysql-bin.000004 |   120 |             | mysql,test,information_schema,performance_schema |          |

+------------------+----------+--------------+--------------------------------------------------+-------------------+

1 row in set (0.00 sec)

 

 

ifconfig

eth0      Link encap:Ethernet  HWaddr 02:8C:A2:61 

          inet addr:172.31.9.88  Bcast:172.31.15.255  Mask:255.255.240.0

          inet6 addr: fe80::8c:a2ff:fe61:c841/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

          RX packets:112357 errors:0 dropped:0 overruns:0 frame:0

          TX packets:82278 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:113169520 (107.9 MiB)  TX bytes:11858827 (11.3 MiB)

 

eth0:0    Link encap:Ethernet  HWaddr 02:8C:A2: 

          inet addr:172.31.0.79  Bcast:172.31.0.255  Mask:255.255.0.0

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

 

lo        Link encap:Local Loopback 

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:65536  Metric:1

          RX packets:138 errors:0 dropped:0 overruns:0 frame:0

          TX packets:138 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1

          RX bytes:27398 (26.7 KiB)  TX bytes:27398 (26.7 KiB)

 

 

 

[slave1]

my_slave1은 현재 my_master(172.31.9.88) master로써 동기화하고 있다.

mysql> show slave status \G;

Slave_IO_State: Waiting for master to send event

                  Master_Host: 172.31.9.88

                  Master_User: repl

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000005

          Read_Master_Log_Pos: 120

               Relay_Log_File: my_slave1-relay-bin.000009

                Relay_Log_Pos: 283

        Relay_Master_Log_File: mysql-bin.000005

             Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

              Replicate_Do_DB:

          Replicate_Ignore_DB:

           Replicate_Do_Table:

       Replicate_Ignore_Table:

      Replicate_Wild_Do_Table:

  Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

          Exec_Master_Log_Pos: 120

              Relay_Log_Space: 623

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

           Master_SSL_Allowed: No

           Master_SSL_CA_File:

           Master_SSL_CA_Path:

              Master_SSL_Cert:

            Master_SSL_Cipher:

               Master_SSL_Key:

        Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

  Replicate_Ignore_Server_Ids:

             Master_Server_Id: 88

                  Master_UUID: b3146e4b-d3e3-11e6-b88d-028ca261c841

             Master_Info_File: /mysql/var/master.info

                    SQL_Delay: 0

          SQL_Remaining_Delay: NULL

      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it

           Master_Retry_Count: 86400

                  Master_Bind:

      Last_IO_Error_Timestamp:

     Last_SQL_Error_Timestamp:

               Master_SSL_Crl:

           Master_SSL_Crlpath:

           Retrieved_Gtid_Set:

            Executed_Gtid_Set:

                Auto_Position: 0

 

[slave2]

my_slave2 my_master 대체 슬레이브로써 읽기 전용으로만 사용되고 있고 172.31.9.88(my_master)와 동기화 되어 있다.

mysql> show variables like 'read_only';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| read_only     | ON    |

+---------------+-------+

1 row in set (0.00 sec)

 

mysql> show slave status \G;

Slave_IO_State: Waiting for master to send event

                  Master_Host: 172.31.9.88

                  Master_User: repl

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000004

          Read_Master_Log_Pos: 120

               Relay_Log_File: my_slave2-relay-bin.000006

                Relay_Log_Pos: 236

        Relay_Master_Log_File: mysql-bin.000004

             Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

              Replicate_Do_DB:

          Replicate_Ignore_DB:

           Replicate_Do_Table:

       Replicate_Ignore_Table:

      Replicate_Wild_Do_Table:

  Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

          Exec_Master_Log_Pos: 120

              Relay_Log_Space: 576

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

           Master_SSL_Allowed: No

           Master_SSL_CA_File:

           Master_SSL_CA_Path:

              Master_SSL_Cert:

            Master_SSL_Cipher:

               Master_SSL_Key:

        Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

  Replicate_Ignore_Server_Ids:

             Master_Server_Id: 88

                  Master_UUID: b3146e4b-d3e3-11e6-b88d-028ca261c841

             Master_Info_File: /mysql/var/master.info

                    SQL_Delay: 0

          SQL_Remaining_Delay: NULL

      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it

           Master_Retry_Count: 86400

                  Master_Bind:

      Last_IO_Error_Timestamp:

     Last_SQL_Error_Timestamp:

               Master_SSL_Crl:

           Master_SSL_Crlpath:

           Retrieved_Gtid_Set:

            Executed_Gtid_Set:

                Auto_Position: 0

 

[manager]

mha_manager 기동하여 위의 모든 서버들을 모니터링하게 한다.

su - mhauser

cd /data/mha4mysql-manager-0.56/bin/

nohup masterha_manager --conf=/etc/mha-manager.cnf < /dev/null > /data/mha_log/mha4mysql.log 2>&1 &

 

[master]

my_master서버에서 mysql를 kill하여 장애를 발생시킨다.

mysql kill

ps -ef | grep mysql

kill -9 22009 22921

 

위와 같이 할 경우, mha_manager서버의 /data/mha_log/mha4mysql.log파일에 마스터와 슬레이브가

스위칭 되는 로그가 남는다.

마지막에 failover report까지 나오면 스위칭이 완료된다.

 

ifconfig

eth0      Link encap:Ethernet  HWaddr 02:8C:A2:61:C8:41 

          inet addr:172.31.9.88  Bcast:172.31.15.255  Mask:255.255.240.0

          inet6 addr: fe80::8c:a2ff:fe61:c841/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

          RX packets:116549 errors:0 dropped:0 overruns:0 frame:0

          TX packets:85789 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:113678944 (108.4 MiB)  TX bytes:12379793 (11.8 MiB)

 

lo        Link encap:Local Loopback 

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:65536  Metric:1

          RX packets:138 errors:0 dropped:0 overruns:0 frame:0

          TX packets:138 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1

          RX bytes:27398 (26.7 KiB)  TX bytes:27398 (26.7 KiB)

 

[slave2]

마스터에 있던 IP정보가 my_slave2 서버에 옮겨진 것을 확인할 수 있다.

 

ifconfig

eth0      Link encap:Ethernet  HWaddr 02:59:5C:47:DC:2D 

          inet addr:172.31.4.175  Bcast:172.31.15.255  Mask:255.255.240.0

          inet6 addr: fe80::59:5cff:fe47:dc2d/64 Scope:Link

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

          RX packets:104714 errors:0 dropped:0 overruns:0 frame:0

          TX packets:60773 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1000

          RX bytes:112706859 (107.4 MiB)  TX bytes:10153218 (9.6 MiB)

 

eth0:0    Link encap:Ethernet  HWaddr 02:59:5C:47:DC:2D 

          inet addr:172.31.0.79  Bcast:172.31.0.255  Mask:255.255.0.0

          UP BROADCAST RUNNING MULTICAST  MTU:9001  Metric:1

 

lo        Link encap:Local Loopback 

          inet addr:127.0.0.1  Mask:255.0.0.0

          inet6 addr: ::1/128 Scope:Host

          UP LOOPBACK RUNNING  MTU:65536  Metric:1

          RX packets:371 errors:0 dropped:0 overruns:0 frame:0

          TX packets:371 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:1

          RX bytes:56561 (55.2 KiB)  TX bytes:56561 (55.2 KiB)

 

 

 

[slave1]

slave 상태를 확인하면 my_slave1 서버가 동기화하는 master IP가 변경된 것을 확인할 수 있다.

 

show slave status \G;

Slave_IO_State: Waiting for master to send event

                  Master_Host: 172.31.4.175

                  Master_User: repl

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000004

          Read_Master_Log_Pos: 120

               Relay_Log_File: my_slave1-relay-bin.000002

                Relay_Log_Pos: 283

        Relay_Master_Log_File: mysql-bin.000004

             Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

              Replicate_Do_DB:

          Replicate_Ignore_DB:

           Replicate_Do_Table:

       Replicate_Ignore_Table:

      Replicate_Wild_Do_Table:

  Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

          Exec_Master_Log_Pos: 120

              Relay_Log_Space: 460

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

           Master_SSL_Allowed: No

           Master_SSL_CA_File:

           Master_SSL_CA_Path:

              Master_SSL_Cert:

            Master_SSL_Cipher:

               Master_SSL_Key:

        Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

  Replicate_Ignore_Server_Ids:

             Master_Server_Id: 175

                  Master_UUID: 02244886-d3e4-11e6-b88f-02595c47dc2d

             Master_Info_File: /mysql/var/master.info

                    SQL_Delay: 0

          SQL_Remaining_Delay: NULL

      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it

           Master_Retry_Count: 86400

                  Master_Bind:

      Last_IO_Error_Timestamp:

     Last_SQL_Error_Timestamp:

               Master_SSL_Crl:

           Master_SSL_Crlpath:

           Retrieved_Gtid_Set:

            Executed_Gtid_Set:

                Auto_Position: 0

 

 

 

[manager/master/slave/slave2]

mha_manager은 이렇게 IP와 동기화 되는 부분을 자동으로 변경하고 중지된다.

/data/mha_app를 삭제하지 않으면 mha_manager 기동 시 에러가 발생한다.

 

rm -f /data/mha_app/*

* MHA 구성시 에러사항 정리 

 

Mon Jan  9 04:24:20 2017 - [error][/usr/local/share/perl5/MHA/ManagerUtil.pm, ln177] Got Error on finalize_on_error at monitor: Permission denied:/data/mha_app/mha-manager.master_status.health at /usr/local/share/perl5/MHA/MasterMonitor.pm line 633.

chown mhauser.mysql mha_app

chown mhauser.mysql mha_scripts


 

Mon Jan  9 04:29:26 2017 - [error][/usr/local/share/perl5/MHA/ManagerUtil.pm, ln122] Got error when getting node version. Error:

Mon Jan  9 04:29:26 2017 - [error][/usr/local/share/perl5/MHA/ManagerUtil.pm, ln123]

mysql에 mha4node가 설치되어 있지 않았다. 


 

Mon Jan  9 05:28:53 2017 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln158] Binlog setting check failed!

Mon Jan  9 05:28:53 2017 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln405] Master configuration failed.

Mon Jan  9 05:28:53 2017 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln424] Error happened on checking configurations.  at /u

sr/local/bin/masterha_manager line 50.

Mon Jan  9 05:28:53 2017 - [error][/usr/local/share/perl5/MHA/MasterMonitor.pm, ln523] Error happened on monitoring servers.

Mon Jan  9 05:28:53 2017 - [info] Got exit code 1 (Not master dead).

mkdir /data/mha_app 

chown mhauser.mysql /data/mha_app

[출처] MHA 구성|작성자 theswice


+ Recent posts