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 core、stop live-sync、stop taifex-fetcher,接著 stop quote-receiver。
所有 daemon 停止後,系統進入維護窗口。
06:02 — 匯出稽核紀錄(選填)
tapio-order-risk-log-export 與 tapio-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 sftp 把 archived/*.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-sync 與 start core 沒有彼此的啟動依賴,可各自獨立啟動。
09:15 — API Key 自動補發 / 換發
tapioctl keys rotate-expiring 為使用者自動處理 API Key,包含兩種情況:
- 使用者目前沒有任何 API Key:自動產生一把並寄信給該使用者。
- 使用者目前最新一把 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 身份編輯:
格式不需要 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:
/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 檔:
格式與 /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:/bin。tapioctl 本身用絕對路徑呼叫 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 跑爆」。模擬方式:
這會剝光環境變數只留 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)