UniFi - Mongo 데이터베이스 크기를 조절하고 이전 데이터를 삭제 하는 방법

download at 2017-10-16T17:48:21Z origin

Overview

이 문서는 UniFi 컨트롤러에서 사용하는 데이터베이스 크기를 이전 통계 정보를 제거하여 조절하는 방법에 대하여 서술합니다.

UniFi 장비는 MongoDB를 사용하여 연결된 기기, 컨트롤러 설정, 클라이언트, 통계정보를 저장합니다.

UniFi 컨트롤러의 다수의 장비를 관리하는 작업과 많은 클라이언트를 로깅하는 작업은 비활성화가 되지 않았다면 많은 시간이 필요하게 됩니다. 이 문서에서는 제거 스크립트를 사용하여 X일 이전의 통계치, 알람, 이벤트, 게스트 접속, 비정상적 접근을 한 AP의 탐지 내역, 알려진 클라이언트, 기한이 만료된 바우처, 트래픽 통계치 등을 제거하는 방법에 대하여 서술합니다.

제거 스크립트는 컨트롤러가 올바르게 동작할 수 있도록 하는 꼭 필요한 정보를 제거하지 않습니다.

Note: V5부터 UniFi 컨트롤러는 컨트롤러 내부에서 데이터베이스를 제거하는 옵션을 제공하고 있습니다. UniFi 컨트롤러에 로깅을 할 수 있다고 가정하면, 컴팩트 데이터베이스 기능을 Settings -> Maintenance 에서 사용하십시오.

Table of Contents


윈도우에서 호스팅하는 컨트롤러 데이터를 제거하는 방법

맨위로 가기

전제조건: 컨트롤러는 스크립트를 수행하기 앞서서 구동중이어야합니다. 구동중이지 않다면, 다음 명령어를 입력하기 이전에 컨트롤러를 수행하십시오. 중요한 변경 사항을 수행하기 이전에 항상 백업을 생서하십시오.

Step 1: mongo 다운로드

윈도우 UniFi 인스톨러는 mongo 바이너리를 포함하고 있지 않습니다. MongoDB official download website 를 방문하여 2.4.14 버전을 드롭다운에서 선택하고, CPU 아키텍처에 맞는 .zip 파일을 다운로드 받습니다.

Step 2: mongo 압축풀기

\bin\mongo.exe 파일을 작업 디렉토리에 압축해제합니다. 이 문서에서는 C:\prune\ 를 사용합니다. 패키지의 다른 모든 파일은 무시해도 됩니다.

Step 3: Script 다운로드

이 곳을 클릭 하여 스크립트를 다운로드 받고, 작업 디렉토리에 붙여넣으십시오.

Step 4: 커맨드 프롬프트 실행

윈도우 + R 키를 입력하여 커맨드 프롬프트를 수행합니다. 팝업이 수행되면 cmd 를 입력하고, 엔터키를 입력합니다.

Step 5: 작업 디렉토리로 이동

커맨드 프롬프트에서, 작업 디렉토리를 변경합니다:

cd C:\prune\

Step 6: 테스트 수행

기본값으로, 스크립트의 "dryrun" 모드가 존재하며 해당 모드는 database에서 실제로 수행하지는 않고 데이터를 제거하는 순서를 수행합니다. 이 과정은 실제로 올바르게 동작하는지 확인하기 위해 수행합니다:

mongo.exe --port 27117 < mongo_prune_js.js

결과는 다음과 비슷하게 출력되어야 합니다:

Step 7: "dryrun" 비활성화

스크립트를 수정하여 dryrun을 비활성화하고, 몇일간의 데이터를 보관할지 설정합니다. 기본값으로는 7일간의 데이터를 보관처리합니다. 메모장을 실행하거나, 동일한 텍스트 에디터를 실행하여 스크립트를 수정합니다. (rich text 에디터를 사용하지는 마십시오.) Notepad++ 와 같은 텍스트 에디터 사용을 권장합니다. 이 에디터는 숨겨진 줄바꿈과 같은 의도치 않은 문자가 추가되는 것을 방지합니다.

