https://github.com/rspivak/sftpserver


윈도우에서도 잘 돌아감


c:\Python27\Scripts>sftpserver.exe -k id_rsa.key -l DEBUG


#-*- encoding: utf-8 -*-

import paramiko
pkey = paramiko.RSAKey.from_private_key_file('c:\Python27\Scripts\id_rsa.key')
transport = paramiko.Transport(('localhost'3373))
transport.connect(username='admin'password='admin')
sftp = paramiko.SFTPClient.from_transport(transport)
print sftp.listdir('.')
"""
output:
['loop.py', 'stub_sftp.py', 'sftpserver-script.py']
"""
""" download """
sftp.get('sftpserver-script.py''sftpserver-script.py')


https://github.com/rspivak/sftpserver/blob/master/src/sftpserver/stub_sftp.py

class StubServer (ServerInterface):

    def check_auth_password(self, username, password):

        # all are allowed

        return AUTH_SUCCESSFUL


위 check_auth_password 함수에 pyotp 적용하면 보안상 좋을듯....

https://github.com/pyotp/pyotp


python_window_daemon.py

#-*- encoding: utf-8 -*-
# Now works in python 3 aswell as 2

import sys, threading, time, os, datetime, time, inspect, subprocess, socket
from subprocess import PIPE, STDOUT
from wsgiref.simple_server import make_server

class Webshite():

    def __init__(self):
        self.hostname = socket.getfqdn()
        self.header = """
        <html>
        <header>
        <style>
        body {
            background-color:#6C7A89;
        }
        p {
            color:white;
            font-family:Consolas;
        }
        </style>
        </header>
        <body>
        """
        self.shite = "<p>"+str(self.hostname)+"</p>"

        self.footer = """
        </body>
        </html>
        """

    def grains(selfenvironstart_response):
        self.environ = environ
        self.start = start_response
        status = '200 OK'
        response_headers = [('Content-type','text/html; charset=utf-8')]
        self.start(status, response_headers)
        fullsite = self.header + self.shite + self.footer
        fullsite = [fullsite.encode('utf-8')] # in python 3, this needed to be a list, and encoded
        return fullsite

    def run(self):
        srv = make_server('127.0.0.1'8080self.grains)

        while True:
            try:
                threading.Thread(target=srv.handle_request()).start()
            except KeyboardInterrupt:
                exit()



# ------------------ terrible daemon code for windows -------------------
if __name__ == '__main__':
    webshite = Webshite()

    Windows = sys.platform == 'win32'
    ProcessFileName = os.path.realpath(__file__)
    pidName = ProcessFileName.split('\\')[-1].replace('.py','')

    if Windows:
        pidFile = 'c:\\Windows\\Temp\\'+pidName+'.pid'
    else:
        pidFile = '/tmp'+pidName+'.pid'


    def start(pidfilepidname):
        """ Create process file, and save process ID of detached process """
        pid = ""
        if Windows:
            #start child process in detached state
            DETACHED_PROCESS = 0x00000008
            p = subprocess.Popen([sys.executable, ProcessFileName, "child"],
                                    creationflags=DETACHED_PROCESS)
            pid = p.pid

        else:
            p = subprocess.Popen([sys.executable, ProcessFileName, "child"],
                                    stdout = PIPE, stderr = PIPE)
            pid = p.pid


        print("Service", pidname, pid, "started")
        # create processfile to signify process has started
        with open(pidfile, 'w'as f:
            f.write(str(pid))
        f.close()
        os._exit(0)


    def stop(pidfilepidname):
        """ Kill the process and delete the process file """
        procID = ""
        try:
            with open(pidfile, "r"as f:
                procID = f.readline()
            f.close()
        except IOError:
            print("process file does not exist, but that's ok <3 I still love you")

        if procID:
            if Windows:
                try:
                    killprocess = subprocess.Popen(['taskkill.exe','/PID',procID,'/F'],
                                                        stdout = PIPE, stderr = PIPE)
                    killoutput = killprocess.communicate()

                except Exception as e:
                    print(e)
                    print ("could not kill ",procID)
                else:
                    print("Service", pidname, procID, "stopped")

            else:
                try:
                    subprocess.Popen(['kill','-SIGTERM',procID])
                except Exception as e:
                    print(e)
                    print("could not kill "+procID)
                else:
                    print("Service "+procID + " stopped")

            #remove the pid file to signify the process has ended
            os.remove(pidfile)

    if len(sys.argv) == 2:

        if sys.argv[1] == "start":

            if os.path.isfile(pidFile) == False:
                start(pidFile, pidName)
            else:
                print("process is already started")

        elif sys.argv[1] == "stop":

            if os.path.isfile(pidFile) == True:
                stop(pidFile, pidName)
            else:
                print("process is already stopped")

        elif sys.argv[1] == "restart":
                stop(pidFile, pidName)
                start(pidFile, pidName)

        # This is only run on windows in the detached child process
        elif sys.argv[1] == "child":
            webshite.run()
    else:
        print("usage: python "+pidName+".py start|stop|restart")

#kill main
os._exit(0)


'Python' 카테고리의 다른 글

rrdmod  (0) 2017.02.03
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

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
#!/usr/bin/env python

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello'
;)

print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print " [x] Received %r" % (body,)

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)

