정보화용역사업 마무리즈음 백업서비스를 구현해야 할 일이 생겼다.
장고 데이터 덤프기능을 이용하여 데이터 백업하고, 사용자 업로드 파일디렉토리는
rdiff-backup을 쓰면 깔끔하겠다 생각하고는 쉘스크립트. (cron으로 하루 1회 백업하고, 30일 지난 것 지우기)
#!/bin/sh
rdiff-backup /usr/local/dsite /home/agrims_backup/file
rdiff-backup --remove-older-than 30D /home/agrims_backup/file
/usr/local/bin/python /usr/local/dsite/manage.py dumpdata > /home/agrims_backup/db/dump_`date '+%Y%m%d.json'` 2>&1
앗, 쉘스크립트로 dump_20081101.json 이렇게 되어 있는 파일의 30일 이전 것을 어떻게 찾지? 음냐; 저부분은 파이썬으로!
#!/usr/local/bin/python
import sys, os
from datetime import date, timedelta
target = sys.argv[1]
for d in os.listdir(target):
if d.startswith('dump_'):
year = int(d[5:9])
month = int(d[9:11])
day = int(d[11:13])
file_date = date(year,month,day)
if date.today() - file_date > timedelta(30):
os.remove(os.path.join(target, d))
잘 돌아가나 확인을 해봐야하는데, 음... 대충 target 디렉토리에 빈 파일 넣어보고 돌려본다. 잘 되네... 그러고 넘어가려던 중 갑자기
어제 읽은 포스트가 생각났다.
저는 테스트 케이스가 없는 코드를 레거시 코드로 봅니다.
... 테스트 없는 코드는 나쁜 코드입니다. 얼마나 잘 짰는지는 중요치 않아요. 아무리 예뻐도, 아무리 객체지향적이어도, 아무리
캡슐화가 잘 되어 있어도 소용 없습니다. 테스트가 있으면 빠르고 검증가능한 방식으로 코드의 행위를 수정할 수 있습니다. 테스트가
없으면 코드가 좋아지고 있는지 나빠지고 있는지 알 방법이 없지요.
꿀꺽. 나도 테스트가 중요하다는 것쯤은 안다고. 음냐; 테스트 만들자. 그간 테스트없어서 고달펐던 몇몇 일들을 떠올리며,,, 아 그리고 며칠전 읽었던
파이썬스러운 용법들 적용해서 멋스럽게~
#!/usr/local/bin/python
import sys, os
from datetime import date, timedelta
def remove_older_than(target, days, basis=None):
if not basis:
basis = date.today()
for d in os.listdir(target):
if d.startswith('dump_'):
year = int(d[5:9])
month = int(d[9:11])
day = int(d[11:13])
file_date = date(year,month,day)
if basis - file_date > timedelta(30):
os.remove(os.path.join(target, d))
def main():
target = sys.argv[1]
days = sys.argv[2]
remove_older_than(target, days)
return 0
import unittest
class RemoveTest(unittest.TestCase):
def test_remove_older_than(self):
days = 30
basis = date(2008, 11, 27)
target = '/tmp'
recent_filename = os.path.join(target, 'dump_20081101.json')
old_filename = os.path.join(target, 'dump_20081001.json')
open(os.path.join(target, 'dump_20081101.json'),'w')
open(os.path.join(target, 'dump_20081001.json'),'w')
self.assert_(os.path.exists(recent_filename))
self.assert_(os.path.exists(old_filename))
remove_older_than(target, days, basis)
self.assert_(os.path.exists(recent_filename))
self.assert_(not os.path.exists(old_filename))
def tearDown(self):
try:
os.remove(os.path.join(target, 'dump_20081101.json'))
os.remove(os.path.join(target, 'dump_20081001.json'))
except:
pass
if __name__=='__main__':
unittest.main()
status = main()
sys.exit(status)
테스트가 생겨서 뿌듯하긴 하다. 하지만 뭔가 아쉬움이 남는 것이 배보다 배꼽인듯한...
Trackback Address :: http://yong27.biohackers.net/trackback/341