rrd로 트래픽수집을 하다보면 아래 그림처럼 갑자기 트래픽이 튀는 경우가 발생한다.



위와 같은 문제가 발생하면 rrd 디비를 dump -> 데이터수정 -> restore 를 해줘야 하는데 


상당히 귀찮은 작업이다.


그래서 스크립트 하나 만들어 봄...


1. rrd 파일을 xml 로 dump 를 받고

2. Param 으로 받은 시간대의 데이터를 0.0000000000e+00 으로 수정

3. 수정된 xml 로 restore 를 진행한다.


tip:

dump 이후에 수집된 데이터는 누락이 되는 문제가 있어 

dump 전/후 lastupdate 시간이 다를경우에 dump 후에 수집된 raw 데이터를 구하여 

update를 진행합니다. 


[root@new test]# /usr/local/python2.6/bin/python rrdmod.py -h

rrdmod.py [options]

Options:

-t, --time=<timestamp>   time format %Y%m%d%H or %Y%m%d

-f, --file=<filename>    rrd file name


코드는 아직 정리 전이라 보기에 좀 불편하겠지만 수정하여 다시 업데이트 할예정임...


import sys

import subprocess

import getopt

import datetime

import time

import re

import os


def get_rrd_lastinfo(rrd_file):

    last_time, last_input, last_output = None, None, None


    p = subprocess.Popen(

            ('rrdtool', 'lastupdate', rrd_file), stdout=subprocess.PIPE)

    out, err = p.communicate()

    for s in out.split("\n"):

        m = re.search(r"(\d+): (\d+) (\d+)", s)

        if m:

            last_time, last_input, last_output = m.groups()


    return last_time, last_input, last_output


def get_rrd_update_value(rrd_file, start_time, end_time, input, output):

    values = []

    p = subprocess.Popen(

        ('rrdtool', 'fetch', rrd_file, 'AVERAGE', '-s', start_time, '-e', end_time), stdout=subprocess.PIPE)

    out, err = p.communicate()

    for s in out.split("\n"):

        m = re.search(r"(\d+): ([\.e\+\-\d]+) ([\.e\+\-\d]+)", s)

        if m:

            last_time, last_input, last_output = m.groups()

            last_input = int(eval(last_input)*300)

            last_output = int(eval(last_output)*300)

            values.append((last_time,last_input, last_output))


    values.reverse()

    input = float(input)

    output = float(output)


    for n, v in enumerate(values):

        input -= v[1]

        output -= v[2]

        v = v + ("%d" % input,)

        v = v + ("%d" % output,)

        values[n] = v


    values.reverse()

    for v in values:

        print v

        subprocess.Popen(

            ('rrdtool', 'update', rrd_file, '%s:%s:%s' % (v[0], v[3], v[4])), stdout=subprocess.PIPE).communicate()


def modrrd(mod_time, rrd_file):

    """

    <!-- 2017-02-02 15:00:00 KST / 1486015200 --> <row><v>NaN</v><v>NaN</v></row>

    """

    pattern = re.compile(r" %s\s?[:\d]+ \w+ / (\d+) --> <row><v>(.*)</v><v>(.*)</v></row>" % mod_time)

    init_value = "0.0000000000e+00"


    last_update_time = get_rrd_lastinfo(rrd_file)[0]


    p1 = subprocess.Popen(

            ('rrdtool', 'dump', rrd_file), stdout=subprocess.PIPE)


    if os.path.exists('%s.new.rrd' % rrd_file):

        os.unlink('%s.new.rrd' % rrd_file)


    fp = open("%s.xml" % rrd_file, "a+")

    for num, line in enumerate(p1.stdout):

        matching = pattern.search(line)

        if matching:

            if len(matching.groups()) == 3:

                line = line.replace(matching.groups()[1], init_value).replace(matching.groups()[2], init_value)


        fp.write(line)

    fp.close()


    p2 = subprocess.Popen(

            ('rrdtool', 'restore', "%s.xml" % rrd_file, '%s.new.rrd' % rrd_file), stdout=subprocess.PIPE)


    out, err = p2.communicate()


    if os.path.exists("%s.xml" % rrd_file):

        os.unlink("%s.xml" % rrd_file)


    _last_update_time, _last_input, _last_output = get_rrd_lastinfo(rrd_file)


    if last_update_time != _last_update_time:

        get_rrd_update_value(rrd_file, last_update_time, _last_update_time, _last_input, _last_output)


