尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Solaris crontab用法详解:与Linux差异、避坑指南及定时任务实战

Solaris crontab用法详解:与Linux差异、避坑指南及定时任务实战 简介Solaris下的crontab定时任务配置常让不少管理员困惑。这份PDF聚焦Solaris与Linux/FreeBSD平台下crontab用法的差异面向需要维护Solaris服务器或正在完成系统相关毕业设计的读者。文档明确指出Solaris不支持crontab -u参数与*/5式频率写法并给出推荐操作路径通过vim直接编辑/var/spool/cron/crontabs/下对应用户文件配合/etc/init.d/cron stop/start完成服务启停。全文以1个PDF文件呈现大小约153KB内容紧凑适合随时查阅。目前已有93人学习/下载。阅读后可掌握crontab六字段格式、分钟/小时/日期/月份/星期各段含义以及-e、-l、-r等常用参数用法文档还整理了多个定时任务示例、范围与间隔写法以及容易误操作导致原配置被替换的注意事项对日常系统维护和排错具有直接参考价值。1. Solaris crontab 用法从“看着装了却跑不了”讲起做毕业设计那年第一次摸到 Solaris 机器我把 Linux 上玩得很熟的 crontab 直接照搬过去。crontab -e能进编辑界面:wq也提示 “installing new crontab”看起来一切正常可到了时间点任务就是不跑。后来才知道Solaris 的 cron 实现、任务文件位置、时间字段限制和日志路径都和 Linux 有不少差异有些坑不踩过根本想不起来。这份《Solariscrontab的用法.pdf》整理的正是这类真实用法怎么确认当前用的是哪个 crontab、怎么避开不支持的时间写法、日志去哪个文件看、权限文件怎么配。它不是把 Linux 手册换个名字而是把“在 Solaris 上运行定时任务”拆成可复现的步骤和排查方向。适合正在做 cs 相关毕业设计的学生也适合需要维护老 Sun/Oracle 服务器的运维同事。后面我会按“命令与格式差异 → 实际编写与日志 → 权限控制 → 踩坑记录 → 毕业设计可复用模板”往下拆把 PDF 里每个需要留意的地方单独拿出来讲。这样你看完正文基本就能判断这份内容对你有没有用也知道下载后重点该翻哪几页。2. Solaris 和 Linux 的 crontab 差异先想清楚命令、文件和时间段2.1 命令路径与默认行为等一等再敲crontab -e在 Linux 上打开终端敲crontab -e默认走的是/usr/bin/crontab对应 cronie 或 vixie cron。Solaris 里也有一个crontab命令但它的实现和后台的 cron 守护进程是 Solaris 自己的行为不完全一样。我拿到一台新 Solaris 机器后的第一件事是先用which crontab确认命令解析到了哪里而不是顺着 Linux 的习惯直接敲编辑命令。Solaris 的 crontab 命令常见路径是/usr/bin/crontab但登录 shell 的 PATH 不同实际调用的可能是/usr/sbin/crontab也可能是管理员手动放入的包装脚本。多台机器一起排查时格外容易踩这个坑A 机器的/usr/local/bin里放了一个 wrapperB 机器没有结果两台机器执行同一条crontab -l的表现完全不同。建议先跑一组基线命令把环境钉住# 确认 crontab 命令解析到哪里 which crontab # 确认当前用户是否已有任务同时看退出码 crontab -l echo exit code: $?如果当前用户没有任务Solaris 的crontab -l输出可能是空的退出码是 1Linux 一般会打印no crontab for user。这个差异会影响自动化脚本的判断比如crontab -l | grep backup在没有任务时会抓到一行提示导致后续逻辑走错分支。我一般会把输出单独存到一个变量里先看退出码再看内容不让提示语混进配置判断。编辑时还要注意编辑器环境变量。Solaris 的传统 cron 会参考EDITOR和VISUAL两个变量都没设置时crontab -e可能打开 vi也可能落到系统默认的ed这会让很多年轻工程师直接懵掉。因此我建议先把编辑器固定下来服务器上只设 viexport EDITOR/usr/bin/vi export VISUAL/usr/bin/vi crontab -e这里有个容易被忽略的锁机制crontab编辑会话会在 spool 目录留下临时锁。如果上次编辑因为断连或kill -9中断锁文件可能没来得及清理再次执行crontab -e会提示crontab: locking或file busy。这种情况下不要盲目killcron 进程先找锁文件确认没有其他编辑器进程后再删掉。查找位置通常和任务文件同级名字类似/var/spool/cron/crontabs/username.lock。这个问题的排查思路我在后面的避坑章节里会再展开一次。2.2 任务文件与属主要改任务就通过 crontab 命令别直接碰文件Solaris 的用户 crontab 文件集中在/var/spool/cron/crontabs下文件名就是用户名。这个目录只有 root 能直接进入普通用户即使知道路径也无法读取别人的任务文件。安全的操作方式是使用crontab -l查看、crontab -e编辑、crontab -r删除不要用 vi 直接打开 spool 下的文件。为什么不能手动编辑因为 cron 守护进程只在两种时候重新读取任务crontab命令提交了新的内容或者 cron 守护进程重启。直接改文件不会触发重载你看到的内容改动和实际调度是两回事任务往往不会跑。另一个原因是手动编辑容易把属主改到 root 或把权限变成 644crontab命令对这类文件会拒绝提交反而把自己锁在外面。修正权限的常见写法是# 假设任务文件属于 user1但权限坏了 chown user1:staff /var/spool/cron/crontabs/user1 chmod 600 /var/spool/cron/crontabs/user1上面这条命令需要 root 权限。Solaris 对 crontab 文件的属主检查比较严格文件归 root 时crontab -u user1 -e虽然可以编辑但最终 cron 读取时是否接受取决于文件属主如果属主不是任务对应用户任务状态会变成No such user或直接忽略。如果你平时负责运维还需要关心多用户部署root 替某个普通用户装任务时用crontab -u username -e它会以那个用户的身份创建或替换 spool 文件。不要先切到 root 再直接写 spool 文件那样文件属主会变成 root普通用户自己却不能再编辑非常被动。2.3 时间字段与系统 crontab五段之外还有一个用户列标准 crontab 时间字段是五段分、时、日、月、周。Solaris 的用户 crontab 沿用了这个格式如果你编辑的是/etc/crontab这个系统级文件那么第五段后面还可以再加一个“用户”字段指示这条任务以哪个用户身份运行。这是和 Linux 有明显差异的地方很多从 Linux 迁过来的人在这里翻车把用户名往用户 crontab 的第六段里塞结果整条任务被解析成非法格式。举例来说系统级 crontab 的写法是这样的# 系统 crontab分 时 日 月 周 用户 命令 0 1 * * * root /export/home/scripts/backup.sh而用户自己的 crontab 不应该写第六段直接0 1 * * * /export/home/scripts/backup.sh即可。如果写成0 1 * * * root /export/home/scripts/backup.shcron 会把第一个字段之后的root当作命令的一部分执行时找不到这个路径日志里会留下诡异的报错。这条差异在 PDF 里是放在目录最前面的重点建议用“用户 crontab vs 系统 crontab”两张示例表对照记忆。时间字段的扩展语法也需要留意。Linux 的 cronie 支持reboot、daily、hourly这类简写Solaris 的传统 crond 在某些版本里并不认识它们。还有步长写法比如*/15 * * * *在部分 Solaris 上不会按预期展开为“每 15 分钟”我实际测试时发现它可能被解析成一个奇怪的值或被直接忽略。保守做法是把步长展开成数值列表0,15,30,45 * * * *。这样的写法在任何平台都不会有歧义。此外百分号在 crontab 里有特殊含义它表示换行或标准输入的分隔符。Linux 和 Solaris 都如此但 Solaris 的命令行参数传入方式让这个问题更容易爆发。你如果想执行date %Y%m%d不转义会导致 cron 把%Y%m%d之后的内容丢给前一命令的标准输入命令本身并不会报错但结果完全不对。正确做法是对%做\%转义这个我会在第 5 章踩坑记录里给一个完整例子。这一章落地的结论是操作前先确认命令路径编辑统一走crontab命令时间字段谨慎使用扩展语法搞清用户 crontab 和系统 crontab 的第六段区别。这些规则明白了后面的实机演练才不会越做越乱。3. 实机演练把 Solaris crontab 用起来日志也要能查到3.1 第一次编辑任务编辑器、保存和验证先设置编辑器再执行crontab -e。很多 Solaris 默认不设置EDITOR结果进到 ed 编辑器里光标不显示、不知道如何保存。所以我每次都会先写一行export EDITOR/usr/bin/vi。下面是最常见的第一遍操作流程export EDITOR/usr/bin/vi crontab -e进入 vi 后插入以下内容并保存退出# 每分钟输出一行测试日志到自己的 home 目录 * * * * * /usr/bin/date /export/home/yourname/test.log 21保存退出后用crontab -l确认内容crontab -l * * * * * /usr/bin/date /export/home/yourname/test.log 21这里解释一下为什么要用/usr/bin/date的绝对路径而不是date。cron 执行命令时的 PATH 比较简化如果脚本没有自己定义 PATH光写date很可能在运行时找不到命令。Solaris 的默认 PATH 一般不会像你登录 shell 那样完整绝对路径能避开这个坑。表示追加避免每次执行覆盖日志21表示把标准错误也写到同一个文件这样即使date命令本身出问题你也能从日志里看到线索。第一遍建议只放这种最低开销的任务跑几分钟后用tail -f观察输出是否正常增长。如果日志文件没有出现第一步查 crontab 是否真的安装第二步查/var/cron/log第三步就要看时间字段了。3.2 时间字段推演从“每 5 分钟”到“每月 1 号凌晨”新手最容易卡在时间字段的换算上。五段分别是分、时、日、月、周每段都可以填单值、逗号列表、区间和通配符。Solaris 下我对步长语法保持谨慎能用列表就不用*/。下面几条是我经常用的参考写法# 每 5 分钟执行一次 5,10,15,20,25,30,35,40,45,50,55 * * * * /export/home/test/bin/task.sh # 每小时的第 15 分钟执行 15 * * * * /export/home/test/bin/task.sh # 每天凌晨 2 点执行 0 2 * * * /export/home/test/bin/task.sh # 每月 1 号的 3 点 30 分执行 30 3 1 * * /export/home/test/bin/task.sh每条任务的字段如果按顺序排最后想象成一个从“分”到“周”的过滤器。5,10,...这种写法比*/5长但它把语义固定住了不会受 cron 实现差异影响。如果你觉得手写列表容易漏数也可以在 PDF 里找到一张“分钟/小时/日/月/周边界值速查表”照着写即可。还要注意日志重定向这一块属于任务命令的一部分* * * * * command log 21里的和21不是 crontab 字段而是交给 shell 执行的输出重定向。如果命令本身带有参数比如find /tmp -name *.tmp -exec rm {} \;里面的%、;、空格都有被 cron 转义或截断的风险。常见做法是把复杂命令写到一个脚本文件里crontab 只保留一条调用脚本的纯净命令这比在 crontab 里硬塞一长串参数要稳得多。3.3 查看 crontab 执行日志日志在哪个文件怎么看“查看 crontab 执行日志”是我经常被问到的问题。原理很简单crontab -l只能看“配置”不能看“执行结果”。执行结果有两层记录一层是 cron 自己记的调度日志另一层是你任务脚本里重定向出去的业务日志。很多用户盯着crontab -l找执行记录当然什么也找不到。Solaris 的 cron 调度日志传统上在/var/cron/log或/var/log/cron具体路径跟版本有关。这个文件一般由 root 所有普通用户读取会有权限问题。运维排查时可以这样用# root 或 adm 组用户执行 tail -100 /var/cron/log | grep yourname # 只看最新记录 tail -f /var/cron/log如果你没有权限看/var/cron/log最直接的替代方案是给每个任务都加上独立日志文件用重定向把 stdout 和 stderr 都留到自己的家目录。比如30 2 * * * /export/home/test/bin/backup.sh /export/home/test/logs/backup.log 21这样排错时先用ls -l看日志文件是否存在再看时间戳是否新鲜最后看文件内容。如果日志文件压根没生成说明命令可能没被调度而不是脚本执行出错。/var/cron/log里记录的是调度事件出现CMD (path)字样说明任务被调用如果只有USER没有CMD可能是内容解析失败。这一段详细的日志格式对照PDF 里做成了截图式表格我在正文里先用文字把关键点说透避免你把两层日志混为一谈。4. 权限控制与任务隔离cron.allow、cron.deny、属主和 PATH4.1 cron.allow/cron.deny谁能使用 crontab 并不是靠猜的Solaris 控制 crontab 使用权限的文件通常是/etc/cron.d/cron.allow和/etc/cron.d/cron.deny也有的版本放在/etc/cron.d路径以实际机器为准。两个文件每行一个用户名解析顺序和 Linux 不完全一样。一般来说如果cron.allow存在只有列在里面的用户可以使用 crontab其他用户即使没被cron.deny排除也不行如果cron.allow不存在而cron.deny存在那么不在 deny 列表中的用户都可以使用。两个文件都不存在时Solaris 默认通常只允许 root 使用。这个默认策略值得特别记住。你在 Linux 上配 cron 时默认是大多数用户都能用 crontab但 Solaris 不一样很多 Unix 版本是隐式禁止普通用户。因此毕业设计或者实验环境下如果普通用户执行crontab -e直接报错不要急着怀疑锁定文件先检查这两个文件cat /etc/cron.d/cron.allow 2/dev/null cat /etc/cron.d/cron.deny 2/dev/null如果想让某个账号能使用定时任务root 可以把它追加到cron.allow中。注意修改后不需要重启 cron 服务crontab 命令每次执行都会重新读取这两个文件。这种即时生效的机制在其他有些平台并不具备排查时可以先把这点作为基线。还有一个容易混淆的点cron.allow控制的是用户能不能调用crontab命令它不控制 cron 本身能否以该用户身份运行任务。也就是说即使任务已经存在如果该用户后来被加入了 deny 列表原有任务可能仍然继续执行直到文件被移除或 cron 重启。这给人一种“明明禁止了却还在跑”的错觉排障时需要区分“提交任务”和“执行任务”两个阶段。4.2 属主和文件权限任务没跑先查 crontab 文件而不是业务脚本很多任务不执行的问题根源不在业务脚本而在 spool 下的 crontab 文件权限。正常状态是任务文件归对应用户所有权限为 600。若管理员用 root 直接修改了文件或某个脚本误操作把权限改成了 666cron 在读取时可能就会忽略该任务甚至发出权限警告。查看命令ls -l /var/spool/cron/crontabs/yourname -rw------- 1 yourname staff 120 Sep 10 09:00 yourname如果看到属主不是你自己比如变成了 root那么需要 root 介入修正chown yourname:staff /var/spool/cron/crontabs/yourname chmod 600 /var/spool/cron/crontabs/yourname还有一种情况系统里的用户账号被删除但其 crontab 残留日志中会出现No such user。这类残留文件不会自动清理需要运维定期扫描/var/spool/cron/crontabs对比当前 passwd 文件中的用户把孤儿文件移走或删除。直接用crontab -r无法清理不属于自己的文件用 root 也要小心日期参数别把其他用户的任务一并摘掉。4.3 环境变量隔离脚本里没有 PATH就等于命令不存在cron 在执行任务时只提供一个很小的环境登录 shell 中.profile定义的环境不会自动加载到 cron 任务里。所以你会看到很多任务在自己的环境下能跑一放到 crontab 里就报date: not found或find: not found。解决方式有两种一是命令写绝对路径二是在 crontab 文件顶部统一声明变量。下面是一个推荐的头部写法PATH/usr/bin:/usr/sbin:/usr/xpg4/bin:/usr/local/bin SHELL/bin/sh HOME/export/home/yourname MAILTOyournameexample.com # 每小时的第 15 分钟运行检查脚本 15 * * * * $HOME/bin/check_disk.sh $HOME/logs/check_disk.log 21说明一下PATH行如果放在任务列表上面cron 会把这一行解析为环境变量设置而不会当作任务。之后每条任务里的$HOME和裸命令就会在这个 PATH 下工作。SHELL/bin/sh设置的是执行命令的 shell不是登录 shell所以不要指望rc文件被加载。MAILTO指定错误和输出发送给谁如果不想收邮件可以不设置或让它发到 /dev/null。在 Solaris 上/usr/xpg4/bin是一个和 POSIX 兼容的工具集地址很多脚本在PATH里加上它之后grep、sed、awk的行为会相对现代一些。但加了它也可能改变原有脚本对古老命令行为的依赖是否加入需要根据你的脚本实际情况判断。这些都是让 cron 环境稳定的常见做法PDF 里在“环境变量模板”一节给出了几种典型组合按照自己的应用选择就好。5. 避坑手册Solaris crontab 的五个典型问题与排查记录在 Solaris 上报障最怕的就是把所有问题都归结为脚本逻辑。我把过去踩过的坑整理成了五条每条都按照现象、原因、解决三步走你看的时候可以一一对照。5.1 任务不执行但crontab -l显示正常步长写法被忽略现象我在 crontab 里写了*/15 * * * * /export/home/test/bin/task.sh使用crontab -l查看时一切正常但到了时间点任务不跑手动执行脚本又是好的。原因Solaris 的 cron 没有把*/15当作步长语法处理。不同版本对这个写法的解释不一致有的直接把整条任务当作非法忽略掉有的则只执行第一个匹配字段表现是偶尔跑、偶尔不跑。解决把步长写法改成显式列表。0,15,30,45 * * * *在几乎所有平台都能正常工作。排查时可以在/var/cron/log里看有没有CMD记录如果没有高度怀疑是语法被忽略。之后每次写时间字段我都先检查是不是用了*/一旦出现就主动展开避免给后面埋雷。5.2 命令里有%符号日志出现奇怪的执行状态现象任务里写了一条date %Y%m%d /tmp/date.log但文件里的日期不完整甚至命令的后续部分直接丢失日志中出现两次命令调用或标准输入内容。原因在 crontab 里未转义的%会被 cron 当作换行符%后面的内容会被送到上一命令的标准输入。date %Y%m%d里的%Y还没被 shell 展开就被 cron 分开了最终执行内容面目全非。解决把每个%都转义成\%也就是写成date \%Y\%m\%d。如果任务里有一长串带%的串联命令很容易漏转义所以我通常选择把命令写成一个脚本脚本内部正常使用%crontab 只保留一条干净的脚本调用。这样既能避免转义遗漏也让脚本更可读、可测。5.3 日志里找不到任务记录查错了日志或权限不够现象任务好像执行了但在/var/log/cron里找不到任何记录用grep username /var/log/cron也只看到几行无关内容。原因Solaris 的 cron 日志路径不是/var/log/cron常见的是/var/cron/log且日志默认权限不对普通用户开放。读错文件当然找不到权限不够时看到的内容是空的也会造成“任务没跑”的错觉。解决先用ls -l /var/cron/log确认文件存在再确认自己是否在 adm 组或有 root 权限。没有权限就靠任务自己的重定向日志排查。我在排障时会同时抓两个证据一是任务脚本自己生成的业务日志二是/var/cron/log里出现的CMD记录。只有两层都没有才能断定任务未被调度。5.4 手工编辑 spool 文件后任务不加载没有通知 cron 重读现象用 vi 直接改了/var/spool/cron/crontabs/root任务内容明显已经更新但到了点还是不执行重启 cron 后才正常。原因cron 不像某些服务那样随时监听文件变化它只通过crontab命令提交时加载任务直接编辑 spool 文件不会触发重载。而且手工编辑绕过了锁定和属主检查容易留下不一致状态。解决任何时候编辑任务都用crontab -u 用户名 -e保存后立刻用crontab -l确认。如果是 root 管理多个用户也不要自己去找 spool 文件crontab -u是唯一推荐方式。实在需要手工清理孤儿文件操作前先备份操作后执行一次crontab -l验证。5.5 环境变量为空导致命令不存在脚本路径与环境依赖不一致现象脚本在终端手动执行正常放到 crontab 后提示date: not found或script: not found日志里完全没有有效输出。原因cron 提供的最小环境里 PATH 很短甚至没有包含脚本期望的目录执行时不会读取用户.profile导致依赖的自定义变量和脚本路径全部为空。解决在 crontab 顶部显式写PATH、SHELL、HOME命令尽量写绝对路径。脚本内不要依赖登录环境开头可以加#!/bin/sh如果真的要加载环境文件用. /export/home/user/.profile二选一但要谨慎.profile里的输出或交互语句可能干扰异常任务环境。更稳妥的做法是脚本自带所有环境定义让 crontab 成为纯调用者。6. 放进毕业设计里的进阶用法一套带状态检测和告警的 cron 模板如果你在做 cs 方向的毕业设计比如在一台 Solaris 服务器上写数据采集、临时文件清理或进程守护最好把每一条定时任务都做成“可观测”的。只写一个裸命令日志里看不见脚本退出码任务失败了你也不会第一时间知道。我这边常用的方式是三层设计外层是 crontab 调用中间是 watchdog 包装脚本内层是你要执行的业务脚本。包装脚本负责记录开始时间、结束时间、退出码并将异常写入单独的错误日志。下面是一个可直接套用的模板主要是用sh写的包装函数#!/bin/sh # watchdog.sh - 包装任意命令生成结构化日志 CMD$ LOG_DIR/export/home/graduate/logs mkdir -p $LOG_DIR stamp$(/usr/bin/date \%Y-\%m-\%d_\%H:\%M:\%S) start$(/usr/bin/date %s) echo [$stamp] CMD_START: $CMD $LOG_DIR/run.log $CMD $LOG_DIR/run.log 21 rc$? end$(/usr/bin/date %s) duration$((end - start)) if [ $rc -ne 0 ]; then echo [$stamp] CMD_FAIL rc$rc duration$duration $LOG_DIR/error.log else echo [$stamp] CMD_OK rc$rc duration$duration $LOG_DIR/run.log fi exit $rc重点在于CMD$接受任意命令和参数date \%Y-\%m-\%d_\%H:\%M:\%S里的转义是给 crontab 用的如果这个脚本在普通 shell 下执行就不需要加反斜杠。exit $rc会把业务脚本的退出码传出去这样上层调用工具可以判断成功还是失败。你还可以在CMD_FAIL分支里插入邮件或短信接口让失败任务主动告警。然后在 crontab 中这样调用PATH/usr/bin:/usr/sbin:/usr/xpg4/bin:/usr/local/bin SHELL/bin/sh HOME/export/home/graduate # 每 15 分钟检查磁盘使用率 0,15,30,45 * * * * $HOME/bin/watchdog.sh $HOME/bin/check_disk.sh # 每天凌晨 1 点清理三天前的临时文件 0 1 * * * $HOME/bin/watchdog.sh $HOME/bin/clean_tmp.sh这里用check_disk.sh和clean_tmp.sh代替实际业务命令每个业务脚本自己保持单一职责watchdog.sh不会理解业务只负责记录生命周期。这套结构的好处是无论哪个脚本失败你都能从error.log里看到准确的时间点和退出码而不是在/var/cron/log里翻半天。从那以后我每次写完 crontab 都强制自己走一遍验证流程先crontab -l确认安装再tail -f观察前两次执行最后检查 error.log 是否为空。这套习惯看起来麻烦但能省下后面大量排障时间尤其是毕业设计临近验收熬夜找“为什么没跑”的代价太大了。希望这份 PDF 里整理的 Solaris crontab 用法也能帮你少走一圈弯路。本文还有配套的精品资源点击获取
返回列表