Apache2 + Flask 환경 구성

Apache2 에서 wsgi 모듈을 이용하여 Flask 개발 환경을 구성하는 방법에 대해 간단히 기록한다.

일단, Apache2에서 wsgi 모듈을 설치해야 한다.

sudo apt-get install libapache2-mod-wsgi

그 후에 간단한 구조를 구성해준다. 나는 그냥 간단하게 /FLASK/flask_app 폴더에 __init__.py와 flask_app.wsgi 파일을 생성해두었다.

/FLASK/flask_app/
                /__init__.py
                /flask_app.wsgi

먼저 __init__.py 에 Flask를 이용한 화면 뷰를 구성해준다.

import flask

app = flask.Flask(__name__)

@app.route("/")
def ok_print():
    return "OK!"

if __name__ == '__main__':
    app.run()

간단하게 접속하면 “OK!”를 뿌려주는 뷰이다. 다음으로 flask_app.wsgi 파일을 생성해준다.

#!/usr/bin/python
import sys
sys.path.insert(0, "/FLASK/")
from flask_app import app as application

간단히 보면 현재 패스를 /FLASK로 변경하고 flask_app의 app을 application으로 할당하여 apache2 mod_wsgi 모듈을 통해 실행한다는 의미로 이해된다. 그리고 /FLASK 폴더의 권한을 www-data:www-data로 할당한다.

chown -R www-data:www-data /FLASK

마지막으로 VirtualHost 세팅을 아래을 위해 /etc/apache2/sites-available 폴더에 파일을 하나 생성한다. 나는 편리한 사용을 위해 ok.teshi.net.conf 라는 파일명으로 생성해주었다. 해당 파일 내용은 아래와 같다.

<VirtualHost *:80>
        ServerAdmin [Mail Address]
        ServerName ok.teshi.net
        ErrorLog ${APACHE_LOG_DIR}/ok/error.log
        CustomLog ${APACHE_LOG_DIR}/ok/access.log combined

        WSGIDaemonProcess flask_app user=www-data group=www-data threads=5
        WSGIProcessGroup flask_app
        WSGIScriptAlias / /FLASK/flask_app/flask_app.wsgi
        <Directory /FLASK/flask_app>
            Order deny,allow
            Allow from all
            Require all granted
        </Directory>
        <Files /FLASK/flask_app/flask_app.wsgi>
            Order deny,allow
            Allow from all
            Require all granted
        </Files>
</VirtualHost>

위의 파일을 생성한 후,

sudo a2ensite ok.teshi.net

명령어를 사용하여 사이트를 VirtualHost에 추가한다. 그 후 Apache를 다시 불러온다.

sudo systemctl reload apache2

위와 같이 실행한 후 웹페이지를 열어 접속해본다.

[python] 웹 파싱, re 모듈 사용시 주의 사항

최근 웹 크롤링하는 프로그램을 취미삼아 짜고 있는데 특정 단어가 너무 거슬려서 제거 하기 위해서 re 라이브러리를 사용하고 있다.

사실 테스트 삼아 실행한 문자열은 잘 분리해주는데…

실제 적용하면 분리를 못해주는 증상이 있어서 한참보았더니… 유니코드 문제… 하아….

분리를 하려는 대상은 유니코드이고 검색하려는 값이 유니코드가 아니라서 발생한 문제 하아…

filter 값을 유니코드로 주면 해결된다. 혹시 몰라 기록.

Fail2Ban 재설정 기념 로그 살펴보기

Fail2Ban을 재설정하고 차단을 활성화 시킨 후 문득 궁금해졌다.

대략 하루에 몇번의 접속 시도가 있을 것인가에 대한 것이었다.

 

사실 이 블로그 조차 찾아오는 이가 너—–어무 적은데 들어와 봤자 얼마나 오겠어라는 생각에 조회를 해보았다.

 

그런데 생각보다 많다.

2017년 09월 21일 기준 : 로그인 시도 ( 단순 메시지 기준으로 ) 979회

왜? 도대체 여기에 뭐가 있다고?

그렇다면 시도한 IP 주소는 어떻게 될까?

2017년 09월 21일 기준 : 로그인 시도 IP 수는 27개

무려 27 곳에서 내 서버를 탐내고 있다.

 

 