def usage():

    print 'rrdmod.py [options]'

    print 'Options:'

    print '-t, --time=<timestamp>   time format %Y%m%d%H or %Y%m%d'

    print '-f, --file=<filename>    rrd file name'


def main():

    mod_time, rrd_file = None, None

    try:

        opts, args = getopt.getopt(sys.argv[1:],"ht:f:",["time=","file="])

    except getopt.GetoptError:

        usage()

        sys.exit(2)


    for opt, value in opts:

        if opt in ("-t", "--time"):

            mod_time = value

            if len(mod_time) == 10:

                mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d%H')

                mod_time = mod_time.strftime("%Y-%m-%d %H")

            elif len(mod_time) == 8:

                mod_time = datetime.datetime.strptime(mod_time, '%Y%m%d')

                mod_time = mod_time.strftime("%Y-%m-%d")

            else:

                usage()

                sys.exit(2)


            # make timestamp

            #mod_time = time.mktime(mod_time.timetuple())


        elif opt in ("-f", "--file"):

             rrd_file = value

        elif opt == "-h":

            usage()

            sys.exit()


    if mod_time == None or rrd_file == None:

        usage()

        sys.exit()


    modrrd(mod_time, rrd_file)


if __name__ == "__main__":

    main()

'Python' 카테고리의 다른 글

sftpserver + pyotp  (0) 2017.03.08
Django + djangorestframework + django_rest_swagger 시작  (0) 2017.02.01
Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22

테스트환경

CentOS release 6.8 (Final)

Python 3.4.6

Django-1.10.5

djangorestframework-3.5.3

django_rest_swagger-2.1.1

MariaDB-server-10.0.29

pipenv-3.2.11


1. CentOS release 6.8 (Final)

    1-1. centos 6.8 minimal 설치

    1-2. Development tools 설치

    ]# yum update

    ]# yum groupinstall 'Development tools'


2. Python 3.4.6

    2-1. Python 3.4.6 설치

    ]# wget https://www.python.org/ftp/python/3.4.6/Python-3.4.6.tgz

    ]# tar zxf Python-3.4.6.tgz

    ]# cd Python-3.4.6

    ]# ./configure --prefix=/usr/local/python3.4 --enable-shared

    ]# make

    ]# make install

    ]# echo "/usr/local/python3.4/lib" >> /etc/ld.so.conf.d/python3.4.conf

    ]# ldconfig

    ]# /usr/local/python3.4/bin/pip3 install pipenv

    ]# ln -s /usr/local/python3.4/bin/python3 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/python3.4 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pip3 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pip3.4 /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/pipenv /usr/local/bin/

    ]# ln -s /usr/local/python3.4/bin/virtualenv /usr/local/bin/

    

    Tip: https://www.python.org/dev/peps/pep-0513/#ucs-2-vs-ucs-4-builds

          --enable-unicode=ucs4 옵션은 CPython 2.x, 3.0 ~ 3.2 까지만 사용한다.


3. MariaDB-server-10.0.29

    3-1. MariaDB-server-10.0.29 설치

    ]# vi /etc/yum.repos.d/MariaDB.repo

    [mariadb]

    name = MariaDB

    baseurl = http://yum.mariadb.org/10.0/centos6-amd64

    gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB

    gpgcheck=1

    

    ]# yum install MariaDB-server MariaDB-client MariaDB-devel

    ]# /etc/rc.d/init.d/mysqld start

    ]# mysql -u root

    MariaDB [(none)]> CREATE DATABASE test_django CHARACTER SET UTF8;

    MariaDB [(none)]> CREATE USER django@localhost IDENTIFIED BY '비밀번호';

    MariaDB [(none)]> CREATE USER django@127.0.0.1 IDENTIFIED BY '비밀번호';

    MariaDB [(none)]> GRANT ALL PRIVILEGES ON test_django.* TO django@localhost;

    MariaDB [(none)]> GRANT ALL PRIVILEGES ON test_django.* TO django@127.0.0.1;

    MariaDB [(none)]> FLUSH PRIVILEGES;


