拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Codex CLI 定时任务实战:从 crontab 到自动化工作流

把 Codex CLI 放进定时任务听起来像是一个极客玩具但实际用起来之后它已经成了我每天工作流里不可缺的自动化角色。我现在每天会跑 3 个 Codex 定时任务早上生成前一天的代码变更摘要周日晚上生成周报初稿深夜把零散阅读记录整理成结构化知识卡片。这三个任务都跑在 crontab 和 launchd 上不依赖打开终端手动敲 prompt。这篇文章会把这 3 个 Codex 定时任务的完整设计思路、Shell 脚本、cron 表达式、验证方式写出来也会把调试过程中真正卡住我的几个问题整理成排错清单。你可以直接复制脚本改成自己的仓库和输出目录也可以在理解原理之后把它迁移到 Java 项目、xxl-job 或 Quartz 这类调度框架里。1. 为什么要把 Codex CLI 改成定时任务1.1 Codex CLI 不只有交互式对话一种用法很多人在终端运行codex时进入的是交互式对话界面输入一句需求Codex 给出修改建议或直接改文件。这种模式适合“我当时就在电脑前能立刻检查结果”的场景。但定时任务的场景完全不同凌晨 1 点没有人在终端前任务需要在固定时间自动启动跑完之后把结果写到某个目录。这要求 Codex CLI 能支持非交互式执行。Codex CLI 提供的exec子命令就是为这种场景设计的。它可以接收一段 prompt执行完成后退出而不是进入对话循环。常见的使用方式是把 prompt 通过管道传给codex exec或者直接把 prompt 放在参数里。codex exec 用一句话解释什么是 HTTP 状态码 429这条命令会输出 Codex 对 prompt 的回复然后退出。定时任务要做的就是把要处理的数据整理成 prompt在固定时间触发codex exec再把标准输出重定向到 Markdown 文件。1.2 定时执行解决的是“人机协作频率”问题手动使用 Codex 时工作模式通常是“我现在有一个想法立刻打开终端问一次”。这种模式下Codex 的价值取决于你什么时候想起来用它。定时任务改变了这个逻辑。它把“想起用 Codex”从人脑判断变成了系统行为。每天固定时间点脚本自动收集 git 提交、文件变更、阅读记录把这些数据整理成 prompt再调用 Codex 生成结构化结果。人只需要在早上或周末花几分钟确认结果而不是从零开始回忆、梳理、写作。从工程角度拆解Codex 定时任务本质上是一条流水线数据源git 仓库、文件系统、Markdown 文件。收集脚本用git log、find、cat等命令把原始数据提取出来。prompt 构造把原始数据包进一段明确的指令文本。执行体codex exec调用模型。输出层Markdown 文件、日志文件、错误捕获。后文三个任务都是这套流水线的不同实例。任务之间的差别不是工具不同而是“数据源不同、prompt 意图不同、输出规范不同”。2. 环境准备先让 Codex 在非交互模式下跑通在写任何定时任务之前必须先确认三件事Codex CLI 已安装、已登录、能在非交互模式下执行并返回结果。这三件事有一个没确认后面所有定时任务都会在凌晨静默失败。2.1 安装、登录与版本确认不同系统安装 Codex CLI 的方式略有差异。常见的全局安装命令是 npm 方式npm install -g openai/codex具体包名和版本要以你当前使用的 Codex 文档为准因为 CLI 版本更新很快包名或参数可能调整。安装完成后先确认可执行文件存在codex --version如果命令不存在说明全局 npm bin 目录没有加入 PATH或者安装阶段出了问题。检查方式which codex正常输出应该是一个绝对路径例如/usr/local/bin/codex或$HOME/.local/bin/codex。如果which没有输出先检查 npm 全局目录npm config get prefix ls -la $(npm config get prefix)/bin登录步骤也要提前完成。Codex CLI 使用前需要完成身份认证认证方式以官方文档为准。登录成功后Codex CLI 会保存凭据后续非交互命令不需要重复登录。2.2 先跑一条最小 prompt验证全链路安装完成不是终点必须用exec子命令验证一次非交互调用因为定时任务和交互模式的调用路径不同。执行codex exec 只回答链路通如果能正常输出结果说明 CLI 本身没问题。如果提示exec不是有效子命令说明当前版本的主命令结构不同需要执行codex --help查看当前支持的命令。这里要注意一个关键点不要跳过这一步直接配置 cron。定时任务最大的问题是“没有现场可调试”一旦失败你只能看日志。提前在终端跑通等于排除了命令行本身的问题后续故障只会出现在定时环境、PATH、模型名或数据源上。2.3 记录 codex 二进制绝对路径定时任务运行时环境变量来自 crontab 或 launchd不是你的交互 shell。它会使用最小 PATH可能不包含 npm 的全局 bin 目录。为了避免“终端能跑、cron 不能跑”的经典问题在准备阶段就记录下codex的绝对路径。command -v codex得到的路径例如/usr/local/bin/codex后面写脚本时可以直接引用或写进脚本开头的 PATH 里。这是一个很小的准备动作但能省掉大量排查时间。3. 任务一每天早上生成前一天的代码变更摘要3.1 思路与数据源这个任务要解决的是“每天早上打开仓库想快速知道昨天改了什么”。手动做这件事需要执行git log、git diff再逐条看提交信息遇到不规范的提交信息还要翻代码。Codex 定时任务把这一步完全自动化。数据源只有一个目标仓库的 git 历史。脚本固定进入仓库目录用git log拉取最近 24 小时的提交记录再用git diff --stat拉取文件变更统计。两部分文本拼接成 prompt交给codex exec生成中文摘要。目录结构如下~/.codex-jobs/ ├── daily_summary.sh ├── weekly_report.sh ├── knowledge_card.sh └── logs/所有脚本放在~/.codex-jobs下日志统一输出到logs/方便排查。3.2 脚本实现#!/usr/bin/env bash set -euo pipefail REPO_DIR${1:?用法: $0 /path/to/repo} OUTPUT_DIR${CODEX_OUTPUT_DIR:-$HOME/Documents/codex-daily} TODAY$(date %F) LOG_DIR$HOME/.codex-jobs/logs LOG_FILE$LOG_DIR/daily-$TODAY.log mkdir -p $OUTPUT_DIR $LOG_DIR if [ ! -d $REPO_DIR/.git ]; then echo [$(date %Y-%m-%d %H:%M:%S)] REPO_DIR 不是 git 仓库: $REPO_DIR $LOG_FILE exit 1 fi cd $REPO_DIR COMMIT_LOG$(git log --since24 hours ago --prettyformat:%h %s (%an) --dateshort 2$LOG_FILE) DIFF_STAT$(git diff --stat HEAD~1 2$LOG_FILE || true) if [ -z ${COMMIT_LOG:-} ]; then echo [$(date %Y-%m-%d %H:%M:%S)] 最近 24 小时没有提交 $LOG_FILE echo 最近 24 小时没有新的代码提交。 $OUTPUT_DIR/daily-$TODAY.md exit 0 fi PROMPT你是一个技术负责人。请根据下面的 git 提交记录和变更统计生成一份面向开发者的每日代码变更摘要。 要求 1. 按模块或功能点分类不要逐条翻译 commit message。 2. 先写总变更趋势再写关键变更点。 3. 如果提交涉及 bug 修复、接口变化、数据库变更单独标注。 4. 输出 Markdown 格式中文回答。 以下是原始 git 数据 ----- commit log ----- $COMMIT_LOG ----- diff stat ----- $DIFF_STAT { echo $PROMPT } | codex exec $OUTPUT_DIR/daily-$TODAY.md 2$LOG_FILE echo [$(date %Y-%m-%d %H:%M:%S)] 生成完成: $OUTPUT_DIR/daily-$TODAY.md $LOG_FILE脚本里几个关键点set -euo pipefail一旦某条命令失败脚本立即退出避免输出一个半截文件。git diff --stat HEAD~1用上一次提交作为对比点比依赖 reflog 的HEAD{1}更稳定尤其适合 cron 环境。空提交判断如果 24 小时没有提交直接生成提示文件不调用 Codex。这样可以避免把手写提示词错误当作“生成结果”。重定向策略正常输出写入 Markdown 文件错误输出追加到日志文件。3.3 cron 配置与验证假设每天早上 8 点 30 分执行编辑 crontabcrontab -e加入一行30 8 * * * /bin/bash /Users/yourname/.codex-jobs/daily_summary.sh /path/to/your/repo /Users/yourname/.codex-jobs/logs/cron-job1.log 21注意三个细节使用/bin/bash显式指定解释器避免调度环境默认 shell 不同。所有路径都用绝对路径。脚本自身的日志追加到cron-job1.log方便和 Codex 的运行日志分开排查。验证方式有两种。第一种是手动执行一次脚本本体bash /Users/yourname/.codex-jobs/daily_summary.sh /path/to/your/repo执行后打开$HOME/Documents/codex-daily/daily-$(date %F).md查看结果。第二种是等待 cron 到点执行后查看日志文件cat /Users/yourname/.codex-jobs/logs/daily-$(date %F).log4. 任务二每周日生成一份周报初稿4.1 思路复用每日摘要不重复收集 git 数据如果周报也调用一次 git会得到一周的提交记录但输出可能和每日摘要大量重复而且信息密度低。更合理的做法是让周报消费“每日摘要文件”而不是再次分析 git。这时的数据源不再是一个 git 仓库而是~/Documents/codex-daily/目录下最近 7 天的 Markdown 文件。脚本收集这些文件内容让 Codex 汇总成一封周报初稿。这样每日摘要和周报形成两级结构每天做原始数据清洗每周做信息再聚合。4.2 脚本实现#!/usr/bin/env bash set -euo pipefail DAILY_DIR$HOME/Documents/codex-daily OUTPUT_DIR$HOME/Documents/codex-weekly LOG_DIR$HOME/.codex-jobs/logs TODAY$(date %F) LOG_FILE$LOG_DIR/weekly-$TODAY.log mkdir -p $OUTPUT_DIR $LOG_DIR WEEK_FILES$(find $DAILY_DIR -maxdepth 1 -name daily-*.md -mtime -7 | sort) if [ -z $WEEK_FILES ]; then echo [$(date %Y-%m-%d %H:%M:%S)] 最近 7 天没有每日摘要文件 $LOG_FILE echo 最近 7 天没有可用的每日摘要。 $OUTPUT_DIR/weekly-$TODAY.md exit 0 fi COMBINED_CONTENT for FILE in $WEEK_FILES; do COMBINED_CONTENT$COMBINED_CONTENT $(basename $FILE) $(cat $FILE) done PROMPT你是一名技术组长。请基于下面的每日代码变更摘要生成一份周报初稿。 要求 1. 合并同类项不要保留每日摘要的逐条内容。 2. 分成四个部分本周核心进展、关键技术决策、风险与阻塞、下周计划。 3. 保留具体信息如模块名、功能点、技术栈不要写成泛泛的套话。 4. 输出 Markdown 格式中文回答。 以下是每日摘要内容 $COMBINED_CONTENT { echo $PROMPT } | codex exec $OUTPUT_DIR/weekly-$TODAY.md 2$LOG_FILE echo [$(date %Y-%m-%d %H:%M:%S)] 周报生成完成: $OUTPUT_DIR/weekly-$TODAY.md $LOG_FILE这里使用find ... -mtime -7筛选最近 7 天修改的每日摘要文件按文件名排序后逐个拼接。排序很重要它保证 Codex 看到的每日摘要是按时间顺序排列的生成的周报才有时间线感。4.3 避免重复统计-mtime -7是按文件修改时间筛选而不是内容里的日期。如果某一天没有生成摘要文件周报会少一天如果补跑了一个旧文件它的修改时间会变成现在也会被统计进去。实际使用中可以根据自己的容错需求调整。更精确的筛选方式是直接用文件名里的日期例如把daily-2025-06-01.md转换成日期再与当前日期比较。这样更稳但脚本会稍微复杂。下面这段是纯文件名日期过滤的思路可以按需使用DAILY_DIR$HOME/Documents/codex-daily TODAY$(date %F) WEEK_FILES for FILE in $DAILY_DIR/daily-*.md; do [ -e $FILE ] || continue FILE_DATE${FILE##*daily-} FILE_DATE${FILE_DATE%%.md} # 这里需要把 FILE_DATE 与 7 天前日期比较date 命令在 mac/linux 上写法不同 WEEK_FILES$WEEK_FILES $FILE done注意macOS 的date -v-7d和 Linux 的date -d 7 days ago语法不同跨平台脚本需要单独处理。如果只在 Linux 服务器上跑直接使用find -mtime最省事。5. 任务三深夜把零散阅读记录整理成知识卡片5.1 思路用 inbox 文件收集碎片这个任务解决的是“碎片信息堆积”问题。平时看到一段代码思路、一个架构方案、一句有启发的话往往随手记在一个临时文件里但之后很少再整理。专门整理又太浪费时间。我采用一个统一的inbox.md作为入口。白天往文件里追加一行记录深夜由 Codex 定时任务把新增内容转成结构化知识卡片追加到knowledge-base.md然后清空inbox.md。文件位置~/Documents/codex-inbox/inbox.md ~/Documents/codex-inbox/knowledge-base.mdinbox 每行是一个待整理条目。允许一行内有自己的描述Codex 会负责补全背景和结构化。5.2 脚本实现#!/usr/bin/env bash set -euo pipefail INBOX$HOME/Documents/codex-inbox/inbox.md KNOWLEDGE_BASE$HOME/Documents/codex-inbox/knowledge-base.md LOG_DIR$HOME/.codex-jobs/logs TODAY$(date %F) LOG_FILE$LOG_DIR/knowledge-$TODAY.log mkdir -p $(dirname $INBOX) $LOG_DIR touch $INBOX $KNOWLEDGE_BASE if [ ! -s $INBOX ]; then echo [$(date %Y-%m-%d %H:%M:%S)] inbox 为空跳过整理 $LOG_FILE exit 0 fi CONTENT$(cat $INBOX) PROMPT你是一名技术编辑。下面是一个技术碎片清单每行一个条目。 请把它们整理成知识卡片追加到 Markdown 文档中。 要求 1. 每个条目输出一个 H3 卡片。 2. 卡片包含核心观点一句话、适用场景、原理或依据、可操作的下一步。 3. 如果条目本身信息不足不要编造细节可以补充“待验证”标记。 4. 输出 Markdown 格式字体清晰结构一致。 raw input: $CONTENT { echo $PROMPT } | codex exec $HOME/Documents/codex-inbox/_new_cards.md 2$LOG_FILE if [ -s $HOME/Documents/codex-inbox/_new_cards.md ]; then { echo echo ## 整理日期$TODAY cat $HOME/Documents/codex-inbox/_new_cards.md } $KNOWLEDGE_BASE # 清空 inbox $INBOX echo [$(date %Y-%m-%d %H:%M:%S)] 知识卡片已追加inbox 已清空 $LOG_FILE else echo [$(date %Y-%m-%d %H:%M:%S)] 生成结果为空未清空 inbox $LOG_FILE fi这个脚本的关键是“只有生成结果非空才清空 inbox”。如果 Codex 调用失败或输出为空inbox 仍然保留避免数据丢失。5.3 验证知识卡片格式脚本执行后可以检查知识库文件末尾tail -n 40 ~/Documents/codex-inbox/knowledge-base.md正常情况会看到类似这样的结构## 整理日期2025-06-01 ### 如何避免日志记录里面的敏感信息泄漏 - 核心观点日志脱敏不能依赖开发人员手动判断。 - 适用场景微服务请求日志、错误堆栈、SQL 慢查询日志。 - 原理或依据常见处理方式是提前配置脱敏字段在日志输出层统一处理。 - 下一步整理公司内部日志框架的脱敏插件选型。如果格式不统一可以调整 prompt 里的输出规范比如新增“每个 H3 卡片必须包含四个字段”这类硬性要求。Codex 对明确的格式约束响应更好。6. 挂到后台之后真正麻烦的是这几个问题定时任务从“手动能跑”到“挂上 cron 也稳定”中间会碰到几个高频问题。这里按排查路径从输入到输出排序。6.1 unable to locate the codex cli binary出现的典型现象是终端直接运行 codex 没问题但 Codex 桌面端、IDE 插件或某个自动化脚本启动时报错unable to locate the codex cli binary. set codex cli path or ensure the executable is in PATH这句话的意思是调用方可能是 Codex 桌面应用、编辑器插件也可能是 cron 脚本找不到codex可执行文件。原因通常是调度环境或插件进程的 PATH 与终端 shell 不一致。排查步骤在终端执行command -v codex拿到绝对路径。执行echo $PATH确认该路径位于 PATH 中。检查 cron 脚本或桌面端的Codex CLI Path设置项直接填入绝对路径。在定时脚本内部显式导入 PATH而不是依赖外部环境export PATH$HOME/.local/bin:/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:$PATH这行代码要放在脚本最前面再执行codex。6.2 model is not supported 这类模型不匹配问题定时任务里如果显式指定了模型或者 Codex CLI 配置的默认模型和当前使用的模式不匹配可能出现类似the gpt-5.6-sol model is not supported when using codex with a...这是一个提示性的错误你请求的模型名在当前 Codex 模式下不可用。排查方向不是去搜索引擎复制这条错误而是先确认当前环境支持的模型列表。codex models如果当前版本没有models子命令就查看配置文件cat ~/.codex/config.toml配置里通常有model或model_provider字段。把它改成当前环境支持的模型名或者在调用codex exec时通过--model参数指定。这个坑最常见的触发点是你把“网上看到的模型名”直接写进脚本但你的 Codex CLI 版本或账号并不支持该模型。落地前先执行codex models。6.3 脚本在终端正常在 crontab 里不执行这是定时任务最经典的问题。脚本手动执行正常cron 到点时日志文件没有新内容或运行时报command not found: codex。原因在于 cron 环境是极简环境。它不加载你的.bash_profile、.zshrcPATH 通常只有/usr/bin:/binnpm 全局 bin 目录不在里面。另一个常见问题是脚本里使用了$HOME之外的相对路径但 cron 执行时工作目录不是仓库目录。应对方式脚本开头显式定义 PATH。脚本内部所有路径使用绝对路径。cron 命令里使用/bin/bash /full/path/to/script.sh。脚本对关键参数做校验例如if [ ! -d $REPO_DIR/.git ]; then echo $(date): REPO_DIR 不是 git 仓库 $LOG_FILE exit 1 fi6.4 任务重叠和日志缺失cron 只负责在固定时间启动命令不负责“上一次还没结束就不要启动下一次”。如果 Codex 生成结果比较慢而 cron 周期又短就可能出现两个 codex 进程同时运行。轻则浪费配额重则两个进程写同一个输出文件内容互相覆盖。处理方式是在脚本入口加flock锁。以任务一为例exec 9 /tmp/codex-daily-summary.lock flock -n 9 || { echo $(date): 上一次任务未结束跳过本次执行 $LOG_FILE; exit 1; }这样同一时间只会有一个任务实例运行。日志缺失的解决方式更简单cron 命令最后统一追加 /path/to/log 21并且脚本内部每次关键节点都写一行带头部时间戳的日志。下面是一个按现象到处理建议的排查表现象常见原因检查方式处理建议crontab 完全没有输出脚本路径错误或未执行在 cron 命令里先执行echo start写日志确认绝对路径查看/var/mail或重定向日志unable to locate the codex cli binaryPATH 未包含 codexcommand -v codex在脚本顶部注入 PATH或填写绝对路径model is not supported模型名不匹配codex models检查 config.toml使用当前支持的模型名任务重复执行上一次未结束ps -ef | grep codex使用 flock 锁输出文件为空prompt 输入为空或 codex 失败查看日志文件中的错误输出增加输入判空重定向 stderr 到日志脚本在终端正常 cron 报错cron 环境变量不完整手动执行env -i /bin/bash script.sh在脚本内定义 PATH、HOME、LANG7. 个人电脑用 cron什么时候才需要 Quartz、xxl-job7.1 三种调度方案的适用范围如果定时任务只跑在自己的电脑上crontab 是最直接的选择。它不需要额外依赖配置简单适合“单机、固定周期、少量任务”的场景。缺点也很明显没有失败重试、没有任务追踪界面、没有分布式能力跨机器管理要自己另想办法。进入 Java 项目后常见的选择有两个Quartz 和 xxl-job。Quartz 是 Java 进程内调度器适合嵌在单个服务内部执行定时任务。xxl-job 是调度中心加执行器的架构调度逻辑和执行逻辑分离适合多服务、集群场景自带日志和失败重试。维度crontabQuartzxxl-job运行形态操作系统进程Java 进程内调度中心 执行器集群支持无需要自己实现分片和竞争锁内置多种调度策略失败重试无可通过 JobListener 实现调度中心内置日志追踪依赖文件重定向应用日志调度中心自带执行日志依赖复杂度零额外依赖需引入 Quartz 依赖需部署调度中心适合场景个人脚本、单机自动化单服务内部定时任务多服务、分布式、需要可视化调度7.2 在 Java/Spring 项目里调用 Codex 自动化任务时的选型建议如果你需要把“Codex 生成代码摘要”这类能力接到 Spring Boot 项目里不要直接在业务请求路径里调用 Codex CLI。更稳妥的做法是用定时调度框架Scheduled、Quartz、xxl-job 任一触发任务。任务把请求发送到消息队列。队列消费者异步执行 Codex 自动化任务。结果写入数据库或对象存储。这样即使 Codex 调用变慢也不会阻塞业务请求。用Scheduled时还要注意默认就是单线程执行多个任务相互影响时要用Async或配置线程池。xxl-job 的典型优势是执行日志和调度记录不需要自己开发失败重试也比较完整适合团队协作场景。选择标准可以简单记成一句话任务只有一个、跑在单机、不需要运维界面用 crontab 或Scheduled任务分散在多个服务、需要中心化调度和失败重试用 xxl-job任务嵌在 Java 进程内部、需要定制触发规则用 Quartz。8. 最佳实践让 Codex 定时任务长期稳定运行8.1 脚本里必须做好的 6 件事一个稳定的 Codex 定时任务不只是“调一下 codex exec”而是要把脚本当成小型流水线来对待。下面 6 件事我在每个脚本里都强制执行使用set -euo pipefail让未定义变量和管道错误直接暴露。所有输出目录先mkdir -p避免首次运行崩溃。所有日志写入统一目录文件名带日期便于回溯。对输入做空值判断输入为空时不调用 Codex直接生成提示文件。使用绝对路径或脚本开头注入 PATH不依赖 cron 环境变量。使用flock防止任务重叠保证输出文件不会被并发覆盖。8.2 把任务升级成 CI 或框架任务时可以怎么扩展并不一定要依赖本地电脑的 cron。如果仓库托管在支持 CI 的平台上可以用仓库自带的 schedule 功能每天触发一个 workflow在 CI 容器里安装 Codex CLI然后执行同样的脚本。优势是即使本地电脑关机任务也能执行而且执行日志由 CI 平台统一管理。如果走这条路脚本里的输出目录要改成 CI 工作目录或者直接输出到构建产物目录。注意 CI 环境也需要完成 Codex 登录或配置访问凭据这一步要和你的凭据管理方式对齐。如果团队已经用 xxl-job 这类框架也可以把“收集 git 数据 调用 Codex 写 Markdown”封装成一个 Java 执行器把调度交给框架把模型调用放在执行器内部。核心算法和本文章的 Shell 脚本思路一致只是把git log、find等命令换成 Java 代码或 JGit 调用。这三个任务真正有价值的地方不是它们用了多复杂的 AI 接口而是它们把 Codex 从“每次都要手动对话”变成了“按节奏自动产生交付物”。如果你现在只手动使用 Codex建议先选一个每天都会重复的动作做成定时任务跑一周。根据每天的日志和输出结果调整 prompt稳定之后再考虑迁移到后端调度框架或 CI 里。从最小闭环开始比一开始就搭建复杂调度体系更实际。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门