…. 이해가 안된다. 물론 좀비로 쓰려고 하면 할 수 있겠지만 이거참…. 주기적으로 패스워드를 바꿔 주는게 좋을듯 하긴 하다.

 

아무튼 해당 데이터가 어떤지 보려고…. 파이썬을 조금 이용해 보았다.

 

파이썬 + freegeoip 라고 생각하면 좋을 듯 하다.

 

import json
import requests


if __name__ == '__main__':
    country_ip_dict = {}
    for line in open("cut", "r"):
        res = requests.get("http://freegeoip.net/json/" + line.strip()).text
        res_json = json.loads(res)
        if res_json['country_name'] not in country_ip_dict: c
            ountry_ip_dict[res_json['country_name']] = []
        country_ip_dict[res_json['country_name']].append(line.strip())

    key_list = country_ip_dict.keys()
    key_list.sort()

    for _key in key_list:
        print _key, ":", len(country_ip_dict[_key])
        for item in country_ip_dict[_key]:
            print "    -", item

 

그래서 목록을 만들어 보았더니…

 

Australia : 1
– 203.27.138.60
China : 7
– 117.78.34.221
– 123.183.209.135
– 123.59.199.40
– 124.93.247.99
– 182.61.21.98
– 218.28.238.162
– 58.30.96.138
Croatia : 2
– 5.188.10.179
– 5.188.10.182
France : 2
– 212.129.23.96
– 90.41.191.181
Indonesia : 1
– 103.71.255.27
Israel : 1
– 62.219.209.70
Italy : 1
– 212.237.11.114
Netherlands : 1
– 95.211.230.94
Poland : 1
– 62.21.48.119
Republic of Korea : 4
– 1.209.148.74
– 1.221.187.110
– 14.58.118.69
– 180.70.170.34
Russia : 1
– 185.110.132.49
Seychelles : 1
– 93.174.90.30
Singapore : 1
– 139.59.110.43
Sweden : 1
– 85.230.149.52
Ukraine : 1
– 193.201.224.236
United States : 1
– 74.208.169.251

역시 부동의 1위는 중국이다. 아… 진짜… 그리고 2위는 한국이다…

 

가끔은 진짜 궁금해진다. 도대체 무슨 용도로 내 서버에 그리 접속하려는 걸까? 단순히 경유지로 쓰려고? 흠… 뭐… 아무튼… 일하기 싫은 금요일 오후 약간의 삽질을 해보았다.

 

 

[python] psutil 라이브러리의 cpu_times()

쓸데없는 고민의 시작은 자원 모니터링을 구현하려고 하다가 갑자기, 문득, 쓸데없이 떠올랐다.

 

python psutil 라이브러리의 cpu_times() 함수의 결과 값은 /proc/stat 의 값과 동일한가?

 

… 참 쓸데 없다… 아무튼 검증을 해보니… 동일하다. 결국 psutil.cpu_times() 는 jiffy 값을 리턴한다.

python 멀티쓰레딩 환경에서 socket, select, makefile

이글을 쓰게 된 이유는 아래와 같다.

  • python 으로 짜여진 코드를 수정해서 사용해야 한다.
  • Multi Threading 환경으로 구성되어 있다.
  • 기존 코드를 최대한 유지하는 방향으로 작성한다.
  • 사용된 라이브러리는 socket, select 이며,
    makefile 로 socket을 file descriptor 로 변경하여 readline을 사용한다.

여기서 문제가 되었던 기능은

  1. [C] 사용자가 socket으로 특정 쓰레드 생성 명령어 수행
  2. [S] 쓰레드 생성 및 실행
  3. [C] 사용자 접속 종료

으로 심플한 기능이다. 단순히 쓰레드를 실행하는 것일 뿐인데 문제가 되는 부분은 3이었다. 분명 서버단에서 close를 호출하여 file descriptor 를 닫아주었고, socket도 따로 close 했음에도 불구하고 클라이언트는 끊어지지 않은 것으로 판단, 계속해서 동작하는 문제였다. ( 사실 동작은 아니다. 그저 끊어지지 않았을 뿐 )

그래서 구글링한 결과를 정리하자면 먼저 소켓을 shutdown 시키면 되다는 것을 알게 되었다.

sock.shutdown(socket.SHUT_WR)

위와 같이 써준 후 socket을 close 하면 정상 동작한다.