Mac에서 git commit - push 자동화시키기

SongWoo Yu·2025년 3월 13일
0

Git

목록 보기
1/3

얼마 전 나의 Desktop 디렉토리를 날려먹은 경험을 앞선 포스팅을 통해서 전해드렸다. 한동안 git에 백업하지 않았던 Obsidian file이 사라진 것이 가장 큰 문제였다. 다른 파일들은 그나마 여러 자료들과 개인적인 증명서 등만 가지고 있었기에 큰 문제는 되지 않았지만, 그동안 요구사항 정리와 매일매일 정리한 내용들이 30일치가 사라져 아주 큰 타격이 되었다.

이를 방지하기 위해서 매일매일 git에 백업을 하겠다고 다짐했지만, 쉽지만은 않았다. 그저 터미널을 열고 git commit -m '2025-03-13 obsidian backups' git push 이렇게만 적으면 되는 것인데 말이다.

이런 이야기를 박 수석님께 말씀드렸더니, 자동으로 옵시디언을 백업해보자고 말씀하셨다. 그리고 지금 우리가 가지고 있는 DB도 자동 백업을 해보자고 하셔서 그 방법을 해보려고 한다. 먼저 shell script를 생성하고, 이를 자동으로 실행되게 하면 된다. 생성된 스크립트를 맥에서 제공하는 자동화 프로그램(crontab, launchctl)을 통해 일정 주기마다 자동으로 실행할 수 있는 방법이다. 많은 시간을 들여서 해봤지만, 잘 동작하지 않아 나중에 제대로 정리해보려고 한다.

1. CronJab, Launchctl 시도 - 실패

대강 설명하자면 스크립트까지는 잘 실행이 되었다. 그러나 crontab과 launchctl에서 자동으로 실행시키지 못하는 문제가 발생하였던 것이다. 순서는 홈 디렉토리에 스크립트와 logs 디렉토리를 생성하는 것으로 시작한다.

cd
mkdir -p ~/scripts
mkdir -p ~/logs

스크립트 디렉토리에 편집기를 사용하여 zsh 파일을 하나 생성한다. vi ~/scripts/auto_commit.zsh 내용은 하려고 하는대로 만들면 된다.

#log pile 경로
LOG_FILE='/Users/(Username)/logs/auto_commit.log"
ERR_LOG_FILE="'/Users/(Username)/logs/auto_commit_err.log"

#저장소 디렉토리
REPO_DIR="(커밋하려는 저장소의 절대경로)"
COMMIT_MESSAGE="자동 커밋: $(date '+%Y-%m-%d %H:%M:%S')"

# 디렉토리로 이동
cd "$REPO_DIR" || {
    echo "디렉토리 이동 실패: $REPO_DIR" >> "$ERR_LOG_FILE"
    exit 1
}

# Git 명령어 실행
if [[ -n $(/usr/bin/git status --porcelain 2>>"$ERR_LOG_FILE") ]]; then
    /usr/bin/git add . || {
        echo "git add 실패" >> "$ERR_LOG_FILE"
        exit 1
    }
    /usr/bin/git commit -m "$COMMIT_MESSAGE" || {
        echo "git commit 실패" >> "$ERR_LOG_FILE"
        exit 1
    }
    /usr/bin/git push origin main || {
        echo "git push 실패" >> "$ERR_LOG_FILE"
        exit 1
    }
    echo "커밋과 푸시 완료: $COMMIT_MESSAGE" >> "$LOG_FILE"
else
    echo "변경사항 없음: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
fi

이제 실행 권한을 부여해주면 스크립트는 완성이다. chmod +x ~/scripts/auto_commit.zsh ls -l ~/scripts/auto_commit.zsh 테스트를 해보자면 다음과 같이 직접 실행시킨 다음에 로그를 확인해주면 된다.

~/scripts/auto_commit.zsh
cat ~/logs/auto_commit.log
cat ~/logs/auto_commit_err.log

이제 어떤 간격으로 이 쉘스크립트를 실행시킬지는 clontab을 만들거나 plist 파일을 생성해주면 거의 다 끝난다. 크론탭은 유닉스 계열에서 사용되는 자동화 툴로 맥에서도 지원해준다. crontab -e를 통해 편지기를 열어주고, i를 눌러 편집 모드로 들어간다. 형식을 맞춰 0 2 * * * /Users/(Usersname)/scripts/auto_commit.zsh 이렇게 작성해주면 매일 새벽 2시에 이 스크립트를 실행해야 한다. 근데 우리는 실패했다. 그래서 맥에서 지원하는 launchectl 방식을 해보기로 했다.

