반응형
반응형

Python으로 온갖 자동화를 하다보니, 이제 소스는 그대로 두고 설정파일만으로 뭔가를 해봐야겠다는 생각을 하던 중,

yaml이 Python과 호환성이 좋다는 얘기를 들었었기 때문에, parser가 있는지 찾아보던 중 pyYaml이라는 lib를 찾게 되었다.


설치 방법은 아래 링크로 대체하겠다.

http://pyyaml.org/wiki/PyYAMLDocumentation


사용방법은 아래 예제를 참고하면 된다.

# test.yaml
strs:
  - a
  - b
  - c


import yaml

doc = yaml.load(open('test.yaml', 'r'))
strs = doc['strs']

for s in strs:
    print(s)  # a, b, c
반응형

'개발 > Python' 카테고리의 다른 글

[Python] Python 3.x no module MysqlDB  (0) 2017.02.14
[PyQt5] GUI 개발을 위한 PyQt5 세팅  (0) 2017.02.14
[Python] asyncio  (0) 2017.02.10
[Python] paramiko for SSHClient  (0) 2017.02.10
[Python] requirements.txt  (0) 2017.01.31
,

[Python] asyncio

개발/Python 2017. 2. 10. 10:31
반응형

서버 한대에 SSH로 붙어서, 여러개의 원격 서버에 request를 해야 하는 일이 생겼는데,

SSH를 매번 붙여서 하기엔 SSH접속이 너무 느려서, async하게 처리하는 방법을 찾던 중,

coroutine이라는 비동기 처리를 할 수 있는 기능이 있다는 것을 알았다.


다만, python에서 제공하는 비동기 처리는 GIL (global interpreter lock)이라고 해서, lock이 존재하기 때문에 비동기 처리 같지 않은 비동기처리라고 많이 불리고 있었다. 


이런 문제점을 해결하기 위해 Python 3.4 버전이상부터 사용할 수 있는 asyncio(https://docs.python.org/3/library/asyncio.html)라는 lib가 있어서, 사용법에 대해 간단히 설명을 하고자 한다. (이 기능때문에 Python 2.7에서 3.4 이상 버전으로 갈아탈 준비를 하고 있다.)


일단 설치는 pip로 가능하다.

$ pip install asyncio


아래는 예제소스인데, 이 포스팅에서는 정말 간단한 기능만 다루기 때문에 (실제로도 간단한 기능만 사용했고;;),

상세한 정보 획득을 위해선 공식 홈을 참조하는 게 좋다. https://docs.python.org/3/library/asyncio.html

예제소스에서는 asyncio에서 사용하는 event_loop를 초기화해서, print찍는 부분을 async하게 동작하도록 해볼 생각이다.

import asyncio

@asyncio.coroutine
def print_string(str):
    print(str)

    # 아래와 같이 텀을 두지 않으면, 동시에 여러개의 Thread를 생성하면서 초기화하는 과정에서, 문제가 발생한다.
    yield from asyncio.sleep(0.1)

@asyncio.coroutine
def print_all():
    strs = ['a', 'b', 'c']

    # coroutine기반의 Task를 생성한다.
    fetches = [asyncio.Task(print_string(str)) for str in strs]  

    # asyncio에 Task들을 등록한다.
    yield from asyncio.gather(*fetches)

def main():
    # Event Loop를 초기화 한 후 coroutine으로 돌릴 메서드를 지정하여, 완료될때까지 loop한다.
    asyncio.get_event_loop().run_until_complete(print_all()) 

if __init__ == '__main__':
    main()


반응형
,
반응형

특정 서버에 SSH로 접속하여, 원격 커맨드를 날릴 일이 있어서 이것저것 찾아보던 중,

Python에서는 paramiko라는 lib를 많이 사용한다는 걸 알았다.


설치방법은 아래와 같이 pip로 원 커맨드로 가능함.

$ pip install paramiko


테스트했던 Python버전은 3.6이었지만, Python 2.x나 그 전 버전에서도 잘 동작하는 것으로 보인다.


아래는 예제소스다. 

ssh.connect부분은 각 Case에 맞춰서 하나만 사용하면 된다.

import paramiko

def main():
    ssh = paramiko.SSHClient()

    # HostKey 저장 여부를 결정하는 옵션인데, 왠만하면 그냥 넣어주자.
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())       

    # CASE 1: 인증 시 username과 password를 사용
    ssh.connect('서버 IP', username='인증 ID', password='패스워드')  

    # CASE 2: AWS의 EC2같은 경우 password를 key_filename로 바꾸어서 파일 명을 지정할 수 있다.
    ssh.connect('서버 IP', username='인증 ID', key_filename='Key파일 위치') 

    stdin, stdout, stderr = ssh.exec_command('커맨드 입력')    
    ssh.close()
    
