pass, expect 프로그램과 함께한 #jekyll 블로그 deploy 스크립트

2 minute read

static 블로깅 툴인 jekyll은 직접 빌드를 해야 한다. 빌드 결과물인 html, css 파일을 웹호스팅 서버로 배포한다. 이걸 수동으로 하고 있었다. script/build 스크립트로 빌드하고 filezilla로 업로드하고 있다. 언젠가는 aws로 옮기고 push hook을 걸어 빌드와 배포를 자동화해야지 하면서. 이게 1년이 넘었네. 언젠가는 해야지 하면서도 별로 불편하지 않아서 aws로 옮기는 건 매번 미루고 있다.

실수 한 번 한 게 트리거가 됐다. 빌드해서 다른 블로그로 올린 실수를 했다. 블로그가 lifelog, ddiary, emacsian, pnotes 이렇게 총 4개인데, 이제까지 실수를 안 한게 더 신기하다. 단순 노가다에 강한 걸까? 또 실수할 게 뻔하니 이참에 자동화를 하자.

사용중인 호스팅 서비스는 패스워드 입력 방식만 지원한다. 이걸 잘 감추는 게 필요하다. deploy 스크립트에 패스워드를 평문으로 남겨놓긴 싫으니. 패스워드 저장에 tpass 프로젝트를 하면서 알게 된 pass 프로그램을 사용하기로 했다.

password=$(pass ftp/www.site.com)

pass를 호출해 패스워드를 꺼낸다.

scp -rv . admin@site.com:path

파일 전송은 scp를 사용했다. 처음엔 sftp를 썼는데, 하위 디렉터리를 순회하며 모든 파일을 업로드하는 방법을 못 찾았다. 나와 비슷한 걸 원하는 사람 질문에 scp 쓰세요라는 답변이 달린 걸 보고 나도 그냥 scp를 사용하기로 했다.

expect <<EOF
    set timeout 600
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
    expect eof
EOF

scp로 파일을 전송할 때, 입력하는 패스워드는 expect 프로그램으로 해결했다. 복사에 시간이 오래 걸릴 수 있어서 타임 아웃을 넉넉하게 설정했다.

#!/bin/sh

set -e

cd "$(dirname "$0")/.."

basepath=/home/user
site=pnotes
password=$(pass ftp/www.site.com)

script/build
cd _site

expect <<EOF
    set timeout 600
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
    expect eof
EOF

전체 스크립트.

삽질1 - expect로 패스워드 입력은 잘 되는데, 파일 전송이 끝날 때까지 안 기다려

expect <<EOF
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
EOF

expect는 spawn 명령어로 만든 프로세스 수명을 제어한다. 패스워드 입력후 바로 종료시켜서 문제가 됐다.

expect <<EOF
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
    expect eof
EOF

전송 끝날때까지 기다리게 했다.

삽질2 - 파일을 전송하다가 중지

scp 명령어에 v 옵션을 붙여 디버깅 정보도 출력했는데, 단서를 못 찾았다.

expect <<EOF
    exp_internal 1
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
    expect eof
EOF

exp_interal 1 명령을 spawn 호출 전에 실행하면 디버깅 정보를 볼 수 있다.

Sink: E
Entering directory: D0755 0
cool-things-chromecast-2nd-generation
Sink: D0755 0 cool-things-chromecast-2nd-generation
Sending file modes: C0644 7560 index.html
Sink: C0644 7560 index.html
index.html                                      0%    0     0.0KB/s   --:-- ETA
dex.html                                    100% 7560     7.4KB/s   00:00
Sink: E
Entering directory: D0755 0 cool-things-hbs-750" (spawn_id exp7) match glob pattern "$ "? no
expect: timed out

아! 타임아웃.

expect <<EOF
    set timeout 600
    spawn scp -rv . admin@site.com:$basepath/$site
    expect "password:"
    send "$password\n"
    expect eof
EOF

타임아웃 기본값은 10초. 업로드하는거니 시간을 넉넉하게 설정했다.