1. 什么场景下需要ESXi 7.0定时关机——先看清需求再动手
前阵子朋友所在的实验室找到我,机柜限功率,晚上八点以后必须把几台跑测试的服务器关掉,第二天上班再开。这个需求听着小,可真动起手来,我发现有不少人卡在同一个地方:ESXi 7.0的Web管理界面里,你只能手动点"关机"或"重新引导",压根找不到一个像Windows任务计划那样直接设置"每天23:30自动关机"的入口。VMware ESXi 7.0定时关机这件事,说难不算难,但确实需要把ESXi的命令行机制和任务调度机制都摸明白再动手。
先回答最核心的问题:到底什么场景真的需要用这个功能?我接触下来主要是这三类。
第一类是实验室和办公测试环境。很多公司的测试服务器白天跑虚拟机,晚上没人看,风扇嗡嗡开一整夜,电费白交,还得担心散热和噪音。搭配一个定时关机,让ESXi凌晨两点自动断电,第二天早上再远程开机,工作量少,电费也能省下来。第二类是限功率机柜。老旧机房或者临时机房,回路功率卡得特别死,几台双路服务器同时满负荷跑,晚上再加夜间空调,配电箱就容易顶不住。在这种环境下,定时关机就是刚需,不是可选项。第三类是无人值守的远程站点。像分公司弱电间、门店后仓、边缘计算盒子,白天有业务,晚上没有,与其让ESXi在无人状态下遭遇突然断电,不如到点温和关机,对虚拟机和底层文件系统的保护要好得多。
不过我在这里要先打一个预防针:ESXi 7.0虽然基于Linux派生出了一套命令行环境,但它和你在Ubuntu、CentOS上操作的习惯有很大区别。ESXi没有systemd,没有systemctl,传统Linux上那一套"timedatectl设置时间、systemctl start crond"的思维在这里会碰壁。它用的是自己的init机制,BusyBox工具集,一些命令的路径和Linux发行版也不完全一样。这意味着,你在网上搜到的大部分Linux定时关机教程不能直接照抄,得先搞懂ESXi 7.0自己的底子,否则很容易出现"配置明明写了,到点就是不动"的怪现象。
1.1 三个真实场景的具体需求
拿实验室来说,我接手过一台跑CI构建的ESXi 7.0,虚拟机白天被开发团队频繁调用,晚上十点以后基本没人碰。客户想让它每天23:50自动关机,省电也降低设备损耗。这里要求的就是"每天定时、单机、无需人工介入"的纯自动流程。还有一个门店场景,ESXi放在店里的弱电箱,白天开店业务系统在虚拟机里跑,晚上闭店后店里断电离开。门店负责人希望ESXi在22:30自动关闭,给UPS留足余量,避免深夜电压波动把阵列搞出坏道。这个场景对关机的可靠性要求很高,因为没人值守,出了问题要第二天才能发现。第三个场景是一个企业的灾备演练,定期在周末凌晨对测试ESXi做关机演练,验证虚拟机快照恢复流程。这种需求需要的是"可指定星期几执行"的灵活调度,不是每天固定时间。
这三个场景看起来不同,但共同需求都是:单机ESXi 7.0、没有外部控制服务器、希望ESXi自己在某个时间点触发关机动作。而ESXi 7.0恰恰没有提供GUI方式的定时关机配置,所以只能从命令行层面解决。
1.2 ESXi 7.0的“定时任务”底子跟Linux有什么不同
ESXi 7.0底层是VMkernel,和传统Linux内核完全两码事。但它为了运维方便,保留了一个极简的BusyBox用户态环境。这个环境里有crontab命令,有esxcli命令,有vim-cmd命令,甚至还有vi。然而它没有systemd,服务管理靠的是/etc/init.d下的脚本加chkconfig;它的根文件系统是只读的,很多临时修改重启后会丢;它的cron服务虽然叫crond,但默认是否自启、默认PATH是否和我们习惯的Linux一致,都需要实际验证。这些差异决定了,配置定时关机时,必须额外关注三件事:服务有没有起来、任务是否持久化、脚本中的命令是否能被cron环境找到。
2. 四条关机路线横向对比:vCenter、PowerCLI、原生crond和带外管理
在正式开搞之前,我想先做个方案选型。ESXi 7.0定时关机实际上不止一条路,我见过的大概有四条,每条都有自己的适用面。用一个表格把它们的本质区别列出来,会直观很多。
| 方案 | 外部依赖 | 灵活度 | 上手成本 | 适用场景 |
|---|---|---|---|---|
| vCenter Scheduled Task | 必须部署vCenter | 中,支持主机/虚拟机的常见电源操作 | 低,GUI向导 | 多台ESXi、已有vCenter的集群环境 |
| PowerCLI脚本 + 外部任务计划 | 一台Windows/Linux管理机 | 高,可写判断和循环 | 中,要维护脚本和凭据 | 需要批量编排、精细控制、统一审计 |
| ESXi原生crond | 无 | 中,主要依赖Shell脚本 | 中,纯命令行 | 单台ESXi、无vCenter、追求零依赖 |
| IPMI/Redfish带外管理 | 服务器BMC管理口 | 低,一般只能整机电源操作 | 中 | 作为最后兜底,ESXi崩溃也能关机 |
2.1 各方案优缺点与适用场景
先说vCenter Scheduled Task。如果你的环境已经部署了vCenter,这是最"省脑子"的方案,图形界面上新建一个计划任务,指定主机、指定时间、指定电源操作,保存就完事。它还能记录每次执行的历史,在vCenter的"近期任务"里看得清清楚楚。但它的先决条件很硬:vCenter本身必须在线。如果你这台vCenter正好跑在这些ESXi上的某一台虚拟机里,而计划时间点vCenter还没启动,那任务根本不会触发。这种"循环依赖"在企业里见得太多了,不得不防。
再看PowerCLI。这是VMware官方的PowerShell模块,通过它连到ESXi或vCenter执行Shutdown-VMHost,配合Windows任务计划程序或Linux的cron,就能实现任意复杂的定时关机流程。它最大的优点是可以写判断:先循环关闭所有虚拟机,等虚拟机都Power off之后再关主机;某个虚拟机超过N分钟没关,报警还是跳过,都由你说了算。缺点是要额外维护一台管理机,还要处理脚本里的凭据和权限问题。
然后是ESXi原生crond,这也是我在这类需求里最常用的方案。ESXi自带crond服务,crontab语法和Linux几乎一致,你只需要SSH到主机上写一条cron表达,再放一个关机脚本,任务就挂上了。没有任何外部依赖,哪怕vCenter、管理机全挂了,它也能到点执行。这也是为什么很多单机环境、实验室环境选它。缺点是要熟悉命令行,而且ESXi的只读文件系统让"持久化"这个动作需要多留个心眼。
最后是IPMI/Redfish带外管理。服务器主板上一般都有BMC管理口,通过IPMI或Redfish协议,即使ESXi系统早就死机了,你依然能从硬件层发送Power Off指令。它可以作为其他方案的兜底:假设ESXi上crond配置失败,或者关机脚本中途卡死,BMC总能立刻把机器拉掉。但它不太适合做精细的定时任务,因为BMC通常不提供本地cron,想定时还得靠外部脚本去调BMC接口,配置成本反而更高。
2.2 为什么常规场景下我会首选crond
把四条路摆在台面上后,答案其实很清楚了。如果你只是单台ESXi 7.0,没有vCenter,也不想折腾管理机,那ESXi原生crond几乎是唯一既轻量又可靠的选择。它不需要网络上的第三方依赖,不需要额外花钱,不依赖任何一台常开电脑。只要ESXi自己能启动crond服务、能读取crontab、关机脚本路径放对了,到点必然触发。作为一个运维老手,我特别偏爱这种"把逻辑放在系统内部"的做法,因为外部依赖越少,排错的时候就越省心。哪怕你的环境已经上有vCenter,我仍然建议在每台ESXi上保留crond兜底任务,作为vCenter计划任务失效时的最后防线。
3. 关机原语拆解:esxcli system shutdown poweroff到底做了什么
定时关机的核心,是关机动作本身。ESXi 7.0的命令行关机入口主要有两个:一个是我们已经提到的esxcli system shutdown poweroff,另一个是针对虚拟机的vim-cmd vmsvc/power.shutdown。这两个命令一字之差,行为完全不同,必须先分开讲。
3.1 命令参数与行为说明
esxcli system shutdown poweroff是ESXi主机级的关机命令。完整格式是:
esxcli system shutdown poweroff -d 10 -r "scheduled poweroff"-d参数是延迟执行的秒数,范围从0到86400。为什么要延迟?因为直接延迟几秒会给当前正在运行的进程和虚拟机一个缓冲时间,尤其当你通过SSH远程执行时,你总不想让命令一敲下去自己就断线吧。-r参数是关机原因,这个字符串会写进系统日志,方便事后追溯。还有一个对应的重启命令:
esxcli system shutdown reboot -d 30 -r "reboot after maintenance"如果只执行esxcli system shutdown poweroff不管虚拟机,会发生什么?这取决于ESXi上配置的"虚拟机启动/关闭"策略。在vSphere Client中,你可以进入主机配置的"虚拟机启动/关闭"里,设置ESXi关机时是否向运行中的虚拟机发送优雅关机信号。如果没配置过,ESXi默认直接断电,虚拟机里的数据可能还没来得及落盘,Windows虚拟机还可能出现系统损坏。所以我们要么提前配置好那些策略,要么在关机脚本里先主动优雅关闭所有虚拟机。
3.2 虚拟机优雅关机与强制断电的取舍
涉及虚拟机自身,常用的命令是vim-cmd vmsvc。先获取所有虚拟机的列表和VMID:
vim-cmd vmsvc/getallvms输出里第一列就是VMID,后面是名称和数据存储路径。拿到VMID后,可以用vim-cmd vmsvc/power.shutdown <VMID>优雅关闭它。这个命令会调用虚拟机内的VMware Tools,向Guest OS发出标准关机信号,相当于你手动去操作系统里点了"关机",Windows和Linux都能正常保存状态。但如果虚拟机没有安装VMware Tools,系统收不到信号,这个优雅关机就会失败,虚拟机一直保持Power On状态。
备选方案是vim-cmd vmsvc/power.off <VMID>,直接强制断电。区别类似于"你点了一下系统关机菜单"和"你直接拔了电源线"。生产环境能不用强制断电就不用,但万一有虚拟机死活不关,定时关机脚本总得有个最后的兜底动作,否则主机永远等不到关机时机。
3.3 一个可直接套用的关机脚本
我把上面这些思路整合成了一个实用脚本,你可以在ESXi上直接使用。脚本做的事情是:先遍历所有虚拟机,逐个触发优雅关机;然后每5秒检查一次,最多等120秒,等所有虚拟机都Power off后跳出检查循环;最后延迟30秒关闭主机。为了防止某个虚拟机始终关不掉拖死整个关机流程,我特意设计成"等待超时也继续往下走",因为定时关机场景下,主机比虚拟机更优先。
#!/bin/sh export PATH=/sbin:/bin:/usr/sbin:/usr/bin # 关闭所有虚拟机 for vmid in $(vim-cmd vmsvc/getallvms | awk 'NR>1{print $1}') do state=$(vim-cmd vmsvc/power.getstate "$vmid" 2>/dev/null | grep -i "Powered on") if [ -n "$state" ]; then vim-cmd vmsvc/power.shutdown "$vmid" fi done # 等待最多120秒,确认虚拟机全部关机 i=0 while [ $i -lt 24 ] do sleep 5 i=$((i+1)) still_running=0 for vmid in $(vim-cmd vmsvc/getallvms | awk 'NR>1{print $1}') do state=$(vim-cmd vmsvc/power.getstate "$vmid" 2>/dev/null | grep -i "Powered on") if [ -n "$state" ]; then still_running=1 break fi done if [ "$still_running" -eq 0 ]; then break fi done # 延迟30秒后关闭主机 esxcli system shutdown poweroff -d 30 -r "scheduled poweroff by crontab"这个脚本在ESXi 7.0上实测可用。要注意的是,脚本开头必须写export PATH,因为crond执行脚本时的PATH环境变量极其精简,不主动声明的话,awk、grep、vim-cmd这些命令可能找不到。另外,脚本应该放在持久化数据存储如/vmfs/volumes/datastore1/scripts/下,而不是放在/tmp或/root这种临时目录。
4. 原生crond定时关机完整落地:SSH、crontab与持久化
现在进入操作核心:把上面的关机脚本挂到ESXi自带的crond上。整个落地过程分五步,每一步都有要注意的细节。
4.1 开启SSH并确认crond守候进程
第一步,开启SSH服务。ESXi 7.0默认不开放SSH,需要手动启用。可以在vSphere Client的"主机->配置->服务"里找到SSH,点击"启动",同时把"与其他主机一起启动/停止"打开,这样ESXi重启后SSH会自动随系统启动。也可以在DCUI界面按F2进入系统定制,找到Troubleshooting Options开启SSH。如果在Web界面不方便,直接用命令行:
vim-cmd hostsvc/enable_ssh vim-cmd hostsvc/start_ssh第二步,SSH登录后确认crond服务状态。很多时候定时任务不执行,根因就是crond压根没起来。检查命令:
/etc/init.d/crond status chkconfig --list | grep crond如果服务没跑,启动它并设置开机自启:
/etc/init.d/crond start chkconfig crond on这步虽然简单,但实在太容易被跳过了。ESXi的一些精简镜像里crond可能不是默认自启的,你不确认就直接写crontab,到点自然没有反应。
4.2 写入定时任务:crontab语法与路径规划
第三步,编辑root用户的crontab表。ESXi上直接执行:
crontab -e进入的是BusyBox自带的vi编辑器,操作方法和Linux上的vi基本一致。我习惯用EDITOR=vi crontab -e指定编辑器。往里写入这样一行:
30 23 * * * /bin/sh /vmfs/volumes/datastore1/scripts/esxi-poweroff.sh >> /vmfs/volumes/datastore1/scripts/poweroff.log 2>&1这一行表示每天23点30分执行关机脚本,并把标准输出和标准错误都追加到日志文件。cron的五个字段依次是分、时、日、月、周,和Linux完全一致。如果你想工作日关机,可以写30 23 * * 1-5;只留周日跑,就写30 23 * * 0。
保存退出后,用crontab -l确认任务已经写入。还有一点值得注意:cron触发时会使用root身份,所以不需要担心权限问题,但正因为是root,关机脚本一旦写错后果也更严重。
4.3 验证任务与持久化策略
第四步,验证。我强烈建议不要直接等第二天看结果,而是先手动执行一遍关机脚本,但把脚本里真正关主机的esxcli system shutdown poweroff那行注释掉,先验证"关闭虚拟机+等待"的逻辑是否正常。确认虚拟机都能正常关闭后,再放开关机命令,并把cron触发时间临时改成两分钟后,做一次完整的定时触发测试。测试通过后,再改回真实计划时间。
第五步,也是最容易翻车的持久化问题。ESXi的根文件系统本质是只读的,运行时修改会落在内存叠加层里。这就让很多人担心crontab -e写入的任务会不会重启后消失。根据实际测试,ESXi 7.0的crontab表项会持久化到配置分区,重启后依然保留,我验证过多次。但为了万无一失,每次重启后我都建议执行一次crontab -l检查。如果真的要额外加固,可以把重建crontab的命令写进/etc/rc.local:
#!/bin/sh echo '30 23 * * * /bin/sh /vmfs/volumes/datastore1/scripts/esxi-poweroff.sh >> /vmfs/volumes/datastore1/scripts/poweroff.log 2>&1' | crontab -这样ESXi每次开机都会自动重建定时任务,相当于上了一道双保险。/etc/rc.local本身在ESXi 7.0中是持久化配置文件的一部分,修改后会保留。
5. 踩坑实录:定时关机没触发的排查链路
定时任务最让人头疼的就是"到点没反应"。我在这上面翻过车,也给不少朋友排过,把最常见的问题按排查链路整理出来。
5.1 第一道坎:系统时区与NTP同步
第一个要排查的是系统时间和时区。cron按系统时钟触发,系统时间不对,任务必然错乱。ESXi默认可能没有配置NTP,时间会越走越偏;更隐蔽的是时区问题。ESXi默认的时区可能是UTC,如果你在中国,期望的本地时间23:30触发,系统却认为23:30是UTC时间,那就是第二天早上7:30了。
先用这两条命令确认:
esxcli system time get esxcli system timezone get如果时区不对,改成Asia/Shanghai:
esxcli system timezone set -z "Asia/Shanghai"然后配置NTP并启动同步:
esxcli system ntp set --server=ntp.aliyun.com esxcli system ntp start配置完再用esxcli system time get确认时间已经正确。这一步极其关键,很多"定时关机没执行"的案例,查到最后都是时区差几个小时。
5.2 crond服务状态与crontab表丢失
第二道坎,crond服务状态和crontab表内容。ESXi重启后,crond服务可能没有自启,或者crontab表项意外丢失。排查时依次看:
/etc/init.d/crond status crontab -l如果服务没起来,按上一节的方法启动并设自启;如果表项丢了,重新写入或依赖/etc/rc.local自动重建。我见过不少人在ESXi断电重启后,发现之前配的crontab消失了,就是因为底层的持久化分区出了问题,或是在升级ESXi时配置被重置。所以排查时别想当然,一定要实际看一眼。
5.3 cron环境变量差异与日志取证
第三道坎,cron环境与交互终端环境的差异。你在SSH里手动执行脚本好好的,挂在cron里却报错,大概率是环境变量问题。cron任务执行时PATH非常精简,不主动声明就可能找不到命令。这也是我在开头脚本里写export PATH=/sbin:/bin:/usr/sbin:/usr/bin的原因。此外,脚本里所有依赖相对路径的操作都要改成绝对路径,特别是日志文件、脚本自身路径。
排查问题时,日志是最好的证人。ESXi上cron任务的执行记录可以从/var/log/cron里看,关机相关动作看/var/log/syslog和/vmkernel.log。常用取证命令:
grep "poweroff" /var/log/syslog grep "cron" /var/log/cron | tail -20如果cron执行了但关机失败,日志里会留下明确报错;如果cron连触发的痕迹都没有,那就要回到时间和服务状态上找原因。
5.4 一次真实故障复盘
分享一个现实里的排查过程。有个朋友的实验室给ESXi 7.0配了每天早上凌晨1点自动关机,结果第二天发现机器晚上没关,直到当天上午9点左右才自己关掉。他还是第二天到实验室看到的,整个人一脸懵。
我让他先做两件事:第一,esxcli system time get看系统时间;第二,grep cron /var/log/cron | tail -20看cron日志。结果发现,ESXi系统时区是UTC,系统时间为UTC 01:00时确实执行了关机脚本,但换算成北京时间就是上午9:00。他在配置时按本地时间写cron,却忘了ESXi默认使用UTC,所以时间整整差了8小时。我们把时区改成Asia/Shanghai、配置好NTP之后,第二天凌晨1点关机就完全正常了。这个案例也印证了5.1节的重要性——时间与时区问题,是ESXi定时任务故障里最高频的原因,没有之一。
6. 有vCenter时的进阶玩法:Scheduled Task与PowerCLI自动化
如果你的ESXi环境不止一台,还部署了vCenter,那我建议再往上走一层,把定时关机纳入统一管理。毕竟在每台ESXi上配一遍crond虽然可靠,但管理和审计都不够便捷。
6.1 vCenter计划任务配置步骤与局限
vCenter的Scheduled Task是个正经的GUI功能。登录vSphere Client,在主机和集群界面选中要关机的ESXi主机,进入"配置"页签,找到"计划任务",新建一个。向导里会要求选任务类型,选择"电源"或"电源操作",再设定具体的执行时间,比如每天23:30,然后指定操作是"关闭"还是"重新引导"。保存后,vCenter会在指定时间自动调用API执行操作,在"近期任务"里能看到执行结果。
但要注意,vCenter计划任务只是"到点发指令",至于虚拟机的处理策略,依然取决于ESXi主机的"虚拟机启动/关闭"配置。如果你没有提前配置虚拟机关机策略,vCenter同样可能直接强制断电虚拟机。所以使用之前,我建议在主机配置里把"虚拟机启动/关闭"里的关机延迟调大,给Windows虚拟机足够时间优雅退出。vCenter计划任务还有一个局限,一旦vCenter本身不可用,任务就不执行。这也是为什么我始终强调要在每台ESXi上留一个crond兜底。
6.2 PowerCLI批量关机脚本与外部调度
PowerCLI方案适合想写更复杂编排的运维。你可以在任何一台Windows管理机上安装VMware PowerCLI模块,写一个脚本,先连到vCenter,查出来需要关机的所有主机,然后遍历执行关机。下面是一个最小示例:
Import-Module VMware.PowerCLI -ErrorAction Stop Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false Connect-VIServer -Server vc.example.local -User admin -Password 'P@ssw0rd' $targetHosts = @("esxi-01", "esxi-02") foreach ($hostName in $targetHosts) { $vmList = Get-VMHost -Name $hostName | Get-VM # 优雅关闭该主机下所有虚拟机 $vmList | Shutdown-VMGuest -Confirm:$false Wait-Tools -VM $vmList -TimeoutSeconds 120 -ErrorAction SilentlyContinue # 关闭主机 Shutdown-VMHost -Host $hostName -Force -Confirm:$false } Disconnect-VIServer -Server * -Confirm:$false然后用Windows的"任务计划程序"设定每天23:30调用:
powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\shutdown-esxi.ps1这套方案最大的优点是编排自由度高,你可以写"如果所有虚拟机都关不掉就发邮件",也可以写"这次只关指定标签的虚拟机"。不过要记住,PowerCLI脚本里如果直接暴露了管理员密码,生产环境是很危险的做法。建议改用vCenter的API Token或Windows凭据管理器,至少不要让明文密码出现在ps1文件里。而且这个方案依赖管理机在线,一旦管理机休眠,整个调度就断了。所以PowerCLI更适合作为补充和批处理工具,而不是唯一依赖。
最后说点自己的习惯
我在给真实环境落地ESXi定时关机时,一般会同时铺两条线:vCenter的Scheduled Task作为日常主入口,负责统一管理和审计;每台ESXi上的原生crond任务作为兜底层,保证即使vCenter或管理机出现问题,物理机到点也能自己关。两个方案互不冲突,反而互补。最后分享两个小习惯:第一,所有定时关机脚本统一放在/vmfs/volumes/datastore1/scripts/目录,日志也放同一个目录,方便集中查看;第二,每次部署前先在测试环境跑一次完整流程,确认"关机脚本能正常关闭虚拟机、crond能按时触发、ESXi关机后能正常重启"这三个关键点,再上生产。定时关机这个需求本身不复杂,但一旦漏掉其中一环,深夜被报警电话叫醒的滋味可不好受。