if __name__ == '__main__':
    main()


반응형

'개발 > Python' 카테고리의 다른 글

[Python] pyYaml을 이용한 yaml parsing  (0) 2017.02.10
[Python] asyncio  (0) 2017.02.10
[Python] requirements.txt  (0) 2017.01.31
[SMTPlib] mail loops back to me (MX problem)  (0) 2016.12.27
[Python] file read / write  (0) 2016.11.09
,
반응형

python의 의존 라이브러리 관리를 위해 setup.py와 requirements.txt가 사용되는데,

여기서는 requirements.txt에 대해 포스팅한다.


python 프로젝트 내에 requirements.txt 파일이 들어 있다면,

아래 커맨드 하나 만으로 모든 의존성이 설치가 되게 된다.

$ pip install -r requirements.txt


requirements.txt를 일일히 수작업으로 구성해도 괜찮지만, pip freeze를 이용하면 현재 세팅된 시스템이 가지고 있는 의존성을 아래 키워드로 한 번에 뽑아낼 수가 있다.

$ pip freeze > requirements.txt


단, pip freeze의 경우, 현재 폴더 기준이 아닌 글로벌한 환경 기준으로 의존성을 뽑아내기 때문에,

여러개의 Python 프로젝트를 운용하는 경우 원치않는 결과가 나올수도 있다.


그런 경우, pigar(https://github.com/Damnever/pigar)를 이용하여, 특정 폴더 기준으로 의존성을 추출해 낼 수 있다.

pip 를 이용해서 pigar를 설치한 후, pigar 명령어 뒤에 argument로 폴더 경로를 입력해주면,

해당 폴더부터 의존성을 검색하여 requirements.txt 파일을 뽑아준다.

$ pip install pigar # install pigar
$ pigar



반응형

'개발 > Python' 카테고리의 다른 글

[Python] asyncio  (0) 2017.02.10
[Python] paramiko for SSHClient  (0) 2017.02.10
[SMTPlib] mail loops back to me (MX problem)  (0) 2016.12.27
[Python] file read / write  (0) 2016.11.09
[Python] multipart file upload  (0) 2016.11.09
,
반응형

environment 속성에다가 TZ라는 환경변수만 추가해주면 된다.

abc:
  environment:
    TZ: "Asia/Seoul"


반응형
,
반응형

docker-compose 같은경우 기준이 되는 image를 선택할 때, image라는 속성을 사용할 수도 있지만,

build라는 속성을 이용하여, Dockerfile을 지정해줄 수가 있다.


예) docker-compose.yml (image)

db:
  image: mysql/mysql-server:latest         # dockerhub에 있는 image를 가져오는 경우


예) docker-compose.yml (Dockerfile이 abcd/Dockerfile 경로에 있는 경우)

db:
  build: ./abcd


docker-compose가 아직 Dockerfile이 가지고 있는 기능 전체를 지원하진 않기 때문에,

디테일한 기능들도 컨트롤 하기 위해서는, build 속성을 많이 사용하는 것 같다.


다만, 이 방식의 경우 volume을 컨트롤하는 데 문제가 하나 있다.


docker-compose의 volumes 속성을 이용해서, 폴더 단위로 link를 걸었을 때는 문제가 없지만,

docker-compose가 build 속성에 명시되어 있는 Dockerfile을 참조하는 과정에서 Dockerfile에 ADD나 COPY 구문이 들어있는 경우에 문제가 발생한다.