4. Django-1.10.5, djangorestframework-3.5.3, django_rest_swagger-2.1.1, mysqlclient-1.3.9

    4-1. Django, djangorestframework, django_rest_swagger, mysqlclient 설치

    ]# mkdir /home/test-django

    ]# cd /home/test-django

    ]# pipenv install mysqlclient django djangorestframework django-rest-swagger

    

5. djangorestframework tutorial 시작

]# pipenv shell

(test-django) ]# django-admin startproject test_api

(test-django) ]# cd test_api

(test-django) ]# vi test_api/settings.py


"""

ALLOWED_HOST 수정

DATABASE 수정

"""

- ALLOWED_HOSTS = []

+ ALLOWED_HOSTS = ['*']


- DATABASES = {

-    'default': {

-        'ENGINE': 'django.db.backends.sqlite3',

-        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

-    }

- }


+ DATABASES = {

+    'default': {

+        'ENGINE': 'django.db.backends.mysql',

+        'NAME': 'test_django',

+        'USER': 'django',

+        'PASSWORD': '비밀번호',

+        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on

+        'PORT': '3306',

+        'OPTIONS': {

+            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",

+        },

+    }

}

 


""" migrate 수행 """

(test-django) ]# ./manage.py migrate


""" admin 계정 생성 """

(test-django) ]# ./manage.py createsuperuse


""" app 추가 """

(test-django) ]# ./manage.py startapp v1


""" Post 모델 작성 """

(test-django) ]# vi v1/models.py

from django.db import models

class Post(models.Model):
   title = models.CharField(max_length=200)
   content = models.TextField()
   created_at = models.DateTimeField(auto_now_add=True)
   updated_at = models.DateTimeField(auto_now=True)

   def __str__(self):
       return "{}: {}".format(self.pk, self.title)


""" INSTALLED_APPS 에 v1, rest_framework, rest_framework_swagger 추가 """

(test-django) ]# vi test_api/settings.py

INSTALLED_APPS.append('v1')
INSTALLED_APPS.append('rest_framework')
INSTALLED_APPS.append('rest_framework_swagger')


""" v1 App의 Post 모델 생성 """

(test-django) ]# ./manage.py makemigrations v1

(test-django) ]# ./manage.py migrate v1



""" admin 페이지에서 Post 관리할 수 있도록 추가 """

(test-django) ]# vi v1/admin.py

from django.contrib import admin
from .models import *

admin.site.register(Post)


""" serializers 클래스 생성 """

(test-django) ]# vi v1/serializers.py

from rest_framework import serializers
from .models import *

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'


""" viewset 클래스 생성 """

(test-django) ]# vi v1/views.py

from django.shortcuts import render from .models import * from .serializers import * from rest_framework import viewsets class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer


""" app urls 생성 및 project urls 에 추가 """

(test-django) ]# vi v1/urls.py

from django.conf.urls import include, url from .views import * from rest_framework import routers from rest_framework_swagger.views import get_swagger_view router = routers.DefaultRouter() router.register(r'post', <PostViewSet) schema_view = get_swagger_view(title='TEST API') urlpatterns = [ url(r'^', include(router.urls)),

url(r'^swagger', schema_view) , ]


from django.conf.urls import include, url

from .views import *

from rest_framework import routers

from rest_framework_swagger.views import get_swagger_view


router = routers.DefaultRouter()

router.register(r'post', PostViewSet)


schema_view = get_swagger_view(title='TEST API')


urlpatterns = [

    url(r'^', include(router.urls)),

    url(r'^swagger', schema_view),

]

 


(test-django) ]# vi test_api/urls.py

