跳轉到

crontab 範本

tapioctl 走 non-root,以 broker operator user 執行。

RPM 不會自動寫 crontab

Tapio RPM 安裝時不會觸碰 crontab。各部署的作業時間因 broker 而異,請依實際需求照以下範本自行設定。

crontab 有三種設定位置。大多數部署用 /etc/crontab:有 root、想集中管理、不需要額外建立新檔案。 若有多套系統共用同一台機器、需要用 Ansible 管理,改用 /etc/cron.d/tapio。 若無 root 權限,才改用 user crontab。

三種做法比較

user crontab /etc/crontab /etc/cron.d/tapio
需要 root
格式有 username 欄位
與其他 job 隔離 是(各自帳號) 否(全混一起) 是(獨立檔案)
集中管理
可用 scp / Ansible 部署 可,但會影響整個檔案

設計重點

每天都跑,不限週一到五

星期欄用 * 而非 1-5。原因:週五夜盤會交易到週六凌晨,若只設 1-5,週六早上六點的停機排程不會執行,Tapio 會一直掛著到下週一。 每天都跑開關最簡單,tapioctl 本身是冪等的——服務已停就沒有作用,不會造成副作用。

每日時間序

06:00 — 關機批次

同時送出 stop corestop live-syncstop taifex-fetcher,接著 stop quote-receiver。 所有 daemon 停止後,系統進入維護窗口。

06:02 — 匯出稽核紀錄(選填)

tapio-order-risk-log-exporttapio-login-log-export 必須在 rollover 之前執行。 rollover 會更新 system_date,若在 rollover 後才跑,讀到的日期已是新的交易日,匯出的資料會對不上。 daemon 在 6:00–6:01 已全部停止,此時跑匯出可取得完整的當日紀錄。 轉檔最多可能耗時五分鐘,排在 6:02 可確保在 6:10 rollover 前有充裕時間完成。 兩支工具彼此獨立,可並行;輸出目錄由 -config 指定的 Tapio.toml 決定。 -date auto 會自動讀取目前的 system_date,免去自行 cat 檔案。 不影響交易流程,不排也無妨。

06:10 — rollover(換日)

必須在所有 daemon stop 之後、任何 daemon start 之前執行。 rollover 依當日日期建立 log 目錄、切換 session 資料。若先啟動 daemon 再換日, QuoteReceiver 的 stdout 會寫到昨天的目錄,Tapio 啟動時讀到的 session 資料也是昨天的。

06:15 — 封存舊日資料

tapioctl archive --older-than 7d 在 rollover 之後、行情重啟之前執行。 此時所有 daemon 都已停止,磁碟 I/O 不會影響交易路徑。 archive 以 flock 防並行,冪等 — 重跑只會 skip 已封存的日期。

06:20 — 上傳封存檔給 broker(SFTP)

tapioctl ship --proto sftparchived/*.tar.zst 透過 lftp 上傳到 broker 指定的 SFTP,成功後本地檔自動 unlink(lftp put -E:成功就刪、失敗就留)。失敗的檔保留在 archived/ 下次 ship 自動重試。 排在 archive 之後 5 分鐘給 archive 完成留 buffer;ship 同樣以 flock 防並行,且仍在 06:30 quote 重啟前完成 — 即使網路慢也不會吃進交易時段。 第一次部署或換 broker 後,記得先手動 --dry-run 確認 remote 路徑(見 periodic-routines.md)。

06:30–06:31 — 維護窗口內重啟

quote-clean 清除前一日殘留的行情快取, 必須在 stop quote-receiver 後、start quote-receiver 前執行,否則舊行情殘留會混入當日資料。 行情服務盡早重啟,是為了在開盤前收齊收盤後廣播的行情資訊,縮短離線窗口。

taifex-fetcher start 同樣在 rollover 後即可啟動,會自動從 TAIFEX SFTP 抓當日檔案。 與 quote 無依賴關係,可並行執行。

09:07 — 盤前 / 開盤批次

需確認 broker 已完成拋檔再執行 preopen;拋檔時間因 broker 而異,請依實際情況調整。 preopen 完成後,start live-syncstart core 沒有彼此的啟動依賴,可各自獨立啟動。

09:15 — API Key 自動補發 / 換發

tapioctl keys rotate-expiring 為使用者自動處理 API Key,包含兩種情況:

  1. 使用者目前沒有任何 API Key:自動產生一把並寄信給該使用者。
  2. 使用者目前最新一把 Key 即將到期(預設到期日前三個月內):自動產生新 Key 並寄信。

須在 start core 完成、Tapio 服務已就緒後執行。

06:01–07:00 — mail 維護窗口

mail daemon 自身不依賴 system_date,跨日重啟在功能上沒有必要,但 為了避開維護窗口期間的 SMTP 噪音(換日中產生的告警若送出去會混淆 oncall), 排程在 06:01 一併 stop mail,07:00 再 start mail@reboot 確保開機後立即啟動;*/5 每五分鐘補跑提供崩潰自動恢復, 但 6 點整點跳過避免和維護窗口打架(用 */5 0-5,7-23 * * *)。