문제가 되는 케이스는 아래와 같다. (Nginx webroot에 파일을 추가하는 경우)


1. docker-compose를 이용하여, 최초에 image, container를 생성한다. (정상적으로 파일 ADD, COPY가 이루어짐)


2. 수정사항이 발생하여 파일을 수정 및 추가하여, docker-compose를 통해 container를 재배포한다. (반영되지 않음)


3. docker-compose를 통해 생긴 image, container를 삭제하고, 재생성 후 다시 배포한다. (정상적으로 반영)


아마 docker image를 docker-compose가 자체적으로 caching하고 있어서 발생하는 문제가 아닐까한다.


이런 경우 아래 예시 처럼 docker-compose에 volumes 속성을 사용하여, 폴더째로 link 시켜버리는 게 편한 것 같다.

예) docker-compose.yml (volumes)

db:
  build: ./abcd
  volumes: ./nginx_files:/var/www/html


이런식으로 링크를 걸어두면 host 머신에 있는 nginx_files 경로에 어떤 파일을 넣고, 빼면 container 안에 있는 /var/www/html 에도 즉시 반영이 되게 되어,

파일 배포 시에 docker-compose build라던지 할 필요가 없어지게 된다.


단, .dockerignore파일을 이용하여 메타정보 등의 파일을 빼고 배포시키는 등의 기능은 아직 docker-compose에서는 미지원하는 것 같다.

적절하게 잘 섞어서 쓰면 좋을듯..

반응형
,
반응형

vm환경에서 CentOS를 사용하다가, 특정 프로세스가 메모리점유를 많이해버려서, 메모리가 부족하게 되면,

커널 설정에 따라, oom-killer가 동작을 하고, 원하지 않는 서비스가 제멋대로 kill되어 버리는 상황이 발생한다.


메모리가 부족해도 서비스가 돌아가야 하는 상황에서는, vm.overcommit_memory 값을 변경하여

프로세스가 kill되지 않도록 할 수 있다.


vm.overcommit_memory값은 0~2까지 설정할 수 있으며, 값에 대한 정의는 아래와 같다.

- 0 : 메모리 부족 시 프로세스를 kill

- 1 : 항상 overcommit 허용 (kill하지 않음)

- 2: vm.overcommit_ratio에 설정된 범위만큼만 overcommit을 허용)


여기서는 항상 overcommit을 허용하도록 세팅을 해보도록 하겠다.

$ sysctl vm.overcommit_memory = 1     # 커널 설정 변경
$ echo "vm.overcommit_memory=1" >> /etc/sysctl.conf  # 재부팅 시에도 유지할 수 있도록 파일에 추가
$ sysctl -a | grep overcommit_memory   # 확인


반응형
,
반응형

upstart는 /etc/init 이하에 있는 설정 파일들을 자동으로 읽어들일 수 있게끔 구성이 되어 있기 때문에,

서비스로 구동 시킬 서비스의 configuration 파일을 /etc/init/{서비스명}.conf 형태로 작성을 하면 된다.


docker-compose를 이용해 구성한 컨테이너들도 서비스로 등록이 가능하다.


설정파일 예시 (ex: /etc/init/docker-registry.conf)

description "Docker Registry"  

# 아래 start, stop의 runlevel은 왠만해선 바꿀일이 없기 때문에, 그냥 사용하면 된다.
start on runlevel [2345]  
stop on runlevel [016]

# 자동 재시작을 설정한다. (아래에 있는 limit 설정만 있으면 기능 동작이 안됨)
respawn   

# 자동 재시작 (뒤에 두개의 argument는 COUNT, INTERVAL이다. 제한을 없애려면 unlimited만 적어준다.)
# 즉, 5초동안 10번 재시작해도 재시작에 실패하면 그냥 재시작하지 않겠다는 의미
respawn limit 10 5 

# 디렉토리 변경
chdir /root/docker-registry

# 명령어 실행 (가급적이면 절대경로)
exec /usr/local/bin/docker-compose up


upstart로 띄운 서비스의 로그 확인은 /var/log/upstart/{서비스명}.log 에서 확인이 가능함.