다음 방법은 plist를 생성하고 launchectl로 실행시키면 된다. 먼저 라이브러리에 이 파일을 만들어주겠다. vi ~/Library/LaunchAgents/com.user.autocommit.plist 내용은 다음과 같이 쓰면 된다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.autocommit</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/zsh</string>
        <string>/Users/(Usersname)/scripts/auto_commit.zsh</string>
    </array>
    <key>StartInterval</key>
    <integer>600</integer>
    <key>StandardOutPath</key>
    <string>/Users/(Username)/logs/auto_commit.log</string>
    <key>StandardErrorPath</key>
    <string>/Users/(username)/logs/auto_commit_err.log</string>
    <key>WorkingDirectory</key>
    <string>(커밋할 깃 로컬 저장소 디렉토리)</string>
</dict>
</plist>

이제 10분 마다 커밋을 해주는 plist를 만들었고, 마지막으로 형식 검증과 launchtls 설정을 해주면 된다. 홈 디렉토리에서 plutil ~/Library/LaunchAgents/com.user.autocommit.plist를 통해 형식을 검증하면 문제가 없다면 ok 문구가 나온다. 그리고 작업을 등록하는 방법은 launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.user.autocommit.plist이고, 작업을 시작하는 방법은 vi ~/Library/LaunchAgents/com.user.autocommit.plist이다. 이후 잘 등록되었는지 확인은 launchctl list | grep com.user.autocommit을 통해 할 수 있다.

제대로 작동하는지 확인은 다음과 같이 할 수 있는데, 실패했다.

cd ~/logs
sleep 600
ls -la
cat auto_commit.log
cat auto_commit_err.log

2. Node-RED 설치하기

이번에는 Node-RED라는 자동화 프로그램을 설치해서 내 로컬에서 사용해보도록 하겠다. 이번에는 내 컴퓨터에 있는 스크립트를 일정 시간마다 crontab이나 launchctl와 비슷하게 시간이 되면 실행해주는 프로그램을 이용해보려고 한다. 이를 위해서 스크립트는 컴퓨터에서 작성해서 저장하고 있어야 하고, 프로그램도 설치되어 있어야 하며, 백그라운드에서 작동되고 있어야 한다.

가장 먼저 프로그램부터 설치해주겠다. Node-RED에 접속하여 Get Started 버튼을 누른다. run locally로 들어가면 윈도우, 라즈베리파이 등에서 설치할 수 있는 방법과 Node.js를 통해 설치할 수 있는 방법이 나온다. 우리는 유닉스에서 사용하는 방식으로 후자를 선택해야 한다. 이때도 많은 방식이 있다. npm, docker, snap 등을 통한 설치 방식이 있지만, 우리는 가장 쉬운 npm을 통한 방식을 선택할 생각이다. npm이 설치되어 있지 않다면 homebrew를 먼저 설치한 다음 node.js를 설치해주면 자동으로 npm을 사용할 수 있다.

가장 먼저 터미널에 sudo npm install -g --unsafe-perm node-red를 입력하면, 컴퓨터 pw를 묻는다. 제대로 입력하면 설치과정을 거쳐서 다음과 같은 출력을 보여준다.

+ node-red@1.1.0
added 332 packages from 341 contributors in 18.494s
found 0 vulnerabilities

이제 실행을 하려면 node-red라는 명령어 하나만 사용해도 실행할 수 있다. 실행 종료는 ctrl + c

이제 http://127.0.0.1:1880/ 를 통해 localhost에 접속할 수 있다. 다만 내 컴퓨터에서만 작동하는 방식(local)이니 당연히 다른 웹에서 작성한다고 해도 접속할 수 없다. 자세한 내용은 로컬 웹 설명 부분에서 보면 된다.

3. 스크립트 생성하기

작업을 확인하기 위해 간단한 스크립트를 생성하고 nodered를 통해 자동으로 실행해보겠다. hello world를 출력하고 이를 txt 파일로 만드는 스크립트를 만들었다. vi auto_commit.sh를 만들어 내용은 다음과 같이 추가했다.

#!/bin/zsh
echo "Hello World"
touch /Users/songwoo/scripts/helelel.txt

./auto_commit.sh로 실행해주면 제대로 값이 출력되고, txt 파일도 생성되는 모습을 볼 수 있다. 이제 이걸로 실험해본 후, 내용을 커밋해주는 스크립트로 바꾸면 된다.

4. 백그라운드에서 자동으로 실행하도록 하기

두 방법을 사용했는데, 하나는 원래 되야 하지만 맥이 막고 있는 방법이었다. 일단 node-red를 컴퓨터를 켜면 열리게 하고 싶었기에 system setting - general - login items & extensions에 추가를 해줬다. 그랬더니 그냥 js 파일만 열렸던 것이다. 그 이유는 심볼릭 링크로 된 파일을 직접 가져왔기 때문이라고 한다. 이를 해결하기 위해 스크립트로 직접 실행하는 파일을 만들었다.
그래서 스크립트를 하나 만들어서 이를 실행하도록 조치했다. vi start-node-red.sh 내용은 #!/bin/bash /opt/homebrew/bin/node /opt/homebrew/lib/node_modules/node-red/red.js으로 만들었고, ./node-red.sh로 실행시킨 결과 잘 작동했다.

