我想安排一个命令在Linux机器上重新启动后运行。 我知道如何做到这一点,所以每次重新启动后用@reboot
crontab项一致地运行命令,但是我只希望命令运行一次。 运行后,应该从要运行的命令队列中删除。 我基本上是在Windows世界中寻找一个相当于RunOnce的Linux。
万一重要:
$ 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
有没有一个简单的,脚本化的方式来做到这一点?
在你的crontab中创build一个@reboot
条目来运行一个名为/usr/local/bin/runonce
。
使用mkdir -p
创build一个名为/etc/local/runonce.d/ran
的目录结构。
按如下所示创build脚本/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
子目录,并附加到它的名字的date和时间。 你的syslog
也会有一个条目。
我非常感谢Dennis Williamson的回答 。 我想接受它作为这个问题的答案,因为它是优雅和简单的,但是:
我认为他的解决scheme将成为Linux发行版的开箱即用function。
话虽如此,我写了自己的脚本来完成与丹尼斯的解决scheme差不多的事情。 它不需要任何额外的设置步骤,也不需要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)"
如果发生拼写错误,可以使用-r标志从runonce队列中删除命令:
$ 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"
一些说明:
在/etc/rc5.d中用S99设置脚本,让它在运行后自行删除。
尽pipe我注意到你不能(至less在我testing过的RHEL 5上) at @reboot
或at reboot
,但是你可以at now + 2 minutes
,然后shutdown -r now
。
这并不要求您的系统运行时间超过2分钟。
虽然我希望'runonce'命令是标准套件,但是在你想要0设置的地方也许是有用的。
我觉得这个答案是最优雅的:
将脚本放在/etc/init.d/script
并用最后一行自我删除: rm $0
除非脚本是100%的失败certificate,可能明智地处理exception,以避免致命的错误循环..
我使用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
run-once
/etc/init.d/
chkconfig run-once on
系统启动时,脚本将运行一次,永远不会再运行。
也就是说,除非你想要,否则永远不会。 您始终可以使用chkconfig run-once on
命令重新启用该脚本。
我喜欢这个解决scheme,因为它在系统上放置了一个且只有一个文件,并且如果需要,可以重新发出一次运行命令。
创build例如/root/runonce.sh
:
#!/bin/bash #your command here sed -i '/runonce.sh/d' /etc/rc.local
添加到/etc/rc.local
:
/root/runonce.sh
在redhat和debian系统中,你可以通过/etc/rc.local来做到这一点,它是一种autoexec.bat。