歷史備註:rollover 不再被 mail 擋住

早期版本 tapioctl rollover 會檢查所有 daemon 是否仍在跑(包括 mail), 若有就 refuse — 因此 */5 的 mail 容易在 rollover 時段把 rollover 搞掛。 現行版本 rollover 已豁免 mail,上面的 stop/start 排程屬於「乾淨維護窗口」 的維運慣例,不是必要安全措施。

安裝範本

以 operator user 身份編輯:

sudo -u <operator> crontab -e

格式不需要 username 欄位:

# Tapio 操作排程
# 全部以 operator user 執行,cron 環境變數有限,全部用絕對路徑

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

# === 前一日收尾(每天執行,包含週末;夜盤禮拜五跑到禮拜六凌晨)===
0  6  *  *  *  /opt/Tapio/bin/tapioctl stop core
0  6  *  *  *  /opt/Tapio/bin/tapioctl stop live-sync
0  6  *  *  *  /opt/Tapio/bin/tapioctl stop taifex-fetcher
1  6  *  *  *  /opt/Tapio/bin/tapioctl stop quote-receiver

# === 稽核紀錄匯出(選填;必須在 rollover 前執行)===
2  6  *  *  *  /opt/Tapio/bin/tapio-order-risk-log-export -date auto -config /opt/Tapio/etc/Tapio.toml
2  6  *  *  *  /opt/Tapio/bin/tapio-login-log-export -date auto -config /opt/Tapio/etc/Tapio.toml

# === 切交易日(必須早於任何 daemon start)===
10 6  *  *  *  /opt/Tapio/bin/tapioctl rollover

# === 維護窗口內重啟(rollover 完成後即可)===
30 6  *  *  *  /opt/Tapio/bin/tapioctl quote-clean
30 6  *  *  *  /opt/Tapio/bin/tapioctl start taifex-fetcher
31 6  *  *  *  /opt/Tapio/bin/tapioctl start quote-receiver

# === 封存舊日資料(rollover 完成後,維護窗口內執行)===
15 6  *  *  *  /opt/Tapio/bin/tapioctl archive --older-than 7d

# === 上傳 archived/ 給 broker SFTP(archive 之後;成功後本地檔自動 unlink)===
20 6  *  *  *  /opt/Tapio/bin/tapioctl ship --proto sftp

# === 寄信服務:開機啟動 + 每五分鐘確保存活(6 點維護窗口跳過)===
@reboot              /opt/Tapio/bin/tapioctl start mail
1  6  *  *  *        /opt/Tapio/bin/tapioctl stop mail
0  7  *  *  *        /opt/Tapio/bin/tapioctl start mail
*/5 0-5,7-23 *  *  * /opt/Tapio/bin/tapioctl start mail

# === 盤前 / 開盤(依 broker 拋檔時間調整)===
7  9  *  *  *  /opt/Tapio/bin/tapioctl preopen
8  9  *  *  *  /opt/Tapio/bin/tapioctl start live-sync
9  9  *  *  *  /opt/Tapio/bin/tapioctl start core

# === API Key 自動補發 / 換發(無 Key 直接發;既有 Key 到期前三個月換發)===
15 9  *  *  *  /opt/Tapio/bin/tapioctl keys rotate-expiring

以 root 編輯系統 crontab:

sudo vim /etc/crontab

/etc/crontab 格式比 user crontab 多一個 username 欄位(第 6 欄):

# Tapio 操作排程
# /etc/crontab 格式:min hour dom month dow user command

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

# === 前一日收尾(每天執行,包含週末;夜盤禮拜五跑到禮拜六凌晨)===
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop core
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop live-sync
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop taifex-fetcher
1  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop quote-receiver

# === 稽核紀錄匯出(選填;必須在 rollover 前執行)===
2  6  *  *  *  <operator>  /opt/Tapio/bin/tapio-order-risk-log-export -date auto -config /opt/Tapio/etc/Tapio.toml
2  6  *  *  *  <operator>  /opt/Tapio/bin/tapio-login-log-export -date auto -config /opt/Tapio/etc/Tapio.toml

# === 切交易日(必須早於任何 daemon start)===
10 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl rollover

# === 維護窗口內重啟(rollover 完成後即可)===
30 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl quote-clean
30 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start taifex-fetcher
31 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start quote-receiver

# === 封存舊日資料(rollover 完成後,維護窗口內執行)===
15 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl archive --older-than 7d

# === 上傳 archived/ 給 broker SFTP(archive 之後;成功後本地檔自動 unlink)===
20 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl ship --proto sftp

# === 寄信服務:開機啟動 + 每五分鐘確保存活(6 點維護窗口跳過)===
@reboot              <operator>  /opt/Tapio/bin/tapioctl start mail
1  6  *  *  *        <operator>  /opt/Tapio/bin/tapioctl stop mail
0  7  *  *  *        <operator>  /opt/Tapio/bin/tapioctl start mail
*/5 0-5,7-23 *  *  * <operator>  /opt/Tapio/bin/tapioctl start mail

