KerWork 跑完一轮桌面操作、结果要覆盖原文件时,建议在回写前留一份副本,但副本不应该和原文件一直混在同一个目录里接受扫描。判断要看三件事:回写是不是不可逆(覆盖后原内容是否还能从别处拿回)、这批文件会不会被下一轮任务再次扫到、出问题后你靠什么证据确认哪一份是“对的”。其中任意一条不满足,都应该先备份,并把备份和比对写进流程里,而不是凭记忆临时拷一份。
留副本这一步不能省,但位置和时长要分开处理:单次回写可以先用同目录后缀副本,最低成本拿到一个可回退版本;批量跑批则应把副本落到独立备份目录,避免被下一轮任务当成输入再处理一遍。留多久按批次算,不清空只归档,清理前先用不带删除的 find 或 -WhatIf 列清单核对。回写结果不要只看文件大小,用 sha256 或 diff 与副本比对,并把比对结果落成一条记录,不一致时先停后续批次再排查。
写回前给目标文件做一份同目录副本
同目录副本的意义是“出问题时原路径上立刻有一个可改回来的版本”,不需要额外挂载点和权限。用 cp 时加保留时间戳的参数,副本的可追溯性才完整:
cp -p `--preserve`=timestamps 合同汇总.xlsx "合同汇总.xlsx.bak.$(date +%Y%m%d-%H%M%S)"
复制完用 ls -l `--time-style`=full-iso 看一下副本的修改时间是否与原文件一致,一致说明时间戳被保留了;如果 KerWork 的回写逻辑依赖文件时间判断新旧,副本时间与原文件不一致可能引出额外问题。
命名规则建议“保留原名 + 固定形状后缀 + 时间戳”,不要改原名。程序或任务配置通常按原文件名写入,改了名等于让回写找不到目标;后缀统一成 .bak.YYYYmmdd-HHMMSS 这种可被通配符稳定匹配的形式,后面写排除规则和清理规则都靠这个形状。
一轮跑批涉及多个文件时,用目录遍历一次性复制,避免手写路径漏文件:
ts=$(date +%Y%m%d-%H%M%S)
find /data/inbox -maxdepth 1 -type f -name '*.xlsx' -print0 \
| xargs -0 -I{} cp -p `--preserve`=timestamps '{}' '{}.bak.'"$ts"
ls /data/inbox/*.bak."$ts" | wc -l
复制后拿副本数量与源文件数量对一下,数量不符说明中途有文件被跳过,先补复制再回写。
把副本放到独立目录而不是混在原目录
同目录副本只适合单文件、单次操作。批量任务里副本留在原目录,下一轮扫描很容易把 *.bak.* 当成待处理文件再跑一遍,结果是副本被再次改写,回退点失效。更稳的做法是每次跑批建一个批次目录:
ts=$(date +%Y%m%d-%H%M%S)
bak="/var/backups/kerwork/invoice-sync/$ts"
mkdir -p "$bak"
cp -p /data/inbox/*.xlsx "$bak"/
ls "$bak" | wc -l
备份根目录建议放在与业务目录不同的一层,比如 /var/backups/kerwork/<任务名>/<批次号>/,Windows 侧同理用独立的盘符目录。不同任务分不同子目录,不要把多个任务混进同一个批次目录,否则清理时无法按任务判断。
路径写法上,任务配置里的“输入目录”和“备份目录”必须是两个字段,回写校验时从备份目录读副本、从业务目录读回写结果,源路径只作为记录字段保留。同时要在任务的文件筛选规则里显式排除备份相关内容,常见做法是排除后缀 *.bak.*、排除目录名 _backup 或 backups,再只保留扩展名白名单(如仅处理 *.xlsx),两层限制叠加比单靠一层更保险。
用校验值或逐行比对确认回写结果
核对的核心不是“文件变了没有”,而是“变的是不是预期的那几处”。二进制类文件(xlsx、docx、pdf)用哈希比对,适合判断两份文件是否同一内容,以及备份在回写过程中有没有被误覆盖:
sha256sum "$bak"/合同汇总.xlsx /data/inbox/合同汇总.xlsx
要注意哈希值在回写前后本来就应当不同,所以更实用的用法是两步:回写前记录副本哈希到清单,回写后重新算一次副本哈希,确认副本未被改动;同时把回写后的文件哈希一并记入日志,作为这一批次的产出指纹。
文本类文件(csv、txt、json、日志)直接逐行比对,能看出改动落在哪几行:
diff -u "$bak"/a.txt /data/inbox/a.txt > "$bak"/diff-a.patch
diff -q "$bak"/b.csv /data/inbox/b.csv
只想知道有没有差异用 diff -q;需要留证据用 diff -u 把 patch 存进批次目录。表格类文件不能直接 diff 时,可以先导出为 csv 再比对,或者退回哈希加人工抽检。
结果不一致时,按固定字段记一条,方便后续汇总和检索:
batch: $ts
task: invoice-sync
file: /data/inbox/a.xlsx
status: mismatch
detail: sha256 backup=... written=...
状态非 ok 的文件不要继续让下一批覆盖,先把这条记录连同 patch 留在批次目录里。
确定备份保留多久、什么时候清理
保留规则按批次数比按天数更可执行:每个批次一个带时间戳的目录,保留最近一到两个批次,其余在确认后清理。天数规则的问题在于跑批频率不固定,两天可能只有一批,也可能有二十批。
清理前至少做三个确认动作:回写后的文件已经过校验收到的状态是 ok;业务侧没有反馈这一批结果需要回退;该批次没有被下游任务或对账流程引用。有合规或审计要求保留原件的场景,不适用“保留最近一批”的简化规则,需要单独定。
清理命令先跑不带删除的版本,把清单打印出来看一遍:
find /var/backups/kerwork/invoice-sync -mindepth 1 -maxdepth 1 -type d \
! -name "$keep" -print
确认清单符合预期后,再把 -print 换成 -exec rm -rf {} +。这里有两个风险边界要明确:rm -rf 执行后不可恢复,删掉的就是唯一的原文件版本;路径变量为空或拼接错误时,命令的删除范围会扩大到意料之外的位置,所以执行前先 echo "$bak" 把变量值打出来核对。Windows 侧用 Remove-Item -Recurse -Force -WhatIf 先空跑一遍,确认对象无误再去掉 -WhatIf。
把备份与比对写进固定流程
把这套动作固化成每次跑批都走的步骤,并从日志里判断是否真的执行了:
- 生成批次号,建批次目录。
- 复制待处理文件到批次目录,同时写出清单文件(文件名、大小、sha256)。
- 核对清单行数与被处理文件数是否一致,不一致就停止。
- 执行 KerWork 回写。
- 按文件类型做 diff 或 sha256 比对,结果写入
verify文件。 - 统计状态:全部 ok 才允许进入下一批;出现 mismatch 则保留批次目录并暂停。
- 按保留规则清理旧批次,清理前再列一次清单。
每一步都要有可判定的判据,不能只写“检查一下”:清单行数等于源文件数;副本 sha256 与复制时记录一致;diff 输出只包含预期改动;verify 文件里没有 mismatch 行。把这些判据写进任务描述,下一次跑批时按同一套走:
任务名:invoice-sync
输入:/data/inbox,仅处理 *.xlsx,排除 *.bak.* 与 _backup 目录
回写前:复制到 /var/backups/kerwork/invoice-sync/<批次号>/ 并生成 manifest
回写后:逐文件 sha256 + diff 校验,结果写入 <批次号>/verify
失败处理:状态非 ok 时不覆盖后续文件,保留批次目录并在日志中标 mismatch
保留:最近两个批次,其余经人工确认后清理
任务描述里写清“失败时保留什么、不做什么”,比写清“成功时怎么做”更能减少返工。批次的执行记录现在不少工具都能在页面上看到,但页面记录通常只说明任务跑完了,不代表回写内容正确,所以比对结果还是要落成文件,页面状态只能当作辅助判断。