Назад | Перейти на главную страницу

Linux: команда расписания для однократного запуска после перезагрузки (эквивалент RunOnce)

Я хотел бы запланировать выполнение команды после перезагрузки в Linux. Я знаю, как это сделать, поэтому команда стабильно запускается после каждой перезагрузки с @reboot crontab, но я хочу, чтобы команда запускалась только один раз. После запуска его следует удалить из очереди команд на запуск. По сути, я ищу Linux-эквивалент RunOnce в мире Windows.

В случае необходимости:

$ uname -a
Linux devbox 2.6.27.19-5-default #1 SMP 2009-02-28 04:40:21 +0100 x86_64 x86_64 x86_64 GNU/Linux
$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
$ cat /etc/SuSE-release
SUSE Linux Enterprise Server 11 (x86_64)
VERSION = 11
PATCHLEVEL = 0

Есть ли простой способ сделать это с помощью сценариев?

Создать @reboot запись в вашем crontab для запуска скрипта под названием /usr/local/bin/runonce.

Создайте структуру каталогов под названием /etc/local/runonce.d/ran с помощью mkdir -p.

Создать сценарий /usr/local/bin/runonce следующим образом:

#!/bin/sh
for file in /etc/local/runonce.d/*
do
    if [ ! -f "$file" ]
    then
        continue
    fi
    "$file"
    mv "$file" "/etc/local/runonce.d/ran/$file.$(date +%Y%m%dT%H%M%S)"
    logger -t runonce -p local3.info "$file"
done

Теперь поместите любой сценарий, который вы хотите запустить при следующей перезагрузке (только один раз), в каталог. /etc/local/runonce.d и chown и chmod +x это уместно. Как только он будет запущен, вы обнаружите, что он перемещен в ran подкаталог и дату и время, добавленные к его имени. Также будет запись в вашем syslog.

Я очень ценю усилия, вложенные в Ответ Денниса Уильямсона. Я хотел принять его как ответ на этот вопрос, однако он элегантен и прост:

  • В конце концов я почувствовал, что для настройки требуется слишком много шагов.
  • Требуется root-доступ.

Я думаю, что его решение было бы отличным как готовая функция дистрибутива Linux.

При этом я написал свой собственный сценарий, чтобы выполнить более или менее то же самое, что и решение Денниса. Он не требует никаких дополнительных действий по настройке и не требует root-доступа.

#!/bin/bash

if [[ $# -eq 0 ]]; then
    echo "Schedules a command to be run after the next reboot."
    echo "Usage: $(basename $0) <command>"
    echo "       $(basename $0) -p <path> <command>"
    echo "       $(basename $0) -r <command>"
else
    REMOVE=0
    COMMAND=${!#}
    SCRIPTPATH=$PATH

    while getopts ":r:p:" optionName; do
        case "$optionName" in
            r) REMOVE=1; COMMAND=$OPTARG;;
            p) SCRIPTPATH=$OPTARG;;
        esac
    done

    SCRIPT="${HOME}/.$(basename $0)_$(echo $COMMAND | sed 's/[^a-zA-Z0-9_]/_/g')"

    if [[ ! -f $SCRIPT ]]; then
        echo "PATH=$SCRIPTPATH" >> $SCRIPT
        echo "cd $(pwd)"        >> $SCRIPT
        echo "logger -t $(basename $0) -p local3.info \"COMMAND=$COMMAND ; USER=\$(whoami) ($(logname)) ; PWD=$(pwd) ; PATH=\$PATH\"" >> $SCRIPT
        echo "$COMMAND | logger -t $(basename $0) -p local3.info" >> $SCRIPT
        echo "$0 -r \"$(echo $COMMAND | sed 's/\"/\\\"/g')\""     >> $SCRIPT
        chmod +x $SCRIPT
    fi

    CRONTAB="${HOME}/.$(basename $0)_temp_crontab_$RANDOM"
    ENTRY="@reboot $SCRIPT"

    echo "$(crontab -l 2>/dev/null)" | grep -v "$ENTRY" | grep -v "^# DO NOT EDIT THIS FILE - edit the master and reinstall.$" | grep -v "^# ([^ ]* installed on [^)]*)$" | grep -v "^# (Cron version [^$]*\$[^$]*\$)$" > $CRONTAB

    if [[ $REMOVE -eq 0 ]]; then
        echo "$ENTRY" >> $CRONTAB
    fi

    crontab $CRONTAB
    rm $CRONTAB

    if [[ $REMOVE -ne 0 ]]; then
        rm $SCRIPT
    fi
fi

Сохраните этот скрипт (например: runonce), chmod +x, и запустите:

$ runonce foo
$ runonce "echo \"I'm up. I swear I'll never email you again.\" | mail -s \"Server's Up\" $(whoami)"

В случае опечатки вы можете удалить команду из очереди runonce с флагом -r:

$ runonce fop
$ runonce -r fop
$ runonce foo

Использование sudo работает так, как вы ожидаете. Полезно для однократного запуска сервера после следующей перезагрузки.

myuser@myhost:/home/myuser$ sudo runonce foo
myuser@myhost:/home/myuser$ sudo crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/root/.runonce_temp_crontab_10478 installed on Wed Jun  9 16:56:00 2010)
# (Cron version V5.0 -- $Id: crontab.c,v 1.12 2004/01/23 18:56:42 vixie Exp $)
@reboot /root/.runonce_foo
myuser@myhost:/home/myuser$ sudo cat /root/.runonce_foo
PATH=/usr/sbin:/bin:/usr/bin:/sbin
cd /home/myuser
foo
/home/myuser/bin/runonce -r "foo"

Некоторые примечания:

  • Этот скрипт реплицирует среду (ПУТЬ, рабочий каталог, пользователя), в которой он был вызван.
  • Он предназначен в основном для того, чтобы отложить выполнение команды, поскольку она будет выполняться «прямо здесь, прямо сейчас», до следующей последовательности загрузки.

Создать, например, /root/runonce.sh:

#!/bin/bash
#your command here
sed -i '/runonce.sh/d' /etc/rc.local

добавить в /etc/rc.local:

/root/runonce.sh

я использовал chkconfig чтобы моя система автоматически запускала сценарий один раз после загрузки и никогда больше. Если ваша система использует ckconfig (Fedora, RedHat, CentOs и т. Д.), Это сработает.

Сначала сценарий:

#!/bin/bash
# chkconfig: 345 99 10
# description: This script is designed to run once and then never again.
#


##
# Beginning of your custom one-time commands
#

plymouth-set-default-theme charge -R
dracut -f

#
# End of your custom one-time commands
##


##
# This script will run once
# If you would like to run it again.  run 'chkconfig run-once on' then reboot.
#
chkconfig run-once off
chkconfig --del run-once
  1. Назовите сценарий run-once
  2. Поместите сценарий в /etc/init.d/
  3. Включите скрипт chkconfig run-once on
  4. перезагрузка

Когда система загрузится, ваш скрипт запустится один раз и больше никогда.

То есть никогда больше, если вы этого не захотите. Вы всегда можете повторно включить скрипт с помощью chkconfig run-once on команда.

Мне нравится это решение, потому что оно помещает в систему один и только один файл, а также потому, что при необходимости команду run-once можно повторно запустить.

Настройте сценарий в /etc/rc5.d с S99 и удалите его после запуска.

Вы можете сделать это с помощью at , хотя я заметил, что вы не можете (по крайней мере, на RHEL 5, который я тестировал) использовать at @reboot или at reboot, но вы можете использовать at now + 2 minutes а потом shutdown -r now.

Для этого не требуется, чтобы ваша система работала более 2 минут.

Это может быть полезно, если вы хотите установить 0, хотя я бы предпочел, чтобы команда runonce была стандартным комплектом.

думаю этот ответ самый элегантный:

Поместите скрипт в /etc/init.d/script и самоудаление с последней строкой: rm $0

Если сценарий не является на 100% отказоустойчивым, вероятно, разумно обработать исключения, чтобы избежать цикла фатальных ошибок.

в системах redhat и debian это можно сделать из /etc/rc.local, это своего рода autoexec.bat.