var days=7; 값을 보관하고자 하는 기간을 수정합니다. 또한 var dryrun=true; 구문을 var dryrun=false; 로 수정하여서 실제로 데이터베이스의 데이터를 삭제하도록 변경합니다.

image0

Step 8: 데이터베이스 데이터 제거하기

수정된 스크립트를 실행하려면, 데이터베이스의 데이터 제거를 시작합니다:

mongo.exe --port 27117 < mongo_prune_js.js

Note: 데이터베이스가 실제로 수정되면, 이 과정은 테스트 과정보다 훨씬 더 오래 수행됩니다. bye 가 출력되기 전까지 콘솔에 인터럽트를 수행하지 마십시오.

Step 9: 완료 검증하기

작업이 성공적으로 완료되었는지 검증하며, 에러가 보고되지 않았다면, 다음과 같은 결과가 출력되어야 합니다:

image1

Step 10 (선택사항): 클린업

디렉토리에서 생성한 파일을 제거합니다.

Mac OS X에서 호스팅하는 컨트롤러 데이터를 제거하는 방법

맨위로 가기

전제조건: 스크립트를 실행하기 이전에 컨트롤러가 구동중이어야합니다. 구동중이지 않다면, 다음 단계를 이전하기 이전에 컨트롤러를 구동하십시오. 중요한 변경 내역을 생성하기 이전에는 항상 백업하는 습관을 들이십시오.

Step 1: 작업 디렉토리 생성하기

컴퓨터에 작업 디렉토리를 생성합니다. 이 문서의 목적으로는 /prune으로 생성합니다.

Step 2: mongo 다운로드

Mac OS X UniFi 인스톨러는 mongod 바이너리를 포함하고 있지 않습니다. MongoDB official download website 에 방문하여 OSX 탭을 클릭하고, 2.4.14 버전을 선택하여 다운로드 받습니다.

Step 3: mongo 압축해제

작업 디렉토리에 다운로드 패키지로 이동합니다. 해당 파일을 더블클릭하여 압축을 해제하거나 원하는 압축해제 애플리케이션을 사용합니다.

Step 4: mongo를 작업 디렉토리로 이동합니다.

bin/mongo 바이너리로 파일을 위치하고, 작업 디렉토리에 해당 파일을 복사합니다. .tgz 패키지를 다운로드하였을 때, 추가로 압축 해제된 파일은 제거해도 됩니다.

Step 5: 작업 디렉토리로 이동

터미널 윈도우를 실행하여 작업 디렉토리로 변경합니다.:

cd /prune

Step 6: 스크립트 다운로드

제거 스크립트를 다운로드 받습니다:

curl "https://ubnt.zendesk.com/hc/article_attachments/115024095828/mongo_prune_js.js" -o "mongo_prune_js.js"

image2

Step 7: 테스트를 수행합니다.

스크립트를 테스트 합니다. 기본 값으로, "dryrun" 모드가 설저오디어 있으며, 이 모드는 데이터베이스에서 데이터를 제거하는 스크립트를 수행하지만, 실제로는 제거하지 않습니다. 이 단게는 예상한대로 스크립트를 수행할 수 있는지 확인합니다:

./mongo --port 27117 < mongo_prune_js.js

결과는 다음과 같이 출력됩니다:

image3

Step 8: "dryrun" 비활성화

스크립트를 수정하여 dryrun을 비활성화 하고 데이터를 보관할 기간을 설정합니다. 기본 값으로, 스크립트는 7일간의 데이터만 보관하도록 수행합니다. nano 혹은 비슷한 스크립트 에디터를 사용하여 수정합니다:

nano mongo_prune_js.js