channel.start_consuming()



Receiving.py


#!/usr/bin/env python

import pika


connection = pika.BlockingConnection(pika.ConnectionParameters(

        host='localhost'))

channel = connection.channel()


channel.queue_declare(queue='hello')


print ' [*] Waiting for messages. To exit press CTRL+C'


def callback(ch, method, properties, body):

    print " [x] Received %r" % (body,)


channel.basic_consume(callback,

                      queue='hello',

                      no_ack=True)


channel.start_consuming()



Sending.py


#!/usr/bin/env python

import pika


connection = pika.BlockingConnection(pika.ConnectionParameters(

               'localhost'))

channel = connection.channel()

channel.queue_declare(queue='hello')

channel.basic_publish(exchange='',

                      routing_key='hello',

                      body='Hello World!')

print " [x] Sent 'Hello World!'"

connection.close()

'Python' 카테고리의 다른 글

rrdmod  (0) 2017.02.03
Django + djangorestframework + django_rest_swagger 시작  (0) 2017.02.01
s3 example  (0) 2016.12.28
daemonizing  (0) 2016.12.22
Threading  (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

1. pexpect 사용해보려고 하였으니 윈도우에서 사용이 불가

python27, python53 설치 후 pexpect 설치하여 테스트 해보았으나 동작하지 않음

대안으로 winexpect 라는것이 있는데 오픈소스를 더이상 관리하지 않고 종료된 상태


2. tcl.exe 를 이용하여 윈도우에서 expect 기능을 사용할수 있으나 

python 에서 호출할경우에 tcl 스크립트 호출해야하는 python -> tcl -> output 구조가 되서 에러처리에 문제가 있어보임


1/2 번 모두 비밀번호 입력을 자동화 하려고 하것인데

생각해보니 서버단에서 개인키를 핸들링하면 키로 인증하여 윈도우서버간에 파일전송을 할수가 있음

(파일전송후에는 키를 삭제하면됨)


src나 dst 경로에 공백이 들어갈 경우에 Administrator@test.com:'/cygdrive/e/path\ to\ directory' 와 같이 처리해주면됨


import os
cmd = "rsync -av -e \"ssh -o \"StrictHostKeyChecking=no\" -i /cygdrive/c/id_rsa -p 2222\" "
cmd += "Administrator@test.com:'/cygdrive/e/path\ to\ directory' /cygdrive/f"
os.system(cmd)


'Python' 카테고리의 다른 글

Threading  (0) 2016.12.22
pidlockfile.py for windows  (0) 2016.12.19
remove ^M(Carriage Return)  (0) 2016.11.30
sqlalchemy  (0) 2016.11.28
pexpect.pxssh  (0) 2016.11.24

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

+ Recent posts