# === 盤前 / 開盤(依 broker 拋檔時間調整)===
7  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl preopen
8  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start live-sync
9  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start core

# === API Key 自動補發 / 換發(無 Key 直接發;既有 Key 到期前三個月換發)===
15 9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl keys rotate-expiring

格式容易搞混

忘記加 username 欄位是常見錯誤 — crond 會把 username 當成指令,job 靜默失敗。 貼入後用 sudo journalctl -u crond -n 20 確認有正常執行。

建立 Tapio 專屬的 drop-in 檔:

sudo vim /etc/cron.d/tapio

格式與 /etc/crontab 相同(需要 username 欄位),crond 自動載入,不需要重啟服務:

# Tapio 操作排程
# /etc/cron.d/ 格式:min hour dom month dow user command

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

# === 前一日收尾(每天執行,包含週末;夜盤禮拜五跑到禮拜六凌晨)===
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop core
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop live-sync
0  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop taifex-fetcher
1  6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl stop quote-receiver

# === 稽核紀錄匯出(選填;必須在 rollover 前執行)===
2  6  *  *  *  <operator>  /opt/Tapio/bin/tapio-order-risk-log-export -date auto -config /opt/Tapio/etc/Tapio.toml
2  6  *  *  *  <operator>  /opt/Tapio/bin/tapio-login-log-export -date auto -config /opt/Tapio/etc/Tapio.toml

# === 切交易日(必須早於任何 daemon start)===
10 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl rollover

# === 維護窗口內重啟(rollover 完成後即可)===
30 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl quote-clean
30 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start taifex-fetcher
31 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start quote-receiver

# === 封存舊日資料(rollover 完成後,維護窗口內執行)===
15 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl archive --older-than 7d

# === 上傳 archived/ 給 broker SFTP(archive 之後;成功後本地檔自動 unlink)===
20 6  *  *  *  <operator>  /opt/Tapio/bin/tapioctl ship --proto sftp

# === 寄信服務:開機啟動 + 每五分鐘確保存活(6 點維護窗口跳過)===
@reboot              <operator>  /opt/Tapio/bin/tapioctl start mail
1  6  *  *  *        <operator>  /opt/Tapio/bin/tapioctl stop mail
0  7  *  *  *        <operator>  /opt/Tapio/bin/tapioctl start mail
*/5 0-5,7-23 *  *  * <operator>  /opt/Tapio/bin/tapioctl start mail

# === 盤前 / 開盤(依 broker 拋檔時間調整)===
7  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl preopen
8  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start live-sync
9  9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl start core

# === API Key 自動補發 / 換發(無 Key 直接發;既有 Key 到期前三個月換發)===
15 9  *  *  *  <operator>  /opt/Tapio/bin/tapioctl keys rotate-expiring

格式容易搞混

格式與 /etc/crontab 相同,忘記加 username 欄位同樣會靜默失敗。

cron 環境變數注意事項

cron 預設 PATH 只有 /usr/bin:/bintapioctl 本身用絕對路徑呼叫 binary, 但它啟動的子服務若有自己的 exec 呼叫,同樣受 cron PATH 限制。 範本保留 PATH=/usr/local/bin:/usr/bin:/bin 作為保險。

驗證 cron 是否成功

# 看 cron 服務是否在跑
sudo systemctl status crond

# 看最近幾次執行紀錄
sudo journalctl -u crond -n 50

# 確認 user crontab(user crontab 做法)
sudo crontab -u <operator> -l

除錯:手動模擬 cron 環境

cron 跟登入 shell 環境不同,常見 bug 是「shell 跑 ok、cron 跑爆」。模擬方式:

sudo -u <operator> bash -c 'env -i PATH=/usr/bin:/bin /opt/Tapio/bin/tapioctl status'

這會剝光環境變數只留 PATH,模擬 cron 的最小環境。如果這樣跑會錯,cron 也會錯。

排錯

  • cron 排程到了但 tapioctl 沒跑sudo journalctl -u crond 找對應時間。(CMD) 行表示嘗試執行;旁邊有錯誤訊息 → 可能是 user 不存在(useradd <operator> 沒跑過?) → 可能是 absolute path 不對 → /etc/crontab/etc/cron.d/ 做法:確認每行都有 username 欄位

  • tapioctl 跑了但 process 沒起來 → cron 不會自動印 stderr,看 tapioctl 寫到 log/$today/stdout/tapio-core.log 的內容 → 同樣可手動 sudo -u <operator> /opt/Tapio/bin/tapioctl start core 看 log 是否一致

  • preopen 跑爆 — *.TXT 缺檔 → broker 還沒投檔。若常延誤可把 cron 推後幾分鐘 → 或把缺檔當 alert 處理(寫 wrapper script 包 tapioctl + alert)