Apache에서 error.log에 Too many open files 라는 로그가 남았다. 이게 무슨 말일까? 찾아봤더니, 주어진 계정에서 열 수 있는 최대 파일의 갯수를 초과했다는 이야기란다. 이런 로그가 남았다면, 열 수 있는 최대 파일의 갯수를 조정해주어야 한다. 사실 나는 socket과 관련된 부분에서 이 에러가 났었다. (자세히 기억이 안나네요.)


아래 링크들을 참고하자. 

http://pchero21.com/918

http://stackoverflow.com/questions/2569620/socket-accept-error-24-to-many-open-files

http://rtoodtoo.net/2012/03/07/how-to-use-ulimit-utility-to-restrict-users/


크게 손댈것 없이 첫번째 링크에서 제안하는 방법대로 limit.conf에 계정과 열 수 있는 최대 파일의 갯수를 지정해주었다. 이 다음 재부팅하니 잘 먹혀들어갔다. 


다음의 명령어로 확인할 수 있다. ulimit -Hn (이건 hard 권한, 즉 수퍼유저의 경우), ulimit -Sn (이건 soft 권한, 일반적인 계정의 경우).


여기서 사실 최대 process의 갯수도 정해줄 수 있는데, 너무 작게 할 경우 gnome을 이용한 X window로 진입시 크나큰 문제가 생긴다. (200으로 정해줬는데... 문제가 생겨서 혼났네요.) 정해주지 않을 경우 사실상 무한대의 process가 생성될 수 있는것 같다. 


만약 gnome에서 포크 에러가 느닷없이 발생한다면, 보통 process의 숫자에 제한이 걸려 실행이 되지 않는 경우일 것이다. X window에서 벗어나 command 모드로 들어가도 -bash: fork: retry: No child processes 에러가 발생한다.


이 경우 process의 제한을 지워주면 잘 해결된다. 



여러 검색 끝에 알아낸 원포인트 솔루션!


from py2exe.build_exe import py2exe

from distutils.core import setup

setup(options = {'py2exe': {'bundle_files': 1, "dll_excludes":['w9xpopen.exe'],"compressed":1 }}, windows = [{'script': "ccc.py"}], zipfile = None)


위에서 ccc.py에 원하는 파일 이름을 쓰면 된다.


간단히 해보니 pyQT4 라이브러리가 들어가도 10Mb 정도밖에 안되네. 

정말 많이 삽질했다..ㅜ


sqlite3에서 좋은 점은 full-text searching 알고리즘을 제공한다는 점이다. 물론 모든 테이블에 적용 가능한 것은 아니고, virtual table을 memory에 fts3을 적용하여 만들고, 여기서 검색을 해야 한다.


근데 문제가 있는데... python을 설치하면서 따라온 sqlite3의 query syntax가 하필이면(!) "Standard Query Syntax"라는 점이다. 이게 표준이라고 이름이 붙었지만 MATCH 문법을 쓸 때의 operator에 제한이 있어 사용하기가 불편하다. 자세히 살펴보지 않았지만 sqlite3를 컴파일해서 설치할 때 옵션을 바꾸어주면 정말 편리한 "Enhanced Query Syntax (EQS)"를 사용할 수 있다고 한다. 


두 개의 Syntax 차이점 중 이번에 삽질하게 된 것은 바로 not operator이다. 


EQS의 경우 NOT operator를 따로 제공해준다. OR과 AND operator도 제공해주어 직관적으로 MATCH 문법의 쿼리를 짤 수 있다. 예를 들어, a, b, c 중 하나 이상을 포함하면서도 d, e 중 하나라도 들어있으면 안되는 상황을 생각해보자. 이 경우에 쿼리는 다음과 같이 만들어진다. 물론 EQS에서만... 


column_name MATCH '(a OR b OR C) NOT (d OR e)';


게다가 a, b, c..., e 와 같은 키워드들이 phrase여도 문제가 없다. 즉, "sony vaio" 처럼 주어진 구문의 매칭여부까지 포함한다. 


그런데 SQS의 경우 상황이 조금 다르다. 우선 NOT operator가 없다는게 가장 큰 함정. 대신 - 기호의 operator를 제공해준다. 이 놈의 역할은 NOT operator와 비슷한데 다른점이라면 phrase에서 적용되지 않는다는 점이다. -.-;;; 물론 AND operator 역시 없으며, 그냥 띄어쓰기가 이를 대신한다. 


만약 위와 같은 예제에서 매칭되는 키워드들이 모두 진짜 word라면, 


column_name MATCH '"a" OR "b" OR "c" (-d -e)';


뭐 이런식으로 써야 할 것 같다. (sqlite expert 프로그램에서는 안되네요..;;;) 그런데 문제는 d와 e가 word가 아닌 phrase일 경우... 이런 식의 쿼리문은 에러를 낸다. Stackoverflow에서 봤던 것 같은데, 이를 위해서는 결국 내부쿼리를 이용해서 이런 record들을 빼주는 식으로 처리해야 한다.


SELECT * from table WHERE column_name MATCH '"a" OR "b" OR "c"' and id not IN (SELECT id from table WHERE column_name MATCH '"d" OR "e"');


여기서 a, b, c, d, e 모두 phrase라고 생각해야 한다. 그냥 word였으면 위의 방법대로 되니까...ㅎ


이외에도 SQS와 EQS는 연산자의 순서도 다르다. 그래서 쿼리문을 짜놓고 헷갈리면... 엉뚱한 결과가 나올 수 있다. 자세한 것은 아래 링크에서... (영문)


http://www.sqlite.org/fts3.html#section_3_1



+ Recent posts