Naprawdę doceniam wysiłek włożony w odpowiedź Dennisa Williamsona . Chciałem zaakceptować to jako odpowiedź na to pytanie, ponieważ jest ono eleganckie i proste:
- W końcu czułem, że wymagało to zbyt wielu kroków.
- Wymaga dostępu do roota.
Myślę, że jego rozwiązanie byłoby świetne jako gotowa funkcja dystrybucji Linuksa.
To powiedziawszy, napisałem własny skrypt, aby osiągnąć mniej więcej to samo, co rozwiązanie Dennisa. Nie wymaga żadnych dodatkowych kroków konfiguracji i nie wymaga dostępu do konta 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
Zapisz ten skrypt (np runonce
), chmod +x
i wykonaj:
$ runonce foo
$ runonce "echo \"I'm up. I swear I'll never email you again.\" | mail -s \"Server's Up\" $(whoami)"
W przypadku literówki możesz usunąć polecenie z kolejki uruchamiania za pomocą opcji -r:
$ runonce fop
$ runonce -r fop
$ runonce foo
Korzystanie z sudo działa tak, jak byś tego oczekiwał. Przydatne do uruchomienia serwera tylko raz po następnym restarcie.
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"
Niektóre uwagi:
- Ten skrypt replikuje środowisko (PATH, katalog roboczy, użytkownik), w którym został wywołany.
- Został zaprojektowany tak, aby po prostu odroczyć wykonanie polecenia, ponieważ zostałoby ono wykonane „tu i teraz” aż do następnej sekwencji rozruchowej.