iOS 만 서비스 할때는 그냥 대충 php + cron 으로 push 를 돌렸었는데,

이게 백명 단위만 되어도 delay 문제가 생겨서... async 방식으로 언젠가 도입을 해야지.. 생각만 했었다.


이번에 안드로이드때문에 하게 되었으니.. 겸사겸사...

GCM 으로 iOS 도 사용할 수 있는 방법이 있다는건 봤지만,, 클라를 수정해야 했고..

이미 있는 앱도 같이 적용 + 클라 더 손대기가 귀찮아서 서버쪽을 잘 만들어보기로 했다.



APNS

우선 APNS 는 pyapns 라는 녀석으로 쉽게 asynchronous 한 push 를 구현가능하다.



pyapns 서버를 구축한 후 python 에서


import pyapns

pem_path = 'path_to_push_pem'

pyapns.configure({'HOST': 'http://localhost:7077/'})

pyapns.provision('com.example.appid', pem_path, 'production') #sandbox

push = {'aps': {'alert':'푸시 테스트', 'sound':'default'}}

pyapns.notify('com.example.appid', '### push token ###', push, async=True)


이렇게 사용하면 된다.



GCM

GCM 은 주로 node.js 로 했던 듯 하나... 난 시스템을 통일시키고 싶었다.

찾아보니, 위 pyapns 처럼 로컬에 서버를 열어두고 request를 보내면 되는 방식의 GoCM 이라는 라이브러리가 있었다.

Golang 으로 짜져 있음.



GCM 은 인증서가 필요없고 sandbox / production 구분이 없어서 더 간편하다.

간단히 POST request 만 구현하면 어떻게든 가능하지만, 난 requests 라이브러리 사용을 선호함.


import requests, json

GCM_SEND_ENDPOINT = 'http://localhost:5601/gcm/send'

token = '### token ###'

msg = {'title': '[title]', 'message': 'message'}

requests.post(GCM_SEND_ENDPOINT, data={'tokens': [token], 'payload': json.dumps(msg)})



Daemonize

위 방법대로 하면 이제 APNS / GCM 을 둘다 이용할 수 있게 되지만, 각각 웹서버를 하나 돌려야 해서 귀찮다.

당장은 그냥 쓴다고 해도 재부팅을 한다거나.. 프로세스 유지해주기가 귀찮으니까 데몬으로 만들어버리자.


pyapns 는 python-twistd :: daemon 으로 만들기

GoCM 은 GoCM :: daemon 으로 만들기


글을 각각 참고하면 된다.



Feedback / Report

APNS / GCM 각각 삭제되었거나 더이상 사용되지 않는 token 에 대한 feedback 을 제공해준다.


APNS

pyapns.feedback('com.example.appid') 를 호출하면 

[(timestamp, token), ] 

형태로 반환해준다.


token 으로 uninstalled 처리를 해주면 됨.


GCM

canonicals / notregistered 두가지 feedback 이 존재한다.

전자는 token 이 변경되었을 경우(인 것 같다. 사실 레퍼런스를 안봐서..), 후자는 앱이 삭제된 경우.


이건 그냥 GoCM README 를 보자.



Fin

드디어 Python 만을 사용하여(Go 는 컴파일 한번 하고 끝이니 논외), 하나의 시스템만으로 Asynchronous APNS / GCM 둘다 사용할 수 있게 되었다.


여기선 다루지 않았지만, 동일한 DB에 os 구분하여 token 을 저장하고, os 를 알아서 구분해서 메세지를 보내도록 하면 좀 더 관리가 쉽다.


분명히 두 OS를 같이 서비스하는 사람/업체가 많은데 내가 못찾는건지 다른 방법이 있는건지...

생각처럼 깔끔하고 쉬운 방법이 눈에 안보이네.. 흑

