dput (sftp) + inotify = FAIL

내부적으로 사용하는 apt 저장소에서는 dput이 incoming으로 올린 데이터를 crontab 을 이용해서 실제 배포용 디렉터리에 복사하고 / .db 업데이트하고 / … 등을 처리하게 했다.

crontab을 써서 사실 상 polling하는 구조가 맘에 안들어서, linux의 inotify를 이용해서 이걸 우회하려고 지난 주 후반부에 뭔가 진행해봤다. 대략 chroot jail에 sftp만 허용한 계정을 만들고 여기에 대해서 upload를 감지하자는거였는데 대략 다음과 같이 진행했다.

  1. scp로 업로드한 파일을 inotify가 인지하고 이에 대해서 처리하는 코드 테스트 (정상 작동)
  2. sftp 로 업로드한 파일에 대해선 inotify가 인지못하고 crontab이 처리
  3. ?!?!?!

3의 대혼란.

intoify를 래핑한 inoticoming 를 사용했는데, 코드를 까보니 주석처리된 디버깅 코드가 있더라; 이걸 주석해제하고 돌려보니 아뿔사 -_-

scp와 sftp를 순차적으로 썼을 때 inoticoming이 호출한 inotify에 걸린 이벤트는 아래와 같다. 1

rein@rein:~/inoticoming-0.2.2/build$ ./inoticoming --foreground /tmp/test --suffix .changes echo {} \;
File ready: python-stdeb_0.6.0+git-1_all.deb
File ready: stdeb_0.6.0+git-1_amd64.changes
Will call action echo for: stdeb_0.6.0+git-1_amd64.changes
stdeb_0.6.0+git-1_amd64.changes
File ready: python-stdeb_0.6.0+git-1_all.deb.tmp.1338036938.225992918.7760.688775960
File ready: stdeb_0.6.0+git-1_amd64.changes.tmp.1338036944.455483913.7760.1022155507

dput이 sftp를 통해 업로드할 때 대략 다음과 같은 일을 한다: 2

  1. 위에서 나온 임시 파일 형식으로 파일 업로드; bzrlib/transport/sftp.py:SFTPTransport._put
  2. 업로드가 끝나면 임시 파일을 실제 이름으로 link + 임시 파일 unlink; bzrlib/osutils.py:fancy_rename

그래서 inotify는 이걸 인지할 방법이 없다.

대략 chroot jail에서 scp만 허용하는 쪽으로 바꿔야 할 것 같다. 아니면 dput 말고 딴 걸 쓰거나; 근데 내가 왜 sftp만 허용하는 걸 생각했는지 기억이 나질 않는다 Orz.


  1. python-stdeb는 임의로 가져온 python package다. setup.py가지고 .deb을 빌드할 수 있게 해준다. ↩︎

  2. 정확히는 dput이 사용하는 bzrlib/transport/sftp.py 가 하는 일이 그렇다. ↩︎