在crontab中运行脚本 - 找不到reboot命令

本文探讨了在rootcrontab中遇到'reboot: command not found'问题的解决方法,包括使用完整路径、设置PATH环境变量和在crontab中设置PATH,以确保脚本在默认PATH不足时能正确重启系统。

在root crontab中设置了一个脚本,该脚本应该用 reboot 命令重新启动我的机器 .

但是,尽管 reboot 在root用户的路径中,但我得到了 reboot: command not found .

$ sudo su
$ which reboot
/sbin/reboot
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/go/bin


cron作业以非常基本的环境设置运行;除其他外,默认PATH只是 /usr/bin:/bin . 它不使用用户的常规shell设置 . 有几种方法可以解决这个问题:

使用脚本中的完整路径(即 /sbin/reboot ) .

在使用 reboot (即 PATH=/usr/bin:/bin:/usr/sbin:/sbin )之前在脚本中设置PATH .

在脚本条目之前在crontab中设置PATH(语法与脚本中的相同) 

<think>我们面临的需求是:编写一个支持指定运行轮数的reboot脚本。即每次重启后计数,达到指定轮数后不再执行重启。思路:1.我们需要一个计数器来记录已经重启的次数。2.计数器需要持久化存储(因为重启后内存数据会丢失),所以考虑将计数器存储在文件中(比如在根目录下创建一个文件`/reboot_counter`)。3.在每次重启时,脚本自动运行,读取计数器文件中的当前值,然后判断是否达到指定的轮数。如果未达到,则计数器加1,并重新写入文件,然后执行重启。如果已达到,则不再重启,并可能执行一些清理操作(比如删除计数器文件)或输出提示信息。然而,需要注意的是:这个脚本的执行时机。如果脚本是作为启动脚本的一部分,那么它将在每次启动时运行。但我们希望它在每次重启前计数,并在达到轮数后不再重启。因此,我们可能需要将重启操作也集成到脚本中,而不是直接使用系统的重启命令。但用户要求的是“reboot脚本”,通常是指用于执行重启的脚本。所以我们可以这样设计:方案A:将计数和重启操作放在同一个脚本中(比如叫做`controlled_reboot.sh`)。当我们运行这个脚本时,它会检查计数器,如果未达到指定轮数,则执行重启;否则不重启。但是这样有一个问题:我们如何保证在系统启动时自动增加计数器?因为重启是由这个脚本触发的,那么重启后计数器应该由启动脚本更新。所以我们需要两个脚本:1.一个启动脚本(在系统启动时运行),用于更新计数器(读取当前值,如果小于指定轮数则加1,并写入文件)。2.一个重启控制脚本(由用户手动执行或由其他程序调用),用于检查当前计数器值,如果未达到指定轮数,则调用系统reboot命令;否则不执行重启。然而,这样设计的话,启动脚本只负责更新计数器,而重启控制脚本只负责判断是否重启。但是注意:当系统启动时,启动脚本更新计数器,此时计数器已经表示本次启动是第几次。而重启控制脚本在调用重启前,需要知道当前计数器的值(即已经启动了多少次),然后判断是否还要继续重启。具体步骤:1.创建计数器文件,初始值为0(表示尚未开始计数)。2.编写启动脚本(在系统启动时运行):-读取计数器文件中的值(假设为n)。-如果n小于指定的总轮数(比如N),则将计数器加1(变成n+1)并写入文件。-如果n已经大于等于N,则不再更新(或者可以重置为0,取决于需求)。-注意:如果计数器文件不存在,则创建并写入0(第一次启动时)。3.编写重启控制脚本(controlled_reboot.sh):-读取计数器文件中的当前值n。-如果n<N,则执行`reboot`命令-否则,提示用户已达到指定轮数,不再重启。但是,这有一个问题:启动脚本在每次启动时都会将计数器加1,那么当第一次启动时,计数器变为1;然后我们运行重启控制脚本,它发现1<5(假设总轮数为5),于是重启。系统重启后,启动脚本再次运行,计数器变为2,然后我们又运行重启控制脚本,它再次重启...直到第5次启动后,启动脚本将计数器更新为5,然后当我们运行重启控制脚本时,它发现5>=5,于是不再重启。然而,这个设计存在一个缺陷:启动脚本在每次启动时都会增加计数器,包括我们最后一次启动(即达到轮数后的启动)也会增加。所以实际上,计数器在第一次启动后为1,第二次启动后为2,...,第五次启动后为5。当第五次启动后,我们运行重启控制脚本,它看到5已经达到5,所以不重启。这符合要求。但是,如果我们希望从0开始计数(即第一次启动时计数器为0,然后第一次重启后启动时计数器为1,直到第N-1次重启后启动时计数器为N-1,然后第N次重启控制脚本运行时,发现当前计数器为N-1,于是重启,然后启动脚本将计数器更新为N,这时已经达到轮数,下一次就不会再重启了)?这样就需要在重启控制脚本中判断:当前计数器值(即上一次启动脚本运行后的值)是否小于N-1?因为下一次启动后计数器会加1,所以当前计数器为k,表示已经重启了k次(因为第一次启动后计数器为0,然后每次启动脚本加1,所以第k次启动后计数器为k-1,第k次重启后启动时计数器变为k)。这样理解有些混乱。为了简化,我们这样定义:-计数器记录的是已经启动的次数(即每次启动脚本运行时,计数器加1)。-重启控制脚本要执行重启的条件是:当前计数器的值(即已经启动的次数)小于指定的总轮数(N)。因为如果已经启动了N次,那么就不需要再重启了。注意:我们要求的总重启轮数实际上是N-1次(因为第一次启动不算重启,然后重启一次就是第二次启动,所以重启N-1次,就会产生N次启动)。但用户可能希望指定的是重启的次数(比如重启5次,那么总共启动6次)。所以我们需要明确:用户指定的是重启次数还是启动次数?根据问题:“运行轮数”,应该是指重启的次数。例如,我们希望系统重启5次,那么第6次启动后就不再重启。因此,我们调整:-指定重启次数为R,那么总启动次数为R+1(第一次启动不算重启,然后每次重启增加一次启动)。-启动脚本在每次启动时更新计数器(计数器值=启动次数-1,因为第一次启动时计数器为0,然后每次启动加1,那么第k次启动时计数器为k-1)。-重启控制脚本判断:如果当前计数器值(即启动次数-1)小于R,则执行重启(因为当前启动次数-1就是已经重启的次数,如果小于R,说明还要继续重启)。-注意:在启动脚本中,我们更新计数器:读取计数器文件,如果值小于R,则加1(因为每次启动都要更新,表示下一次重启前已经启动的次数)。但是,当计数器达到R时,说明已经完成了R次重启(即已经启动了R+1次),那么启动脚本就不再更新计数器(或者重置?)。然而,启动脚本的更新逻辑应该是:无论当前计数器是多少,只要小于R(即重启次数),就加1?这样不对,因为第一次启动时计数器是0(表示重启0次),启动脚本将其加1变成1(表示重启1次),但此时系统已经启动了一次(即第一次启动),然后我们运行重启控制脚本,它判断当前计数器1小于R(假设R=5),于是重启。重启后第二次启动,启动脚本读取计数器(1),然后加1变成2(表示重启2次),然后运行重启控制脚本,它判断2<5,于是重启...直到第五次重启后启动,启动脚本将计数器从4加1变成5(表示已经重启5次),然后重启控制脚本判断5>=5,不再重启。这样,启动脚本在计数器小于R时都会加1,那么计数器最终会达到R(即我们想要的重启次数)。注意:第一次启动后计数器被更新为1(表示已经重启1次?但实际上这是第一次启动,还没有执行重启操作)。所以这逻辑有误。重新梳理:我们希望实现:用户指定重启次数R(即系统重启R次,然后停止重启)。步骤:1.第一次启动(冷启动或手动启动):此时计数器应该为0(表示尚未重启过)。2.在第一次启动后,如果我们运行重启控制脚本,它检查当前计数器0<R(假设R>0),于是执行重启(这是第一次重启)。3.系统重启后(第二次启动),启动脚本运行,它读取计数器(0),然后将其更新为1(表示已经重启1次),并保存。4.然后,在第二次启动后,我们运行重启控制脚本,它检查当前计数器1<R(假设R>1),于是再次重启(第二次重启)。5.系统重启后(第三次启动),启动脚本更新计数器为2。6.如此循环,直到第R次重启后启动(第R+1次启动),启动脚本将计数器更新为R(表示已经重启R次)。7.然后,当我们再次运行重启控制脚本时,它检查计数器R>=R,于是不再重启。注意:启动脚本在每次启动时都会更新计数器(加1),直到计数器达到R。所以启动脚本的更新逻辑应该是:if[$current_counter-lt$R];thennew_counter=$((current_counter+1))将new_counter写入文件fi这样,当计数器达到R后,启动脚本就不再更新计数器(保持为R)。因此,我们需要两个参数:-总重启次数R(由用户指定)-计数器文件(记录当前已经重启的次数)具体实现:1.启动脚本(update_reboot_counter.sh):#!/bin/bashR=5#用户指定的重启次数COUNTER_FILE="/root/reboot_counter"#如果计数器文件不存在,则创建并写入0if[!-f"$COUNTER_FILE"];thenecho"0">"$COUNTER_FILE"fi#读取当前计数器的值current_counter=$(cat"$COUNTER_FILE")#如果当前计数器小于R,则加1并写入文件if["$current_counter"-lt"$R"];thennew_counter=$((current_counter+1))echo"$new_counter">"$COUNTER_FILE"fi2.重启控制脚本(controlled_reboot.sh):#!/bin/bashR=5#用户指定的重启次数COUNTER_FILE="/root/reboot_counter"#读取当前计数器的值if[!-f"$COUNTER_FILE"];thencurrent_counter=0elsecurrent_counter=$(cat"$COUNTER_FILE")fi#判断是否重启if["$current_counter"-lt"$R"];thenecho"Rebootingnow(currentcycle:$current_counter,target:$R)..."reboot#需要root权限elseecho"Targetrebootcycles($R)reached.Nofurtherreboot."fi注意:两个脚本中的R值必须相同。为了便于维护,可以将R定义在一个配置文件中,或者使用命令行参数。但是,启动脚本在每次启动时都会运行,所以它会在每次启动时更新计数器(只要计数器小于R)。而重启控制脚本需要由用户手动运行(或者由定时任务等触发),它负责检查并执行重启。如何设置启动脚本在系统启动时自动运行?根据引用的资料,我们可以将启动脚本设置为系统服务(方法一)或者添加到rc.local(方法二)或者使用crontab(方法三)?注意:启动脚本(update_reboot_counter.sh)只需要在启动时运行一次(在启动过程的某个阶段),所以我们可以使用systemd服务或者rc.local。这我们使用rc.local(简单):1.将update_reboot_counter.sh脚本放在一个固定的位置(比如/usr/local/bin/update_reboot_counter.sh)2.赋予可执行权限:chmod+x/usr/local/bin/update_reboot_counter.sh3.编辑/etc/rc.local文件,在exit0之前添加一行:/usr/local/bin/update_reboot_counter.sh这样,每次启动时都会运行这个脚本。另外,重启控制脚本(controlled_reboot.sh)也需要放在一个位置(比如/usr/local/bin/controlled_reboot.sh),并赋予可执行权限。然后用户就可以在需要重启时运行这个脚本(需要root权限)。测试:1.设置R=2(重启2次)。2.第一次启动(计数器文件不存在,启动脚本创建并写入0,然后因为0<2,所以更新为1)。3.然后运行controlled_reboot.sh:它读取到计数器为1(1<2),于是重启。4.系统重启(第二次启动):启动脚本读取计数器为1,因为1<2,所以更新为2。5.运行controlled_reboot.sh:读取计数器为2(不小于2),所以不重启。6.再次运行controlled_reboot.sh,仍然不重启。注意:如果用户希望重置计数器,可以删除计数器文件(/root/reboot_counter),然后重新开始计数。另外,我们也可以修改启动脚本,在计数器达到R后不再更新,那么以后每次启动都不会再更新。这样计数器文件会一直保留。如果我们希望重新开始计数,需要手动删除计数器文件。改进:在启动脚本中,当计数器达到R后,我们可以选择删除计数器文件或者重置为0?这取决于需求。如果希望循环执行(即完成R次重启后,再从头开始),那么可以重置为0。但问题要求“支持指定运行轮数”,所以完成指定轮数后停止,因此我们不重置。安全考虑:启动脚本和重启控制脚本都需要root权限。编写脚本:启动脚本(update_reboot_counter.sh):```bash#!/bin/bash#这个脚本在每次启动时运行,更新重启计数器#指定总重启次数(这设为5,用户可以根据需要修改)R=5COUNTER_FILE="/root/reboot_counter"#如果计数器文件不存在,则创建并写入0if[!-f"$COUNTER_FILE"];thenecho"0">"$COUNTER_FILE"fi#读取当前计数器的值current_counter=$(cat"$COUNTER_FILE")#如果当前计数器小于R,则加1并写入文件if["$current_counter"-lt"$R"];thennew_counter=$((current_counter+1))echo"$new_counter">"$COUNTER_FILE"fi```重启控制脚本(controlled_reboot.sh):```bash#!/bin/bash#这个脚本由用户执行,用于在未达到重启轮数时重启系统#指定总重启次数(必须和update_reboot_counter.sh中的R相同)R=5COUNTER_FILE="/root/reboot_counter"#如果计数器文件不存在,则当前计数器设为0if[!-f"$COUNTER_FILE"];thencurrent_counter=0elsecurrent_counter=$(cat"$COUNTER_FILE")fi#判断是否重启if["$current_counter"-lt"$R"];thenecho"Rebootingnow(currentcycle:$current_counter,target:$R)..."reboot#执行重启命令,需要root权限elseecho"Targetrebootcycles($R)reached.Nofurtherreboot."fi```设置启动脚本自动运行(使用rc.local):1.将update_reboot_counter.sh复制到/usr/local/bin/,并设置权限:sudocpupdate_reboot_counter.sh/usr/local/bin/sudochmod+x/usr/local/bin/update_reboot_counter.sh2.编辑/etc/rc.local文件(可能需要先赋予执行权限,有些系统需要):sudonano/etc/rc.local在文件末尾(exit0之前)添加:/usr/local/bin/update_reboot_counter.sh3.保存并退出。4.确保/etc/rc.local有执行权限:sudochmod+x/etc/rc.local注意:在一些新版的Ubuntu中,rc.local服务默认不启用,需要手动启用。具体步骤可以参考引用[1]中关于rc.local的部分。另外,重启控制脚本(controlled_reboot.sh)也需要放到合适的位置,例如:sudocpcontrolled_reboot.sh/usr/local/bin/sudochmod+x/usr/local/bin/controlled_reboot.sh这样,用户就可以在终端中执行:sudocontrolled_reboot.sh来触发重启(在未达到轮数时)。重要:两个脚本中的R值必须相同,且需要用户手动修改脚本中的R值。为了更方便,我们可以将R值提取到一个配置文件中,两个脚本都读取同一个配置文件。例如,创建配置文件/etc/reboot_cycle.conf,内容为:R=5然后修改两个脚本,在脚本中读取这个配置文件:source/etc/reboot_cycle.conf这样,用户只需要修改配置文件即可。改进后的启动脚本(update_reboot_counter.sh):```bash#!/bin/bash#读取配置文件CONFIG_FILE="/etc/reboot_cycle.conf"if[-f"$CONFIG_FILE"];thensource"$CONFIG_FILE"elseecho"Error:Configurationfile$CONFIG_FILEnotfound.">&2exit1fiCOUNTER_FILE="/root/reboot_counter"#如果计数器文件不存在,则创建并写入0if[!-f"$COUNTER_FILE"];thenecho"0">"$COUNTER_FILE"ficurrent_counter=$(cat"$COUNTER_FILE")if["$current_counter"-lt"$R"];thennew_counter=$((current_counter+1))echo"$new_counter">"$COUNTER_FILE"fi```改进后的重启控制脚本(controlled_reboot.sh):```bash#!/bin/bash#读取配置文件CONFIG_FILE="/etc/reboot_cycle.conf"if[-f"$CONFIG_FILE"];thensource"$CONFIG_FILE"elseecho"Error:Configurationfile$CONFIG_FILEnotfound.">&2exit1fiCOUNTER_FILE="/root/reboot_counter"if[!-f"$COUNTER_FILE"];thencurrent_counter=0elsecurrent_counter=$(cat"$COUNTER_FILE")fiif["$current_counter"-lt"$R"];thenecho"Rebootingnow(currentcycle:$current_counter,target:$R)..."rebootelseecho"Targetrebootcycles($R)reached.Nofurtherreboot."fi```这样,用户只需要编辑/etc/reboot_cycle.conf文件来修改R值。注意:这些操作都需要root权限。最后,提醒用户:这个重启控制脚本只能由root用户执行(因为它调用了reboot命令),所以使用sudo运行。总结:1.创建配置文件/etc/reboot_cycle.conf,设置R=5(或其他数值)。2.创建两个脚本(update_reboot_counter.sh和controlled_reboot.sh),并分别放到/usr/local/bin/,赋予可执行权限。3.设置update_reboot_counter.sh在启动时自动运行(通过rc.local)。4.当需要重启时,运行sudocontrolled_reboot.sh。这样,系统将在每次运行controlled_reboot.sh时检查重启次数,未达到指定轮数则重启,并在重启后由启动脚本更新计数器。注意事项:-确保rc.local服务已启用。-在测试时,可以先将R设为一个较小的值,并注意备份数据,以防频繁重启造成损失。-如果希望自动触发重启(比如定时重启),可以将controlled_reboot.sh加入crontab(使用root用户),但是要谨慎使用。引用说明:我们参考了rc.local的方法来设置启动时运行脚本(引用[1]和引用[2]中提到了rc.local)。引用[3]提到了crontab,但这我们不需要定时,而是手动触发重启。根据用户需求,我们生成了一个支持指定运行轮数的reboot脚本实现方法。相关问题:1.如何设置系统启动时自动运行脚本(除了rc.local还有哪些方法)?2.如何让脚本在每次重启后执行,而不是启动后执行?3.如何防止脚本重复运行(例如,在启动脚本中加锁)?</think>### 支持指定运行轮数的 Reboot 脚本实现方法 要编写一个支持指定运行轮数的 reboot 脚本,可通过以下步骤实现: #### 核心思路 1. **使用计数器文件**:在持久化存储中保存重启计数 2. **启动服务更新计数**:每次系统启动时自动增加计数器 3. **条件重启逻辑**:当计数未达指定轮数时执行重启 #### 完整实现方案 ##### 1. 创建计数器管理脚本 ```bash #!/bin/bash # /usr/local/bin/reboot_counter.sh CONFIG_FILE="/etc/reboot_cycle.conf" COUNTER_FILE="/var/lib/reboot_counter" # 读取配置 source "$CONFIG_FILE" 2>/dev/null # 初始化计数器 [ ! -f "$COUNTER_FILE" ] && echo 0 > "$COUNTER_FILE" current_count=$(cat "$COUNTER_FILE") # 检查是否达到最大轮数 if [ "$current_count" -ge "$MAX_CYCLES" ]; then echo "已达到最大重启轮数($MAX_CYCLES),停止计数" exit 0 fi # 更新计数器 new_count=$((current_count + 1)) echo "$new_count" > "$COUNTER_FILE" echo "更新重启计数器: $current_count → $new_count" ``` ##### 2. 创建配置文件 ```bash # /etc/reboot_cycle.conf # 设置最大重启轮数(修改此值即可调整轮数) MAX_CYCLES=5 ``` ##### 3. 创建重启控制脚本 ```bash #!/bin/bash # /usr/local/bin/controlled_reboot.sh CONFIG_FILE="/etc/reboot_cycle.conf" COUNTER_FILE="/var/lib/reboot_counter" [ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE" current_count=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0) if [ "$current_count" -lt "$MAX_CYCLES" ]; then echo "第 $((current_count+1)) 次重启 (共 $MAX_CYCLES 轮)" sleep 2 sudo reboot else echo "已完成 $MAX_CYCLES 轮重启,不再执行" fi ``` ##### 4. 设置系统服务自动计数 ```bash # /etc/systemd/system/reboot-counter.service [Unit] Description=Reboot Cycle Counter After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/reboot_counter.sh [Install] WantedBy=multi-user.target ``` ##### 5. 配置与启用步骤 ```bash # 设置文件权限 sudo chmod 755 /usr/local/bin/reboot_counter.sh sudo chmod 755 /usr/local/bin/controlled_reboot.sh sudo chmod 644 /etc/reboot_cycle.conf # 初始化计数器 echo 0 | sudo tee /var/lib/reboot_counter >/dev/null # 启用系统服务 sudo systemctl daemon-reload sudo systemctl enable reboot-counter.service sudo systemctl start reboot-counter.service ``` #### 使用说明 1. **修改重启轮数**:编辑 `/etc/reboot_cycle.conf` 中的 `MAX_CYCLES` 值 2. **执行重启**:运行 `sudo /usr/local/bin/controlled_reboot.sh` 3. **查看当前计数**:`cat /var/lib/reboot_counter` 4. **重置计数器**:`echo 0 | sudo tee /var/lib/reboot_counter` #### 工作原理 1. 每次系统启动时,`reboot-counter.service` 自动执行计数脚本 2. 脚本读取 `/var/lib/reboot_counter` 中的当前值 3. 若未达最大轮数则增加计数并保存 4. 当用户执行 `controlled_reboot.sh` 时: - 检查当前计数 - 未达上限 → 执行重启 - 已达上限 → 停止重启 #### 注意事项 1. 需要 root 权限执行重启脚本 2. 计数器文件存储在持久化位置确保重启后不丢失 3. 可通过 `systemctl status reboot-counter.service` 检查服务状态 4. 测试时建议先设置较小轮数值(如 2-3 次) > 此方案通过系统服务实现启动计数[^1],利用配置文件管理重启轮数[^2],结合条件判断控制重启行为[^3],满足精确控制重启次数的需求。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值