Linux: comando Schedule para executar uma vez após a reinicialização (equivalente a RunOnce)

21

Gostaria de programar um comando para ser executado após a reinicialização em uma caixa do Linux. Eu sei como fazer isso, então o comando é executado consistentemente após cada reinicialização com uma entrada @reboot crontab, no entanto, quero apenas que o comando seja executado uma vez. Depois de executado, ele deve ser removido da fila de comandos para ser executado. Eu estou essencialmente procurando por um Linux equivalente a RunOnce no Windows mundo.

Caso seja importante:

$ 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

Existe uma maneira fácil e programável de fazer isso?

    
por Christopher Parker 04.06.2010 / 21:46

8 respostas

20

Eu realmente aprecio o esforço colocado em Resposta de Dennis Williamson . Eu queria aceitar isso como a resposta a essa pergunta, pois é elegante e simples:

  • Em última análise, senti que exigia muitos passos para configurar.
  • Requer acesso root.

Acho que sua solução seria ótima como um recurso pronto para uso de uma distribuição Linux.

Dito isso, escrevi meu próprio roteiro para realizar mais ou menos a mesma coisa que a solução de Dennis. Não requer etapas adicionais de configuração e não requer acesso 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

Salve este script (por exemplo, runonce ), chmod +x e execute:

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

Em caso de erro de digitação, você pode remover um comando da fila de runonce com o sinalizador -r:

$ runonce fop
$ runonce -r fop
$ runonce foo

Usar o sudo funciona da maneira que você espera que funcione. Útil para iniciar um servidor apenas uma vez após a próxima reinicialização.

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"

Algumas notas:

  • Esse script replica o ambiente (PATH, diretório de trabalho, usuário) em que foi chamado.
  • Ele é projetado basicamente para adiar a execução de um comando, já que ele seria executado "aqui e agora" até depois da próxima seqüência de inicialização.
por 13.04.2017 / 14:14
35

Crie uma entrada @reboot no seu crontab para executar um script chamado /usr/local/bin/runonce .

Crie uma estrutura de diretório chamada /etc/local/runonce.d/ran usando mkdir -p .

Crie o script /usr/local/bin/runonce da seguinte forma:

#!/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

Agora, coloque qualquer script que você queira executar na próxima reinicialização (apenas uma vez) no diretório /etc/local/runonce.d e chown e chmod +x apropriadamente. Depois que ele for executado, você verá que ele foi movido para o subdiretório ran e a data e hora anexadas ao seu nome. Haverá também uma entrada no seu syslog .

    
por 04.06.2010 / 22:41
2

Configure o script em /etc/rc5.d com um S99 e faça com que ele seja excluído após a execução.

    
por 11.06.2010 / 03:35
2

Você pode fazer isso com o comando at , mas percebo que não é possível (pelo menos no RHEL 5, no qual testei) use at @reboot ou at reboot , mas você pode usar at now + 2 minutes e então shutdown -r now .

Isso não exige que o sistema demore mais de 2 minutos para ser executado.

Pode ser útil onde você deseja configurar 0, embora eu prefira que o comando 'runonce' seja um kit padrão.

    
por 15.05.2015 / 14:02
2

Eu acho que esta resposta é a mais elegante:

Coloque o script em /etc/init.d/script e auto-exclua com a última linha: rm $0

A menos que o script seja 100% à prova de falhas, provavelmente é bom lidar com exceções para evitar um loop de erro fatal.

    
por 04.09.2015 / 16:19
2

Criar, por exemplo, /root/runonce.sh :

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

Adicione a /etc/rc.local :

/root/runonce.sh
    
por 24.11.2010 / 10:06
1

Eu usei chkconfig para que meu sistema executasse automaticamente um script após a inicialização e nunca mais. Se o seu sistema usa ckconfig (Fedora, RedHat, CentOs, etc), isso funcionará.

Primeiro o script:

#!/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. Nomeie o script run-once
  2. Coloque o script em /etc/init.d/
  3. Ativar o script chkconfig run-once on
  4. reinicializar

Quando o sistema inicializar, seu script será executado uma vez e nunca mais.

Isto é, nunca mais, a menos que você queira. Você sempre pode reativar o script com o comando chkconfig run-once on .

Eu gosto dessa solução porque ela coloca um e apenas um arquivo no sistema e porque o comando run-once pode ser reemitido, se necessário.

    
por 29.04.2016 / 21:26
-1

nos sistemas redhat e debian, você pode fazer isso em /etc/rc.local, é um tipo de autoexec.bat.

    
por 05.06.2010 / 22:44