nano를 사용하여 파일을 수정하는 경우, 화살표 키를 사용하여 텍스트를 이동합니다. var days=7; 값을 수정하여 데이터를 보관할 기간을 설정합니다. var dryrun=true; 값을 var dryrun=false; 으로 변경합니다. 이 값을 변경하면 실제 데이터 삭제를 수행합니다. 준비가 되었으면 CTRL + O를 입력하여 파일을 저장하고, CTRL + X를 입력하여 에디터를 종료합니다.

image4

Step 9: 데이터베이스의 데이터 삭제

수정된 스크립트를 실행하여 실제 데이터베이스의 데이터를 삭제합니다:

./mongo --port 27117 < mongo_prune_js.js

Note: 데이터베이스가 실제로 수정되면 이 과정은 7 단계보다 더 오랜 시간이 소요됩니다. bye 가 출력되기 이전까지 콘솔에 인터럽트를 수행하지 마십시오.

Step 10: 완료 검증하기

과정이 성공적으로 완료되고, 에러가 보고되지 않았다면, 결과는 다음과 같이 출력됩니다:

image5

Step 11: 세션 종료

터미널 세션을 종료합니다:

exit

터미널 윈도우를 종료합니다.

Step 12 (선택사항): 클린업

작업 디렉토리를 삭제합니다.

리눅스 (우분투, 데비안, Cloud Key)에서 호스팅하는 컨트롤러 데이터를 제거하는 방법

맨위로 가기

전제조건: 컨트롤러는 스크립트를 수행하기 앞서서 구동중이어야합니다. 구동중이지 않다면, 다음 단계를 이전하기 이전에 컨트롤러를 구동하십시오. 다음 명령어를 사용하여 컨트롤러를 실행할 수 있습니다:

sudo service unifi start

중요한 변경 내역을 생성하기 이전에는 항상 백업하는 습관을 들이십시오.

Step 1: 커넥션 생성하기

SSH를 사용하여 원하는 클라이언트로 접속하고 인증하여 세션을 생성합니다. 이 섹션의 스크린샷은 PuTTY를 사용하였습니다. 리눅스 혹은 mac 클라이언트를 사용한다면, 내장된 터미널을 사용합니다.

Step 2: 작업 디렉토리로 이동

홈 디렉토리에서 작업 디렉토리를 생성하거나 해당 디렉토리를 사용합니다. 이 문서에서는 홈 디렉토리를 사용합니다.

cd ~

Step 3: 스크립트 다운로드

서버에서 스크립트를 다운로드 받습니다:

wget https://ubnt.zendesk.com/hc/article_attachments/115024095828/mongo_prune_js.js

image6

Step 4: 테스트 수행

스크립트의 테스트를 수행합니다. 기본 값으로 "dryrun" 모드가 설정되어 있으며 이 모드는 데이터베이스에서 데이터를 지우는 스크립트를 수행하지만, 실제로 데이터를 삭제하지는 않습니다:

mongo --port 27117 < mongo_prune_js.js

출력 결과는 다음과 같아야 합니다:

image7

Step 5: "dryrun" 비활성화

스크립트를 수정하여 dryrun을 비활성화 하고 데이터를 보관할 기간을 설정합니다. 기본 값으로, 스크립트는 7일간의 데이터만 보관하도록 수행합니다. nano 혹은 비슷한 스크립트 에디터를 사용하여 수정합니다:

nano mongo_prune_js.js

nano를 사용하여 파일을 수정하는 경우, 화살표 키를 사용하여 텍스트를 이동합니다. var days=7; 값을 수정하여 데이터를 보관할 기간을 설정합니다. var dryrun=true; 값을 var dryrun=false; 으로 변경합니다. 이 값을 변경하면 실제 데이터 삭제를 수행합니다. 준비가 되었으면 CTRL + O를 입력하여 파일을 저장하고, CTRL + X를 입력하여 에디터를 종료합니다.

image8

Note; nano가 설치되지 않아서 에러가 발생한 경우에는, 다음 명령어를 수행하여 에디터를 설치할 수 있습니다.

sudo apt-get update && sudo apt-get -y install nano

Step 6: 데이터베이스 데이터 제거하기

