출처: https://qiita.com/o-magari_kun/items/4cdfda0e9d00cbad3160

gocron을 사용하여 작업 스케줄링 수행

Go의 태스크 스케줄 라이브러리는 몇 개 존재하지만, 무한 루프 등으로 대기 상태를 구현할 필요가 없는 gocron을 선택했다.

Go 버전은 1.17.6

main.go

package main

import (
   
"fmt"
        
"path/filepath"

      "github.com/go-co-op/gocron"
        
"github.com/joho/godotenv"
)

func funcA() {
   fmt.Println(
"A")
}
func funcB() {
   fmt.Println(
"B")
}
func funcC() {
   fmt.Println(
"C")
}

func main() {
        err := godotenv.Load(filepath.Join(
"path", "to", "dotenv", ".env"))
        
if err != nil {
                
panic("can't get .env")
        }

        
// gocron.Every(1).Day().At("00:40").Do(funcA)
        
// gocron.Every(1).Saturday().At("11:15").Do(funcB)
        
// gocron.Every(30).Minutes().Do(funcC)
        
// <-gocron.Start()

   scheduler := gocron.NewScheduler(time.Local)
        scheduler.Every(1).Day().At(
"00:40").Do(funcA) //1일 1회 0시 40분에
        scheduler.Every(2).Saturday().At(
"11:15").Do(funcB)// 2주동안에 1회 토요일 11:15에
        scheduler.Every(30).Minutes().Do(funcC)
// 30분에 1회
        scheduler.StartBlocking()
}

서두의 godotenv에 대해서는 후술. 이 샘플 코드의 시점에서는 불필요.

작성한 태스크 스케줄러를 데몬화

샘플 코드를 실행하면 알겠지만, 이 구현은 항상 프로그램을 실행해 두어야 한다.

그래서 바이너리로 컴파일한 것을 사용하여 데몬화를 시도한다.

우선은 바이너리를 작성한다.

   go build -o go_cron main.go

다음으로 데몬화이지만, 이번은 툴을 사용하지 않고 CentOS의 systemd에 service를 추가한다.

cd /etc/systemd/system
vi go_cron.service

go_cron.service

[Unit]
Description=golang cron tool
ConditionPathExists=/path/to/go_cron


[Service]

User=root
Type=simple
ExecStart=/path/to/go_cron/go_cron
Restart=on-failure
TimeoutStartSec=300

[Install]

WantedBy=/path/to/wantedby

ExecStart에 방금 만든 바이너리를 설정한다.

개인적으로 삽질한 부분으로는

.service 파일을 작성한 후 systemd에 변경 사항을 반영

  systemctl daemon-reload

서비스 시작

systemctl start go_cron.service

#
 ステータス確認
systemctl status go_cron.service

go_cron.service - golang cron tool
  Loaded: loaded (/etc/systemd/system/go_cron.service; disabled; vendor preset: disabled)
  Active: active (running) since 火 2022-03-01 13:15:56 JST; 2h 27min ago

Go 소스 코드에서 환경 변수를 사용할 위치가 있는 경우

서비스가 시작했다! 그리고 작업이 시작되기를 기다리고 있었지만 동작하지 않았다.

이럴 때는 journalctl 라는 명령으로 로그를 볼 수 있다.

  sudo journalctl | grep go_cron

로그를 보면 Go의 처리가 내부에서 panic을 일으키고 있었다.

환경 변수를 사용하는 곳을  출력해 보면, 빈 공란이 출력되었다.

그래서 godotenv 패키지를 이용하여 .env 파일의 환경 변수를 사전에 취득하여 무사히 동작했다. 서두의 main.go 소스의 첫 3행은 이러한 이유이다.