이 스크립트를 추가해서 로그인해봤더니 이번에는 x-code가 열렸다.

이제 웹과 AI를 통해 원인을 분석해보니, 맥에서는 그냥 스크립트나 앱을 바로 실행하지 못하게 한다고 한다. 정확히 말하면, 맥에서 제공하는 automator 앱을 통해서 하거나, 앱에서 요청해서 allow를 받은 것들만 이렇게 작동한다는 것이다(당연히 아닐 가능성도 높다. 내가 아직 부족하기에 추후에 더 알아보려고 한다.)

automator에서 application을 만들어줄거다. 라이브러리에서 run shell script를 선택하고 bin/zsh를 선택한다.
그리고 내부의 cat 자동 저장값을 삭제하고 앱의 절대 경로를 올려준다. 이를 저장하면 끝이다.

이제 login items & extension으로 돌아와서 +버튼을 클릭하고 아이클라우드의 automator을 들어가면 아까 생성한 StarNodeRed.app이 존재하니 그걸 open해주면 로그인시 실행된다.

로컬 웹을 바탕화면에 저장하고 자동화 스크립트 등록하기

그저 웹 도메인 주소를 드레그한 다음 배경화면에 드랍하면 앞으로 배경화면에서 빠르게 접속할 수 있게 된다. get info에서 이미지를 드레그 앤 드랍 방식으로 붙여넣으면 깔끔하게 이미지도 설정할 수 있다.

자동화 설정하기

일단 inject 블럭을 끌고와 가장 처음에 배치한다. 이를 통해 어떤 주기로 실행할 것인지 설정할 수 있다.

좀 더 자세히 보면 언제 실행할지를 정할 수 있다. 위 부분은 좀 더 공부를 해봐야겠지만, Repeat부분에서 none, interval, interval between times, at a specific time과 같이 반복 주기를 설정할 수 있다. 일단 빠르게 해당 작업을 확인하기 위해서 1분 주기로 실행해 보려고 한다.

그 다음은 exec를 생성하여 command에 zsh 파일을 실행하도록 설정했다. 이때 절대경로를 이용해야 실행이 된다.
화면에서 Deploy를 누르고 보면 일단 파일이 하나 생성되고, debug에도 hello world가 생성된 모습을 볼 수 있다.
1분마다 하나씩 출력하고 있는 모습이다. 터미널을 통해 확인해도 1분마다 helelel.txt 파일을 생성하는 모습을 확인할 수 있다.

이제 이 스크립트를 옵시디언을 커밋해주는 스크립트로 변경하여 실제 이용이 되는지 확인해보려고 한다. vi auto_commit.zsh를 통해 편집기를 열어준다. ggdG를 누르면 내용이 전체가 지워진다. 잘못 지웠다면 esc + :q!를 입력하여 나와준다.

내용은 다음과 같이 작성해주면 된다.

#!/bin/zsh
LOG_FILE="/Users/(username)/logs/auto_commit.log"
ERR_LOG_FILE="/Users/(username)/logs/auto_commit_err.log"
REPO_DIR="/Users/(username)/Desktop/obsidian/obsidian_mac"
COMMIT_MESSAGE="자동 커밋: $(date '+%Y-%m-%d %H:%M:%S')"

echo "실행 환경: Node-RED" > "$LOG_FILE"  # 덮어쓰기
echo "PATH: $PATH" >> "$LOG_FILE"
echo "현재 디렉토리: $(/bin/pwd)" >> "$LOG_FILE"
echo "Git 경로: $(/usr/bin/which git)" >> "$LOG_FILE"
echo "사용자: $(whoami)" >> "$LOG_FILE"

cd "$REPO_DIR" || { echo "디렉토리 이동 실패: $REPO_DIR" > "$ERR_LOG_FILE"; exit 1; }
if [[ -n $(/usr/bin/git status --porcelain 2>>"$ERR_LOG_FILE") ]]; then
    /usr/bin/git add . || { echo "git add 실패" >> "$ERR_LOG_FILE"; exit 1; }
    /usr/bin/git commit -m "$COMMIT_MESSAGE" || { echo "git commit 실패" >> "$ERR_LOG_FILE"; exit 1; }
    /usr/bin/git push origin main || { echo "git push 실패" >> "$ERR_LOG_FILE"; exit 1; }
    echo "커밋과 푸시 완료: $COMMIT_MESSAGE" >> "$LOG_FILE"
else
    echo "변경사항 없음: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE"
fi

수동으로 스크립트를 실행하여 잘 되는지 확인한다.

1분마다 커밋되도록 설정하고 1분마다 내용을 변경해보려고 한다.
git hub에서 커밋 주기가 1분마다 커밋하고 있다.

log에도 잘 기록하고 있고 내용도 잘 변경된 것을 확인할 수 있다.

내일은 이를 이용하여 DB를 백업해보도록 하겠다.

0개의 댓글