수정한 스크립트를 실행하여 실제 데이터베이스의 데이터를 삭제합니다:

mongo --port 27117 < mongo_prune_js.js

Note: 데이터베이스가 실제로 수정되면, 이 과정은 4 단계보다 더 많은 시간이 소요됩니다. bye 메시지가 출력되기 이전까지 콘솔에 인터럽트를 입력하지 마십시오.

Step 7: 완료 검증

과정이 성공적으로 완료되고, 에러가 보고되지 않았다면, 결과는 다음과 같이 출력됩니다:

image9

Step 8 (선택사항): 클린업

작업 디렉토리의 스크립트를 삭제합니다.

rm mongo_prune_js.js

Step 9: 세션 종료

터미널의 세션을 종료합니다:

exit

레퍼런스를 위한 제거 스크립트


맨위로 가기

아래의 스크립트는 레퍼런스를 위한 제거 스크립트입니다. 이 문서의 기초되는 첨부 스크립트는 다운로드 받을 수 있습니다:

// keep N-day worth of data
var days=7;

// change to false to have the script to really exclude old records
// from the database. While true, no change at all will be made to the DB
var dryrun=true;

var now = new Date().getTime(),
 time_criteria = now - days * 86400 * 1000,
 time_criteria_in_seconds = time_criteria / 1000;

print((dryrun ? "[dryrun] " : "") + "pruning data older than " + days + " days (" + time_criteria + ")... ");

use ace;
var collectionNames = db.getCollectionNames();
for (i=0; i<collectionNames.length; i++) {
 var name = collectionNames[i];
 var query = null;

if (name === 'event' || name === 'alarm') {
 query = {time: {$lt:time_criteria}};
 }

// rogue ap
 if (name === 'rogue') {
 query = {last_seen: {$lt:time_criteria_in_seconds}};
 }

// removes vouchers expired more than '$days' ago
 // active and unused vouchers are NOT touched
 if (name === 'voucher') {
 query = {end_time: {$lt:time_criteria_in_seconds}};
 }

// guest authorization
 if (name === 'guest') {
 query = {end: {$lt:time_criteria_in_seconds}};
 }

// if a user was only seen ONCE, $last_seen will not be defined
// so, if $last_seen not defined, lets use $first_seen instead
// also check if $blocked or $use_fixedip is set. If true, do NOT purge the
// entry no matter how old it is. We want blocked/fixed_ip users to continue
// blocked/fixed_ip. Also noted users should not be deleted.
if (name === 'user') {
 query = { blocked: { $ne: true}, use_fixedip: { $ne: true}, noted: { $ne: true}, $or: [
 {last_seen: {$lt:time_criteria_in_seconds} },
 {last_seen: {$exists: false}, first_seen: {$lt:time_criteria_in_seconds} }
 ]
 };
 }

if (query) {
 count1 = db.getCollection(name).count();
 count2 = db.getCollection(name).find(query).count();
 print((dryrun ? "[dryrun] " : "") + "pruning " + count2 + " entries (total " + count1 + ") from " + name + "... ");
 if (!dryrun) {
 db.getCollection(name).remove(query);
 db.runCommand({ compact: name });
 }
 }
}

if (!dryrun) db.repairDatabase();

use ace_stat;
var collectionNames = db.getCollectionNames();
for (i=0; i<collectionNames.length; i++) {
 var name = collectionNames[i];
 var query = null;

// historical stats (stat.*)
 if (name.indexOf('stat')==0) {
 query = {time: {$lt:time_criteria}};
 }

if (query) {
 count1 = db.getCollection(name).count();
 count2 = db.getCollection(name).find(query).count();
 print((dryrun ? "[dryrun] " : "") + "pruning " + count2 + " entries (total " + count1 + ") from " + name + "... ");
 if (!dryrun) {
 db.getCollection(name).remove(query);
 db.runCommand({ compact: name });
 }
 }
}

if (!dryrun) db.repairDatabase();