반응형
,
반응형

vagrant의 공식 reference에 보면, cpu, memory에 대해서 설정하는 부분이 나와있지만,

global하게 설정하는 방법밖에 나와있지 않다. (https://www.vagrantup.com/docs/virtualbox/configuration.html)


대충 아래와 같이 설정하면 global하게 설정이 됨.

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
   config.vm.provider "virtualbox" do |vb|
       vb.cpus = 2
       vb.memory = 1024
   end
end


저 설정을 응용해서 여러대의 vm이 있는 경우 각 vm에 provider옵션을 추가하여, cpu, memory를 세팅할 수 있다.

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|

   # 1번 머신
   config.vm.define "ubuntu1" do |ubuntu1|
      ubuntu1.vm.box = "ubuntu14_docker"
      ubuntu1.vm.network "private_network", ip: "192.168.33.10"
      ubuntu1.vm.hostname="ubuntu1604-1"
      ubuntu1.vm.provider :virtualbox do |vb|    
          vb.cpus = 2
          vb.memory = 2048
      end
  end  

  # 2번 머신
  config.vm.define "ubuntu2" do |ubuntu2|
      ubuntu2.vm.box = "ubuntu14_docker"
      ubuntu2.vm.network "private_network", ip: "192.168.33.11"
      ubuntu2.vm.hostname="ubuntu1604-2"
  end

  # 글로벌 설정
  config.vm.provider "virtualbox" do |vb|
       vb.cpus = 2
       vb.memory = 1024
  end
end


1번 머신은 세팅한 대로 2Core에 2GB로 세팅이 되었고, 별다른 설정하지 않은 2번 머신은 글로벌 설정에 따라 2코어에 1GB로 세팅이 되는 것을 확인할 수 있다.

반응형
,
반응형

python에 있는 SMTPLib을 이용해서 cronjob으로 sendmail을 호출하는데, 갑자기 메일이 안보내지길래,

syslog를 까보니, 아래와 같은 에러가 발생하였다. (아래 로그 중 회사관련 정보는 삭제하였음.)

Dec 26 09:02:09 sm-mta[23722]: uBQ929kP023720: SYSERR(root): 도메인 주소. config error: mail loops back to me (MX problem?)
Dec 26 09:02:09 sm-mta[23723]: uBQ929pM023723: 도메인 주소 [127.0.0.1] did not issue MAIL/EXPN/VRFY/ETRN during connection to MTA-v4
Dec 26 09:02:09 sm-mta[23722]: uBQ929kP023720: to=, delay=00:00:00, xdelay=00:00:00, mailer=esmtp, pri=121252, relay=hostname. [127.0.0.1], dsn=5.3.5, stat=Local configuration error
Dec 26 09:02:09 sm-mta[23722]: uBQ929kP023720: uBQ929kP023722: DSN: Local configuration error
Dec 26 09:02:09 sm-mta[23722]: uBQ929kP023722: to=root, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=60000, dsn=2.0.0, stat=Sent
Dec 26 09:02:09 sm-mta[23722]: uBQ929kP023722: to=, delay=00:00:00, xdelay=00:00:00, mailer=esmtp, pri=60000, relay=도메인 주소, dsn=5.3.5, stat=Local configuration error


원인은 머신이 알고 있는 host정보가 유효하지 않아서 발생하는 문제였고,

hostname을 확인하여 /etc/hosts와 /etc/mail/local-host-names에 있는 내용을 각각 바꿔주면 된다.

왠만하면 동일하게 바꿔주는 게 좋다.


[/etc/hosts]

127.0.0.1 hostname


[/etc/mail/local-host-names]

127.0.0.1 hostname


우분투 14.04 기준이기 때문에, 다른 OS는 처리방법이 다를 수도 있다.

반응형

'개발 > Python' 카테고리의 다른 글

[Python] paramiko for SSHClient  (0) 2017.02.10
[Python] requirements.txt  (0) 2017.01.31
[Python] file read / write  (0) 2016.11.09
[Python] multipart file upload  (0) 2016.11.09
[Python] logging to file  (0) 2016.11.09
,
반응형