Solaris crontab与Linux差异详解:配置、日志定位与避坑指南
简介《Solariscrontab的用法》是一份面向Solaris系统管理员、运维人员及计算机相关专业毕业设计开发者的PDF文档专门梳理Solaris下crontab与Linux/FreeBSD环境的差异。文档明确指出现有Linux中常用的crontab -u参数编辑他人任务在Solaris中并不适用需要直接修改/var/spool/cron/crontabs/目录下对应用户文件同时给出停止cron服务、编辑任务、启动cron服务的完整操作流程。正文还解析了crontab六段格式和*、a-b、a,b,c等定时写法示例并特别提醒Solaris不支持Linux中常见的*/n间隔语法能帮助读者避免误操作并快速上手。资源包为单个PDF文件大小153KB内容精炼、查阅方便。目前已有93人学习下载对需要完成定时任务配置或进行毕业设计系统维护的同学具有实际参考价值。1. Solaris 的 crontab 为什么比 Linux 版更挑环境从 Linux 迁移过来的运维最容易在 Solaris 的 crontab 上翻车。同样是 crontab -e在 Linux 能稳定跑的任务放到 Solaris 10/11 可能不执行、执行了但没输出、日志里找不到记录。问题多数不在时间格式而在 Solaris 的 cron 对路径、邮件和日志的处理跟 Linux 完全不同。这里想把 Solaris 上 crontab 的常见用法、五字段边界、执行日志定位和典型故障一一说透这份笔记适合还在维护 Solaris 生产机的系统工程师也适合第一次接手这类机器的同路人。2. Solaris crontab 三件套编辑、查看、删除的最小命令与安全边界先把结论放这Solaris 的 crontab 只管理自己的任务root 可以带 -u 管别人。日常就三个命令crontab -e 编辑、crontab -l 查看、crontab -r 删除。命令本身和 Linux 差不多但细节各有各的坑。2.1 crontab -e先弄清默认编辑器再动手用户登录后第一次执行 crontab -e最常撞见的是编辑器选择错误导致无法编辑。很多发行版的 cron 会自动找 viSolaris 可没这么贴心。如果你没有设置 EDITOR 或 VISUAL它可能直接报错也可能调用默认的 ed命令行直接变成交互式行编辑器看起来就像卡住。所以先检查echo EDITOR$EDITOR echo VISUAL$VISUAL两行输出为空时手动指向 viexport EDITOR/usr/bin/vi export VISUAL/usr/bin/vi把这两行写进 ~/.profile。注意 export 只在当前 shell 生效不写进去下次登录还得再设一遍。Solaris 的 crontab -e 会先建一个临时文件给你编辑完保存后再校验并安装到 /var/spool/cron/crontabs/ 下。如果中途编辑器被杀临时文件留在 /tmp下次再编辑可能提示“临时文件已存在”处理办法是清理 /tmp/crontab.*但别把所有用户的一起删先看属主。提示Solaris 的 crontab 临时文件一定在 /tmp 或 $TMPDIR 下不能直接手工改 /var/spool/cron/crontabs/ 下的用户文件cron 不会自动重读你手工改的内容。要么用 crontab 命令要么不要动。然后编辑命令就是crontab -ecrontab -e 执行后会对语法做校验比如分钟字段超出 0-59 会拒绝保存。它不校验命令是否存在所以就算命令路径写错crontab 也会接受这是另一个坑。2.2 crontab -l 与 crontab -r读比写更重要删前先备份很多文档只教你写任务不教你读和备份。我建议在任何 crontab 变更前都把当前任务完整倒出来。备份命令# 生成带日期的备份文件 crontab -l ~/crontab.backup.$(date %Y%m%d)这里注意如果本来没有任务Solaris 10 的 crontab -l 会输出“No crontab for ”重定向进备份文件后这行文字也可能被误当成合法内容。恢复时用 crontab 文件名导入如果备份里含这行说明导入时会校验错。所以正确做法是备份前先确认crontab -l ~/crontab.check 21 wc -l ~/crontab.check如果输出只有一行且内容是 No crontab说明空任务。删除更需谨慎Solaris 的 crontab -r 不像 Linux 会二次确认执行后全部消失。正确的删除姿态ls -l ~/crontab.backup.* crontab -r删除后同样用 crontab -l 验证返回 No crontab 才算完成。想恢复就用crontab ~/crontab.backup.20250101这是 crontab 命令的另一个用法直接跟一个文件路径用文件替换当前任务。批量迁移、导入 export 出来的任务都靠它。root 管理别的用户Solaris 支持 -u 参数。Solaris 10 的写法是crontab -l -u postgres crontab -e -u postgresSolaris 11 官方更推荐把 -u 放在操作符前crontab -u postgres -l实际使用中两种写法在大多数补丁下都能跑但跨版本自动化脚本里容易中招最好在脚本里探测一下crontab -u postgres -l /dev/null 21如果返回非零再尝试 crontab -l -u postgres。这是常见的兼容性处理别嫌丑。权限控制也和 Linux 相反。Solaris 用 /etc/cron.d/cron.allow 和 /etc/cron.d/cron.deny。当这两个文件都不存在时Solaris 默认只允许 root 使用 crontab而大多数 Linux 默认允许所有用户。所以普通用户报 Permission denied 时先检查 /etc/cron.d/cron.allowls -l /etc/cron.d/cron.allow /etc/cron.d/cron.denyallow 文件里一行一个用户名。如果 allow 不存在root 得创建一个并把自己要放行的用户加进去。很多从 Linux 迁过来的团队第一周都在处理这个差异。队列优先级方面Solaris 的 /etc/cron.d/queuedefs 可以调整不同队列的优先级和最大执行时间。默认配置能应付大多数场景不建议动除非你清楚自己在调什么。这个文件不在本章范围知道存在即可。顺带说一句crontab -e 保存后cron 会自动感知并重新加载不需要重启 cron。判断任务是否装好用 crontab -l 查看再 grep 一下有没有自己的命令crontab -l | grep backup这步虽然简单但能避免“改完没保存”的低级错误。我把这条写进巡检脚本里每次变更后自动执行一次比肉眼检查靠谱得多。3. 时间规则与执行环境Solaris crontab 的五字段边界3.1 标准五字段和最常见的越界用法*/n 为什么时好时坏Solaris crontab 条目是五个字段分钟、小时、日、月、星期。没有 Linux 某些发行版里加用户名的那种第六列如果你把用户名写在任务行里那不是给 cron 看的而是被当成命令的一部分执行时必然报 command not found。五字段写法分 时 日 月 星期 /path/to/script例如每天早上 2:30 执行备份30 2 * * * /usr/local/bin/backup.sh这里 30 是分钟2 是小时三个 * 分别代表每天、每月、任意星期。字段支持数字、枚举、区间和步长但步长的可靠性在 Solaris 老版本上一言难尽。最容易被误导的是步长写法*/n。我自己在 Solaris 10 上见过*/10 * * * *大多数时候能跑但偶尔在跨越整点时漏跑。原因是老版本 Solaris cron 对步长字段的实现并不保证“从 0 开始每隔 n 分钟”而是按 cron 守护进程启动时的基准时间推算。所以如果你要求“每 10 分钟一次”稳定性第一建议写0,10,20,30,40,50 * * * *如果你要求“每 15 分钟一次”写0,15,30,45 * * * *除非你能确认所用 Solaris 版本补丁已修复相关问题否则不要依赖*/n。字段还支持“区间”如8-12以及“枚举区间”的混合写法如0,15,30,45。注意 Solaris 的 cron 不支持 Linux 的reboot、daily这类伪关键字Solaris 11 的 cron 实现仍然只认数字和 *。意图写法说明每分钟* * * * *所有字段都允许任意值每5分钟保守0,5,10,15,20,25,30,35,40,45,50,55 * * * *枚举比步长可靠每天凌晨 3:1515 3 * * *小时 3分钟 15每月1号上午9点0 9 1 * *日字段为 1周一到周五下午18点0 18 * * 1-5星期字段用 1-53.2 脚本里必须写前三行PATH、SHELL、MAILTOcrontab 执行任务时环境变量被重置为一个很小的集合。最常见的问题是手工执行脚本可以但 cron 执行时找不到命令因为 PATH 不再是你的 shell 环境。我一般在脚本第一行写死解释器然后前三行显式定义#!/bin/sh # crontab 环境中 PATH 极短必须重设 PATH/usr/bin:/usr/sbin:/usr/local/bin:/usr/xpg4/bin export PATH然后把输出重定向到日志文件避免全部丢进邮件#!/bin/sh # 记录开始时间便于事后排查 echo start $(date %Y-%m-%d %H:%M:%S) /var/log/myjob.log # 真正的任务代码 /usr/local/bin/archive_maintenance.sh /var/log/myjob.log 21 echo end $(date %Y-%m-%d %H:%M:%S) /var/log/myjob.log参数说明21把标准错误并入标准输出都写进日志文件。这点对 Solaris 特别重要因为如果 cron 捕获到任何来自 stdout/stderr 的输出默认行为是把这些输出打包发送到用户邮箱。Solaris 10 默认没有配置本地邮件服务时邮件发送失败会导致任务执行结束但没有任何记录看起来就像“任务没跑”。关于 MAILTO如果你不想收邮件可以在 crontab 文件里不是脚本内写MAILTO让 cron 丢弃输出。也可以在脚本里直接重定向到文件。crontab 文件内环境变量设置的完整示例# 分钟 小时 日 月 星期 命令 MAILTOroot SHELL/bin/sh 0 3 * * * /usr/local/bin/rotate_mysql.sh /var/log/rotate_mysql.log 21注意 MAILTO 写在五字段之前它不是任务条目。3.3 月份和星期的“或”逻辑以及时区里的隐藏陷阱Solaris 的 cron 和 Linux 一样当“日”和“星期”同时被限制时表达的是“或”关系。比如这一条0 2 1 * 1 /usr/local/bin/some_task.sh写的是“每月 1 号”或“周一”的凌晨 2 点各跑一次。不少人把它理解成“每月 1 号并且是周一”才跑结果任务比预期多跑或者少跑查半天查不出原因。遇到日、星期同时限制的调度先把“或”这个语义刻在脑子里再决定值不值得用。我一般直接避免这种写法改用两个独立条目逻辑更清晰0 2 1 * * /usr/local/bin/some_task.sh 0 2 * * 1 /usr/local/bin/some_task.sh时区是另一个 Solaris 特有坑。cron 用系统本地时间判断执行时机而 Solaris 对夏令时切换的处理并不优雅。在 DST 切换日凌晨任务可能跑两次、少跑一次或者日志时间戳跳变。如果任务不要求本地时间我建议在脚本里统一拿 UTC 时间# 日志时间用 UTC避免夏令时干扰 date -u %Y-%m-%d %H:%M:%S如果整个系统都要固定时区可以修改 /etc/TIMEZONE 把 TZ 设为不带 DST 的区比如 UTC。但改完要重启 cron 服务才能让 cron 继承新时区# Solaris 10/11 下重启 cron 服务 svcadm restart cron这个操作会影响所有用户正在运行的任务必须放在变更窗口里做。我没有把改时区当常规手段非必要不碰。3.4 解释器路径与 SHELL 变量的一致性Solaris 10 默认 /bin/sh 是 Bourne shell不是 Linux 上的 bash。很多从 Linux 拷过来的脚本第一行写#!/bin/bashSolaris 默认没装 bash 时脚本直接“找不到解释器”。就算装了 bash路径也可能是 /usr/bin/bash 或 /usr/local/bin/bash和 Linux 的 /bin/bash 不一样。crontab 文件顶部可以指定 SHELLSHELL/usr/bin/bash但指定前要确认实际路径which bash如果没有 bash就用 POSIX sh 语法重写脚本。Solaris 的 /usr/bin/sh 对$(...)、case、while这些基本结构支持没问题只要别用 bash 的数组和[[ ]]。这个约束在写长期维护任务时最省心一句话Solaris crontab 里的脚本默认按 sh 写别按 bash 写。4. 查看 crontab 执行日志Solaris 的 cron 日志目录与 grep 定位技巧作为系统工程师被问最多的就是“我的 cron 任务到底跑没跑”。Solaris 上的答案和 Linux 很不一样。Linux 的 cron 日志通常进 /var/log/cron 或 syslogSolaris 10 则写在 /var/cron/log而且这个文件可能很大不能直接 cat。Solaris 11 也保持类似路径我们需要把日志捞出来用。4.1 日志文件在哪/var/cron/log 与 /var/cron/olog 的分工Solaris 的 cron 守护进程会把执行记录写入 /var/cron/log。这个文件以“!”开始的行是执行了任务的记录后面跟着日期、用户、主机名、任务命令。另一个文件 /var/cron/olog 记录的是 crontab 文件的变更日志也就是谁在什么时候用 crontab -e 修改过任务对审计有帮助。常见做法# 查看最近 cron 执行记录过滤当前用户 grep postgres /var/cron/log | tail -n 100这个日志文件长期不清理会非常庞大。先看大小ls -lh /var/cron/log如果已经几百 MB直接 grep 会很慢。用 tail 只看尾部最有效tail -n 2000 /var/cron/log | grep postgres4.2 用 grep 和 tail 把执行记录和不执行原因捞出来先看最后 50 行日志确认 cron 进程在正常工作tail -n 50 /var/cron/log如果要找某个用户或某条命令是否执行把用户名或命令关键字作为模式# 查看 postgres 用户今天的执行记录 grep postgres /var/cron/log | tail -n 200如果任务没有出现在日志里说明 cron 根本没启动这次作业如果出现了但没有预期效果就要看脚本自己写出的业务日志。这是两个完全不同的排查方向。很多人想按日期过滤但 Solaris 的日志日期格式在不同版本里有差异硬编码日期容易踩空。更稳妥的方式是 tail 一段再 grep# 最后1000行日志中捞任务命令 tail -n 1000 /var/cron/log | grep -E backup|restart还有一个重要技巧当 cron 日志因轮转丢失或者你怀疑 cron 进程压根没执行时最直接的验证是创建一个测试任务跑一次后留下痕迹# 临时测试行每分钟向 /var/log/cron_test.log 写一行 * * * * * /usr/bin/echo test_cron_job /var/log/cron_test.log 21等待一分钟然后cat /var/log/cron_test.log如果文件里有 test_cron_job说明 cron 调度正常接下来再查业务脚本。测试任务跑完要立即从 crontab 里删掉否则它每分钟都执行一次浪费不必要资源。4.3 日志没内容先看邮件服务和 syslog 设置/var/cron/log 是空的不代表 cron 没工作。原因通常有三个cron 服务本身停了。Solaris 10/11 下用 svcs -l cron 查看状态。日志文件被轮转或清空过。作业执行成功并且所有输出都被重定向cron 不会额外写记录不对cron 会记录时间戳。如果日志文件为空但作业在跑可能是 cron 进程被配置为 quiet 模式。先检查 cron 服务状态svcs -l cron服务状态为 online 时再看日志权限和轮转配置。Solaris 上用 logadm 管理系统日志可以查 /etc/logadm.conf 里有没有 cron 日志的轮转规则grep cron /etc/logadm.conf如果没有任何规则/var/cron/log 会一直增长占满 /var。常见做法是给 cron 日志加一条轮转配置比如超过 50MB 就转走保留三份logadm -w /var/cron/log -b 50m -C 3这条命令由 root 执行会把规则写进 /etc/logadm.conf。注意轮转会切走当前日志cron 进程写日志用的是文件路径重新打开新文件需要 cron 感知在 Solaris 下cron 一般会在收到 SIGHUP 或重启服务后重新打开文件。所以添加规则后最好svcadm refresh cron和svcadm restart cron避免日志继续写入已轮转的旧文件。如果连 /var/cron/log 都没有可能是 cron.debug 的 syslog 输出没有被收集。Solaris 的 cron 也会通过 syslog 发送 info 级别到系统日志可以查 /etc/syslog.conf 中是否包含cron.debug以及落点文件。没有的话补充一条并重启 syslogd。不过实际生产里我更依赖 /var/cron/log它比 syslog 完整得多。5. 常见问题与避坑Solaris crontab 不执行、重复执行、日志丢失的排查记录这一章把我在生产环境里真实踩过的坑整理成几条最典型的记录每一条都按现象、原因、解决来写方便你对照自己的环境排查。5.1 现象crontab -e 报“Unable to create a temporary file”任务始终不敢动现象执行 crontab -e提示crontab: unable to create a temporary file in /tmp或Cannot create /tmp/crontab.*。原因Solaris 的 crontab 在 /tmp 创建临时文件如果 /tmp 空间满了、或者当前用户对 /tmp 没有写权限某些安全加固会把 /tmp 挂载为只读、noexec 或 restrict就会失败。还有 TMPDIR 变量被设置到一个不存在/不可写目录也常见。解决先df -h /tmp清掉大文件。然后检查环境变量echo $TMPDIR如果是空crontab 就用默认的 /tmp。如果 TMPDIR 指向不可写路径在编辑前导出到可用目录export TMPDIR/var/tmp crontab -e我遇到过安全加固后的 Solaris把 /tmp 弄成只读所有用户 crontab 全部编辑失败当时就是这样绕过去的。5.2 现象手工执行脚本正常cron 执行却提示“command not found”现象脚本逻辑没问题放在 cron 里每 5 分钟跑一次日志中显示command not found或脚本没达到预期。原因cron 环境 PATH 只有 /usr/bin 和 /usr/sbin自定义命令如 /usr/local/bin 下的工具不会被找到。另外脚本头#!/bin/bash在 Solaris 上如果没有 bash 这个解释器路径直接加载失败。解决在 crontab 文件里定义 SHELL 和 PATH或者脚本内重设 PATHSHELL/bin/sh PATH/usr/local/bin:/usr/bin:/usr/sbin:/usr/xpg4/bin然后把命令写成绝对路径不依赖 PATH。我一般两种都做脚本开头重设 PATHcrontab 里再显式给 PATH。为什么两种都做因为有些第三方工具在运行时还会调用其他命令只设 crontab 的 PATH 可能不够脚本内的 PATH 能保证所有子命令也走同一套路径。5.3 现象任务在日志里显示执行了但实际重复跑了多次现象一个任务每分钟跑一次但日志里同一分钟出现多次或者业务上出现重复数据处理。原因最常见的是用户意外拥有两份 crontab 文件或者几个用户的 crontab 都包含了同一行命令。Solaris 的 cron 会把 /var/spool/cron/crontabs/ 下所有用户的文件都加载重复很正常。另一种原因是脚本本身逻辑较慢上一次还没结束下一次又启动产生并发。解决先列所有 crontab 文件看是否重复grep -r backup /var/spool/cron/crontabs/如果是并发重复在脚本中使用锁文件。Solaris 没有 flock可以用 mkdir 做原子锁#!/bin/sh LOCKDIR/var/lock/backup_job.lock if ! mkdir $LOCKDIR 2/dev/null; then echo another backup job is running /var/log/backup.log exit 1 fi trap rmdir $LOCKDIR EXIT # 任务主体...注意 mkdir 是原子操作锁文件目录存在时不会创建成功。这个锁可以防重复但要担心残留锁目录所以用 trap 清理。另外锁目录要放在脚本可写路径避免每次 cron 用户不同造成权限问题。5.4 现象任务执行后没有任何输出日志文件也没有记录现象脚本在 cron 里跑了业务结果看不出也没有任何报错。原因cron 默认捕获 stdout/stderr 后发送邮件如果 Solaris 没有配置本地邮件或 sendmail 启动失败输出丢失。如果你在 crontab 里没做重定向也找不到业务日志。解决每一条 cron 任务都强制把 stdout 和 stderr 追加到固定日志文件例如30 2 * * * /usr/local/bin/backup.sh /var/log/backup.log 21同时检查 sendmail 服务状态如果不需要邮件在 crontab 顶部设置MAILTO让 cron 丢弃输出而不是试图发信。这样既能减少邮件队列堆积也不影响业务日志。5.5 现象从 Windows 编辑过的 crontab 文件装不进去现象用 Notepad 修改过备份文件再执行crontab file导入时报格式错误或任务不正常执行。原因文件行尾是 CRLFSolaris 下的 cron 解析会把 \r 当作命令的一部分导致命令找不到五字段行可能直接整行被忽略。解决导入前先用tr -d \r或sed清洗# 去掉回车符再导入 tr -d \r my_crontab.txt my_crontab_clean.txt crontab my_crontab_clean.txt导入后的验证crontab -l | od -c | head -n 20如果发现行尾有\r说明没清干净。实际上用file命令也能看出来file my_crontab.txt输出包含 “with CRLF line terminators” 就要处理。6. 给脚本加执行日志与手动验证一套能反复用的 Solaris crontab 模板最后交一个我长期在用的模板它把环境变量、输出重定向、锁防重、日志分隔都揉在一起拿去改改就能用。crontab 部分# Solaris crontab 模板适合长期维护 MAILTO SHELL/bin/sh PATH/usr/bin:/usr/sbin:/usr/local/bin:/usr/xpg4/bin # 每天 00:05 执行数据检查 5 0 * * * /usr/local/bin/check_data.sh /var/log/check_data.log 21脚本部分#!/bin/sh # check_data.sh LOG/var/log/check_data.log LOCKDIR/var/lock/check_data.lock if ! mkdir $LOCKDIR 2/dev/null; then echo $(date %F %T) another task running $LOG exit 1 fi trap rmdir $LOCKDIR EXIT echo $(date %F %T) begin $LOG # 任务主体所有外部命令用绝对路径 /usr/bin/su - postgres -c /usr/bin/psql -c select 1 $LOG 21 echo $(date %F %T) end $LOG安装之前永远先在当前用户 shell 环境下跑一遍这个脚本并检查退出码sh /usr/local/bin/check_data.sh echo $?退出码为 0 再进 crontab。接着检查日志目录的写权限cron 以当前用户身份执行任务日志文件所在目录必须对该用户可写ls -ld /var/log/check_data.log如果目录属于 root 且没有其他写权限任务执行时日志打不开但 cron 本身可能还是认为任务成功。我处理过的 Solaris 机器几乎每台都有因为日志不可写导致任务“正常执行但毫无记录”的情况。后来养成习惯所有任务在安装进 crontab 之前先在该用户身份下跑一遍并确认日志路径可写装好后等一个周期再看 /var/cron/log 和业务日志双重确认。希望这套模板能帮你减少同样的弯路希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →