我想安排一個命令在 Linux 機器上重新啟動後運行。我知道該怎麼做所以命令每次重新啟動後始終運行帶有@reboot
crontab 條目,但我只想命令運行一次。運行後,應將其從要執行的命令佇列中刪除。我本質上是在尋找一個相當於運行一次在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
有沒有一種簡單的、可編寫腳本的方法來做到這一點?
答案1
@reboot
在 crontab 中建立一個條目來執行名為 的腳本/usr/local/bin/runonce
。
/etc/local/runonce.d/ran
建立一個名為using 的目錄結構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
.
答案2
我真的很感激所付出的努力丹尼斯威廉森的回答。我想接受它作為這個問題的答案,因為它優雅而簡單,但是:
- 我最終覺得它需要太多的步驟來設定。
- 它需要 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)"
如果出現拼字錯誤,您可以使用 -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"
一些注意事項:
- 該腳本複製它被呼叫的環境(路徑、工作目錄、使用者)。
- 它的設計基本上是推遲命令的執行,因為它將「就在這裡,現在」執行,直到下一個啟動序列之後。
答案3
創建例如/root/runonce.sh
:
#!/bin/bash
#your command here
sed -i '/runonce.sh/d' /etc/rc.local
添加/etc/rc.local
:
/root/runonce.sh
答案4
我曾經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
。
我喜歡這個解決方案,因為它在系統上放置一個且僅一個文件,如果需要,可以重新發出運行一次命令。