"""test_api URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [url(r'^admin/', admin.site.urls),url(r'^v1/', include('v1.urls')),]


from django.conf.urls import include, url

from django.contrib import admin


urlpatterns = [

    url(r'^admin/', admin.site.urls),

    url(r'^v1/', include('v1.urls')),

]

 


""" 실행 """

(test-django) ]# ./manage.py runserver 0.0.0.0:80


""" 웹브라우져로 접속 및 테스트 """



 


기본적인 예제를 테스트 해보았고 공식 tutorial 사이트를 방문해서 단계별로 테스트를 진행해야한다...

http://www.django-rest-framework.org/#tutorial

'Python' 카테고리의 다른 글

sftpserver + pyotp  (0) 2017.03.08
rrdmod  (0) 2017.02.03
Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22


from boto.s3.connection import S3Connection


access_key = "*****5JJPZD6WYG*****"

secret_key = "*****GnYf/bmdJ9NfkveFF+Mb8IPjVIGybC*****"

region = "s3-ap-northeast-2.amazonaws.com"

conn = S3Connection(access_key, secret_key, host=region)

bucket = conn.get_bucket('ghpark-mp3')

for key in bucket.list():

    print key.name

 


regions 

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html


seoul region을 명시해줘야 400 에러 발생하지 않음 ㅡㅜ 


http://boto.cloudhackers.com/en/latest/s3_tut.html


import os

import fnmatch

from boto.s3.connection import S3Connection


conn = S3Connection('*****5JJPZD6WYG*****','*****GnYf/bmdJ9NfkveFF+Mb8IPjVIGybC*****', host="s3-ap-northeast-2.amazonaws.com")

bucket = conn.get_bucket('ghpark-mp3')

for key in bucket.list():

    print key.name

    # download

    #key.get_contents_to_filename(key.name)

    # delete

    #key.delete()


for f in os.listdir("."):

    if fnmatch.fnmatch(f, "*.mp3"):

        f = f.encode("UTF-8")

        k = bucket.new_key(f)

        # upload

        k.set_contents_from_filename(f)



s3bucket 용량 구하는거 ... 깔끔하네

https://gist.github.com/robinkraft/2667939



import boto

s3 = boto.connect_s3(aws_id, aws_secret_key)


# based on http://www.quora.com/Amazon-S3/What-is-the-fastest-way-to-measure-the-total-size-of-an-S3-bucket


def get_bucket_size(bucket_name):

    bucket = s3.lookup(bucket_name)

    total_bytes = 0

    n = 0

    for key in bucket:

        total_bytes += key.size

        n += 1

        if n % 2000 == 0:

            print n

    total_gigs = total_bytes/1024/1024/1024

    print "%s: %i GB, %i objects" % (bucket_name, total_gigs, n)

    return total_gigs, n


bucket_list = []

bucket_sizes = []


for bucket_name in bucket_list:

    size, object_count = get_bucket_size(bucket_name)

    bucket_sizes.append(dict(name=bucket_name, size=size, count=object_count))


print "\nTotals:"

for bucket_size in bucket_sizes:

    print "%s: %iGB, %i objects" % (bucket_size["name"], bucket_size["size"], bucket_size["count"]) 




'Python' 카테고리의 다른 글

Django + djangorestframework + django_rest_swagger 시작  (0) 2017.02.01
Pika Python AMQP Client Library  (0) 2017.01.31
daemonizing  (0) 2016.12.22
Threading  (0) 2016.12.22
pidlockfile.py for windows  (0) 2016.12.19

데몬으로 python script 를 실행할때 직접 daemonizing 코드를 구형하여 만들었는데

python-daemon 이라는 패키지를 사용해보니 cmdline 에서 start/stop/restart 도 지원하고 filelock 도 지원한다.

쓸만해보여서 정리해둠 


wget https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tgz
tar zxf Python-2.7.12.tgz
cd Python-2.7.12
./configure --prefix=/home/apps/python2.7 --enable-unicode=ucs4 --enable-shared
make
make install
wget --no-check-certificate https://pypi.python.org/packages/25/4e/1b16cfe90856235a13872a6641278c862e4143887d11a12ac4905081197f/setuptools-28.8.0.tar.gz
tar zxf setuptools-28.8.0.tar.gz
cd setuptools-28.8.0
python2.7 setup.py build
python2.7 setup.py install
wget --no-check-certificate https://bootstrap.pypa.io/get-pip.py
python2.7 get-pip.py
pip install python-daemon
 
mkdir /daemon_sample
cd /daemon_sample
mkdir  bin lib log run
cd bin
vi daemon_sample.py
--------------------------------------------------------------------------------------------
#!/home/apps/python2.7/bin/python
# -*- coding: UTF-8 -*-
import time
from daemon.runner import DaemonRunner
class TestDaemon(object):
    def __init__(self):
        self.stdin_path = '/dev/null'
        self.stdout_path = '/dev/tty'
        self.stderr_path = '/dev/tty'
        self.pidfile_timeout = 0
        self.pidfile_path="/usr/mgmt/apm_package_manager/run/TestDaemon.pid"
    def run(self):
        while 1:
            time.sleep(3)
DaemonRunner(TestDaemon()).do_action()
--------------------------------------------------------------------------------------------
chmod 700 daemon_sample.py
./daemon_sample.py
usage: test.py start|stop|restart
 
 
./daemon_sample.py start
started with pid 24751
 
 
./daemon_sample.py start
  File "./test.py", line 19, in <module>
    DaemonRunner(TestDaemon()).do_action()
  File "/home/apps/python2.7/lib/python2.7/site-packages/daemon/runner.py", line 274, in do_action
    func(self)
  File "/home/apps/python2.7/lib/python2.7/site-packages/daemon/runner.py", line 187, in _start
    raise error
daemon.runner.DaemonRunnerStartFailureError: PID file '/usr/mgmt/apm_package_manager/run/TestDaemon.pid' already locked


'Python' 카테고리의 다른 글

Pika Python AMQP Client Library  (0) 2017.01.31
s3 example  (0) 2016.12.28
Threading  (0) 2016.12.22
pidlockfile.py for windows  (0) 2016.12.19
cygwin + ssh + rsync  (0) 2016.12.10

python 에서 서브쓰레드를 정상종료해보자 

시그널은 메인쓰레드만 받을수 있다.

메인쓰레드에서 시그널을 받아 서브쓰레드에 이벤트로 플래그를 전달한다.


#!/usr/local/python2.6/bin/python
#-*- coding: utf-8 -*-
import threading
import time
import logging
import random
import Queue
import signal
import sys
logging.basicConfig(level=logging.DEBUG,
                    format='(%(threadName)-9s) %(message)s',)
 
BUF_SIZE = 10
q = Queue.Queue(BUF_SIZE)
e = threading.Event()
 
class ProducerThread(threading.Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        super(ProducerThread,self).__init__()
        self.target = target
        self.name = name
    def run(self):
        while not e.is_set():
            if not q.full():
                item = random.randint(1,10)
                q.put(item)
                logging.debug('Putting ' + str(item)
                              ' : ' + str(q.qsize()) + ' items in queue')
        logging.debug("end")
        return
 
class ConsumerThread(threading.Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        super(ConsumerThread,self).__init__()
        self.target = target
        self.name = name
    def run(self):
        while not e.is_set():
            if not q.empty():
                item = q.get()
                logging.debug('Getting ' + str(item)
                              ' : ' + str(q.qsize()) + ' items in queue')
        logging.debug("end")
        return
 
if __name__ == '__main__':
    p = ProducerThread(name='producer')
    c = ConsumerThread(name='consumer')
    p.setDaemon(True)
    c.setDaemon(True)
    p.start()
    c.start()
    try:
        while p.is_alive() and c.is_alive():
            time.sleep(1)
    except KeyboardInterrupt:
        e.set()
 
    p.join()
    c.join()


kill 커맨드로 2번 시그널을 메인쓰레드에 전달한다.

end 구문까지 정상적으로 처리가 되고 종료가 된다.


]# ps -ef | grep tqt.py
root     23927 13186 99 11:55 pts/0    00:00:10 /usr/local/python2.6/bin/python ./tqt.py
 
]# kill -2 23927
 
(producer ) Putting 1 : 1 items in queue
(consumer ) Getting 1 : 0 items in queue
(producer ) Putting 7 : 1 items in queue
(consumer ) Getting 7 : 0 items in queue
(producer ) Putting 5 : 1 items in queue
(consumer ) Getting 5 : 0 items in queue
(producer ) Putting 2 : 1 items in queue
(consumer ) Getting 2 : 0 items in queue
(producer ) Putting 1 : 1 items in queue
(consumer ) Getting 1 : 0 items in queue
(producer ) Putting 1 : 1 items in queue
(consumer ) Getting 1 : 0 items in queue
(producer ) Putting 2 : 1 items in queue
(consumer ) Getting 2 : 0 items in queue
(producer ) Putting 2 : 1 items in queue
(consumer ) Getting 2 : 0 items in queue
(producer ) Putting 2 : 1 items in queue
(consumer ) Getting 2 : 0 items in queue
(producer ) Putting 10 : 1 items in queue
(consumer ) end
(producer ) end


'Python' 카테고리의 다른 글

s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22
pidlockfile.py for windows  (0) 2016.12.19
cygwin + ssh + rsync  (0) 2016.12.10
remove ^M(Carriage Return)  (0) 2016.11.30

기존에 있던 lockfile.pidlockfile 모듈을 참조하여 pid 부분을 수정


import os

import errno

from win32com.client import GetObject


class PIDLockError(Exception):

    pass


class AlreadyLocked(PIDLockError):

    def __init__(self, path):

        self.path = path

        

    def __str__(self):

        return "%s is already locked" % self.path


class LockFailed(PIDLockError):

    def __init__(self, path):

        self.path = path


    def __str__(self):

        return "failed to create %s" % self.path


class PIDLockFile(object):

    def __init__(self, path):

        self.path = path


    def read_pid(self):

        return self.read_pid_from_pidfile()


    def is_locked(self):

        return os.path.exists(self.path)


    def i_am_locking(self):

        running_process = []

        wmi = GetObject('winmgmts:')

        processes = wmi.InstancesOf('win32_Process')

        for pro in processes:

            running_process.append(pro.Properties_('ProcessId').value)

            

        if self.is_locked():

            if self.read_pid() in running_process:

                return True

        return False


    def acquire(self):

        if not self.i_am_locking():

            self.break_lock()

            

        try:

            self.write_pid_to_pidfile()

        except OSError, exc:

            if exc.errno == errno.EEXIST:


                raise AlreadyLocked(self.path)

            else:

                raise LockFailed(self.path)

        else:

            return


    def release(self):

        self.remove_existing_pidfile()


    def break_lock(self):

        self.remove_existing_pidfile()

        

    def read_pid_from_pidfile(self):

        pid = None

        try:

            pidfile = open(self.path, 'r')

        except IOError:

            pass

        else:

            line = pidfile.readline().strip()

            try:

                pid = int(line)

            except ValueError:

                pass

            pidfile.close()

        return pid


    def write_pid_to_pidfile(self):

        pidfile_fd = os.open(self.path, os.O_CREAT | os.O_EXCL | os.O_WRONLY)

        pidfile = os.fdopen(pidfile_fd, 'w')

        pid = os.getpid()

        pidfile.write("%s\n" % pid)

        pidfile.close()        


    def remove_existing_pidfile(self):

        if self.is_locked(): os.remove(self.path) 



# example

import os

import traceback

import pidlockfile import PIDLockFile, PIDLockError


def main():

    pid_file = os.path.join("C:\\", "run", "run.pid")

    plock = PIDLockFile(pid_file)

    try:

        plock.acquire()

        print "hellow" 

        plock.release()

        

    except PIDLockError, exc:

        print exc

    except Exception, exc:

        print traceback.format_exc()

        

if __name__ == "__main__":

    main()



'Python' 카테고리의 다른 글

daemonizing  (0) 2016.12.22
Threading  (0) 2016.12.22
cygwin + ssh + rsync  (0) 2016.12.10
remove ^M(Carriage Return)  (0) 2016.11.30
sqlalchemy  (0) 2016.11.28

http://code.activestate.com/recipes/286229-remove-control-character-m-from-opened-html-files/

http://blogger.pe.kr/170

>>> import curses.ascii
>>> ascii.ascii('^V^M')
'\r'
>>> string.replace( str, '\r', '' )


'Python' 카테고리의 다른 글

pidlockfile.py for windows  (0) 2016.12.19
cygwin + ssh + rsync  (0) 2016.12.10
sqlalchemy  (0) 2016.11.28
pexpect.pxssh  (0) 2016.11.24
PEP8  (0) 2016.11.24

sqlalchemy + python-daemon


]# /home/python2.7/bin/pip install SQLAlchemy

]# /home/python2.7/bin/pip install mysql-python

]# mkdir /home/package_manager

]# cd /home/package_manager

]# mkdir bin lib log run

]# cd bin

]# vi package_manager.py


#!/home/python2.7/bin/python

# -*- coding: UTF-8 -*-


import sys

import time

from daemon.runner import DaemonRunner

sys.path.append("/home/package_manager/lib")


class App(object):

    def __init__(self):

        self.stdin_path = "/dev/null"

        self.stdout_path = "/dev/tty"

        self.stderr_path = "/dev/tty"

        self.pidfile_timeout = 0

        self.pidfile_path = "/home/package_manager/run/app.pid"


    def run(self):

        from database import session

        from models import APMDistributionQueue

        while 1:

            tasks = session.query(APMDistributionQueue).all()

            for task in tasks:

                print task.server_info.hostn


            time.sleep(10)


def main():

    DaemonRunner(App()).do_action()


if __name__ == "__main__":

    main() 


]# cd lib

]# vi database.py


 # -*- coding: UTF-8 -*-

from sqlalchemy import create_engine

from sqlalchemy.orm import scoped_session, sessionmaker

from sqlalchemy.ext.declarative import declarative_base


engine = create_engine('mysql+mysqldb://아이디:비밀번호@localhost/manager_new', convert_unicode=True)

Base = declarative_base()

session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))


]# vi models.py


# -*- coding: UTF-8 -*-

from sqlalchemy.sql import func

from sqlalchemy import ForeignKey, Column, Integer, String, DateTime, Table

from sqlalchemy.orm import relationship, backref

from database import Base, engine


class ServerInfo(Base):

       __table__ = Table('info', Base.metadata, autoload=True, autoload_with=engine)


class APMPackage(Base):

    __tablename__ = 'apm_package'

    id = Column(Integer, primary_key=True)

    name = Column(String(100), unique=True)

    packaging_file = Column(String(200))

    unpackaging_path = Column(String(200))

    queue = relationship("APMDistributionQueue", backref=backref('package'), cascade='all, delete, delete-orphan')


    def __init__(self, name, file, path):

        self.name = name

        self.packaging_file = file

        self.unpackaging_path = path


    def __repr__(self):

        return "%s %s %s %s" % (self.id, self.name, self.packaging_file, self.unpackaging_path)


class APMDistributionQueue(Base):

    __tablename__ = 'apm_distribution_queue'

    id = Column(Integer, primary_key=True)

    mode = Column(String(20), nullable=False)

    server_id = Column(Integer, ForeignKey(ServerInfo.idx), nullable=False)

    package_id = Column(Integer, ForeignKey(APMPackage.id), nullable=False)

    status = Column(Integer, default=1, nullable=False)

    reg_date = Column(DateTime(timezone=True), default=func.now(), nullable=False)

    server_info = relationship("ServerInfo", backref=backref('queue'))


    def __init__(self, mode, sid, pid):

        self.mode = mode

        self.server_id = sid

        self.package_id = pid


    def __repr__(self):

        return "%s %s %s %s" % (self.id, self.mode, self.server_id, self.package_id) 


]# cd ../bin

]# package_manager.py start


프로세스가 fork 되면서 sqlalchemy 의 connection pool과의 연결이 끊기는 문제가 발생해서 한참을 고생했다.

해결방법은 run 메소드 안에서 database.py 를 import 하거나 engine 생성시에 pool_recycle 값을 0으로 설정하면 된다.


새로 만든 테이블과 기존에 있던 테이블을 같이 사용하기 위해 declarative_base, automap_base 중 어떤 맵핑클래스를 

사용하는지에따라 구현하는부분이 달라지는데 테스트코드를 만들어봐야 이해할듯하다.


http://programtalk.com/python-examples/daemon.pidfile.PIDLockFile/

 

 


'Python' 카테고리의 다른 글

pidlockfile.py for windows  (0) 2016.12.19
cygwin + ssh + rsync  (0) 2016.12.10
remove ^M(Carriage Return)  (0) 2016.11.30
pexpect.pxssh  (0) 2016.11.24
PEP8  (0) 2016.11.24

+ Recent posts