자, 이번엔 GoCM (https://github.com/Flyclops/GoCM) 을 데몬으로 만들어두는 방법.


twistd 와 다르게 단일 컴파일된 실행프로그램이므로.. 조금 golang 이라던가.. 그게 아니라 그냥 별개로 생각하자...

뭐 조금 수정하면 다른 방법에서도 쓸 수 있다.

나도 앞에서 글 쓴 twistd 데몬 스크립트를 수정하였음.


1. GoCM 을 컴파일, 바이너리를 적당히 옮겨둔다. 나의 경우 /usr/bin/GoCM

2. /etc/init.d/GoCMd (뭐 데몬이름은 알아서..) 을 작성한다. 내용은 아래 더보기..


3. 위 파일에서, GoCM 경로와 DAEMON_ARGS 에서 api key 를 수정해준다.

4. $ sudo chmod +x /etc/init.d/GoCMd

5. $ sudo update-rc.d GoCMd defaults

6. $ service GoCMd start

twistd 를 daemon 화 하는 방법.

https://github.com/eagafonov/python-twisted-startup-script 의 방법을 이용한다.


1. /etc/python-twistd.d/ 디렉토리를 생성한다.

2. 위 git 에서 python-twisted-web 파일을 받는다. 그리고 파일 이름과 내용을 필요에 따라 수정. 아래부턴 편의상 그냥 python-twisted-web 이라고 쓰겠지만, 알아서 바꾼 이름을 사용하자.

3. git 에서 python-twisted-startup-script 를 위 python-twisted-web 파일과 이름을 똑같이 만들어서 /etc/init.d/ 에 넣는다.

4. $ sudo chmod +x /etc/init.d/python-twisted-web

5. $ sudo update-rc.d python-twisted-web defaults

6. $ service python-twisted-web start

맥에선 brew 로 잘 깔았던 것 같은데..

우분투에선 apt 로 받으니 버전이 낮다.


여튼 맥이고 우분투고 환경변수 설정 문제도 있으니 써둠.



Mac 일 경우

$ brew install go



Ubuntu 일 경우

1. https://golang.org/dl/ 에서 해당하는 파일을 다운로드

2. $ sudo tar -C /usr/local -xzf go*******.tar.gz

3. 환경변수 추가(/etc/.profile 혹은 ~/.profile)

export GOROOT=/usr/local/go

export PATH=$PATH:$GOROOT/bin


일단 이렇게까지 하면 설치 및 사용은 잘 된다.


GOPATH 설정

그런데 go get 등을 하려면 GOPATH 를 설정하라고 하면서 안됨.

찾아보니 그냥 다운받는 패키지를 저장하는 장소를 지정해달라는 것. 설치 디렉토리는 여러 이유로 안됨.(권한, 업데이트 등등)

나는 그냥 ~/golang/pkg 로 지정하였다.

export GOPATH=~/golang/pkg


이러면 go get 등도 잘 됨


go install 을 할 경우 $GOPATH/bin 에 생긴다.




참고:

http://munchpress.com/install-golang-1-5-on-ubuntu/

Ebay 등에서 저렴한 아두이노를 사면 문제가 하나 있는데, 바로 드라이버 인식이 바로 안된다...


본래 사용되는 FT232RL 등의 USB 칩은 인증이 되어있거나 이미 탑재된 경우가 대다수인데,

자체 정책으로 $3 이하로는 못판다나 뭐라나..


여튼 그래서 중국에서 CH340, CH340G or CH341 등의 칩셋을 대신 사용하는데, 이 경우 Windows 건 Mac 이건 따로 커널 드라이버를 설치해줘야함은 물론 signing 도 받지 않아 여러 경고문..을 볼 수가 있다.


----------------------------

수정.


https://tzapu.com/ch340-ch341-serial-adapters-macos-sierra/


이 주소에서 드라이버를 받으면 rootless 를 끄지 않고도 인식 및 사용가능!

sierra 이후는 아래 방법으로 진행하면 연결시 커널패닉.. 이 일어난다.

그냥 윗 링크에서 받아서 사용하자.


----------------------------


Mac 의 경우 rootless 기능이 생기면서 좀 곤란해졌는데, 쉽게 말해 rootless 를 끄지 않으면 사용할 수 없다..


커널 익스텐션 체크만 끌 수 있다는게 다행이면 다행이려나..


여튼,

1. 재부팅하면서 Cmd+R 을 눌러 복구모드로 진입한다

2. 터미널을 실행한다

3. csrutil enable --without kext

4. 재부팅



참고:

http://tzapu.com/making-ch340-ch341-serial-adapters-work-under-el-capitan-os-x/


드라이버 (for MAC):

http://www.wch.cn/download/CH341SER_MAC_ZIP.html

망할 윈도우... BMP 쓰기가 너무 싫어 몇시간을 삽질했다..


GDI+ 를 사용하므로 

gdiplus.lib 

를 프로젝트 속성 - Linker - Input - Additional Dependencies 에 넣어주고


#include <gdiplus.h>

using namespace Gdiplus;


를 코드 상단에 적어주자.





위 코드로 

HBITMAP hBitmap = LoadPNGToHBITMAP(MAKEINTRESOURCE(IDB_PNG));

와 같이 이미지를 불러온 후에


WM_PAINT 메세지에서 아래 더보기와 같이 그려주면 된다.

사이즈는 원래 구하는 코드가 있었는데, 난 필요없어서 제거함. 그정도는 구글링하자.(후에 내 자신을 원망하겠지..)




* VS 2015 에서 VS 2010 의 컴파일러를 사용하여, Win XP SP3 및 Win 7 SP1 에서의 작동을 확인하였다.



수동으로 동기화

sudo ntpdate pool.ntp.org


자동으로 동기화 (데몬 설치)

sudo apt-get install ntp


참고 (사실 여기에 다 있음)

https://www.digitalocean.com/community/tutorials/how-to-set-up-time-synchronization-on-ubuntu-12-04

아두이노로 인터넷 연결을 사용하고 싶었으나, 학교 무선망은 기업용 WPA2 였고, 이는 OS 레벨단의, 잘 만들어진, 인증이 없으면 사용하기 힘들다는 글들만...


가능한 모듈이 있다고 한들 그 가격이 비쌀것이기에 결국 라즈베리파이로 눈을 돌렸다.


라즈베리파이에서도 연결하는게 쉽진 않았지만 여튼...


설정법이 워낙 다양하겠지만, 우리학교(UNIST)에선 이렇게 가능했다.


참고로 우리 학교 공용망에 대해 간략히 설명하자면

SSID: WUNIST_AAA

보안종류: WPA2 Enterprise

암호화: AES

네트워크 인증 방법: PEAP

EAP 인증 방법: MSCHAP v2

*서버 인증서 유효성 검사 하지 않음


1. wpa_supplicant 설정

우선

/etc/wpa_supplicant/wpa_supplicant.conf

이 파일의 내용을 수정한다.



ssid 는 알거고,

key_mgmt 는 개인용이 WPA-PSK / 기업용이 WPA-EAP

proto 랑 pairwise 는 아래 표 참고

 

WPA1 

WPA2 

proto 

WPA 

RSN 

pairwise

TKIP

CCMP 

identity 랑 password 는 인증정보 알아서 입력해주면 되고,

scan_ssid / eap / phase1 / phase2 등도 위와 같이 입력해주면 된다.


뭐 없어도 되는 값들이 있을 수 있지만, 그냥 저 상태로 잘 되길래 더이상 터치 안했다.


보통 ca_cert 값에, pem 파일을 넣을텐데, 위에 적었듯이, 서버 인증서 유효성 검사를 하지 않을 경우 생략하면 된다.



2. 설정 확인

설정 및 인증이 잘 되는지 확인해보려면 아래와 같은 명령어를 사용한다.

우선 네트워크 연결을 꺼주고..

# ifdown wlan0

우리가 만든 설정파일로 연결을 시도한다.

# wpa_supplicant -Dwext -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf

(혹시나 네트워크 이름이 wlan0 이 아닐경우 바꿔주자.)


참고로 -B 옵션은 백그라운드. 밑에선 쓴다.


로그를 읽어보면 '아 안됐구나..' / '어 된건가?'

하는 감이 온다.(귀찮)



3. network interface 설정

/etc/network/interfaces 를 아래와 같이 수정해준다.


lo, eth0 인터페이스들은 알아서 하고,



이렇게 입력해준다.


4. 연결하기

# ifdown wlan0

# ifup wlan0


을 한 후, 로그에서 DHCP 로 아이피까지 잘 받아오면 성공.


나의 경우 2번에 한번 꼴로 잡는 것 같은데, 왜그런진 잘 모르겠다.

재부팅시마다 잘 잡아야 할텐데...;;;


그냥 시간이 좀 걸리는 것 같기도 하고....



참고 URL

http://weworkweplay.com/play/automatically-connect-a-raspberry-pi-to-a-wifi-network/

https://www.raspberrypi.org/forums/viewtopic.php?p=353961

별로 추천하지 않는 방법이라곤 했지만.. 깔끔하게 하고 싶어서 이렇게 했었다.

/w/ 으로 변경하긴 했지만...


하위 디렉토리 없게 (http://aaa.bbb.ccc/대문)

/.htaccess

/wiki/~~~~


.htaccess


wiki/LocalSettings.php



난 userdir 을 별로 좋아하지도 않고 따라서 잘 쓰지도 않는데,

동아리 서버는 특성상 해당 모듈을 켜두고 있었다.


근데 동아리 친구로부터 "php 파일이 다운로드 되는데 내 컴이 이상한거야?"

라는 문의를 받고..


확인해보니 php가 그냥 다운받아져버리는 심각한 문제를 확인..


실서비스 중인 것도 몇개 해당 서버에 있었기에, 최근 패키지 업데이트 이후 설정이 꼬인 문젠가 싶어서 급하게 확인해봤는데

다행히 그냥 userdir 안의 파일들만 그러하였다. 물론 그렇다고 문제가 없는건 아니지만..


=========== 여기까지 쓸데없는 서론 =================


여튼, 결론만 말하자면, userdir 안에서의 php 모듈이 기본적으로 disable 상태이다.


/etc/apache2/mods-enabled/php5.conf

파일에서

<IfModule mod_userdir.c>

    <Directory /home/*/public_html>

        php_admin_value engine Off

    </Directory>

</IfModule>


부분을 전체 주석처리(#) 해버리면 된다.

Off를 On 으로 바꾸는것 또한 가능하지만,

.htaccess 파일을 이용하여 php 를 꺼버리는(보통 업로드 폴더에서 보안을 목적으로 주로 해둔다.) 작업이 불가능해지므로

그냥 주석 처리 혹은 지워버리는 것을 추천.



참고:

http://devplant.net/2010/05/04/linux-php-not-working-in-userdir-public_html/


'Linux, Server, Web' 카테고리의 다른 글

python-twistd :: daemon 으로 만들기  (0) 2015.12.23
우분투 시간 동기화  (0) 2015.11.01
MediaWiki URL 설정  (0) 2015.07.30
특정 국가(중국!!) 차단하기  (0) 2013.10.19
Unix, Linux, BSD, 그리고 MacOS  (0) 2013.01.03

+ Recent posts