Linux:再起動後にコマンドを1回実行するようにスケジュールする(RunOnceと同等)


26

Linuxボックスでの再起動後に実行するコマンドをスケジュールしたいと思います。私はこれを行う方法を知っているので、crontabエントリを使用して再起動するたびにコマンドが一貫@rebootして実行されますが、コマンドを1回だけ実行したいです。実行後、実行するコマンドのキューから削除する必要があります。基本的に、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

これを行う簡単でスクリプト可能な方法はありますか?


1
RunOnceは、再起動前に構成を完了する際の問題に起因するWindowsのアーティファクトです。再起動する前にスクリプトを実行できない理由はありますか?上記のソリューションは、RunOnceの妥当なクローンのようです。
BillThor

回答:


38

@rebootcrontabにエントリを作成して、というスクリプトを実行します/usr/local/bin/runonce

/etc/local/runonce.d/ranusing というディレクトリ構造を作成します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.dchownchmod +x適切に配置します。実行されると、ranサブディレクトリに移動され、その名前に日付と時刻が追加されます。にもエントリがありますsyslog


2
ご回答有難うございます。このソリューションは素晴らしいです。それは技術的に私の問題を解決しますが、この作業を行うために必要なインフラストラクチャの準備がたくさんあるようです。ポータブルではありません。あなたのソリューションは理想的にはLinuxディストリビューションに焼き付けられると思います(なぜそうでないのかはわかりません!)。あなたの答えは私の究極の解決策に影響を与えました。私はそれも答えとして投稿しました。再度、感謝します!
クリストファーパーカー

local3を選択した理由と、0〜7の他の施設の選択
クリストファーパーカー

3
@Christopher:サイコロは常に最良の方法です。しかし、真剣に、例のためにそれは問題ではなく、それは私の指が上陸したキーです。その上、私は8面ダイスを所有していません。
追って通知があるまで一時停止します。

@デニス:ありがとうございます。偶然にも、local3はに表示されるローカル施設ですman logger
クリストファーパーカー

ない$file変数は、完全なパスまたはファイル名だけが含まれていますか?
アンドリューサビニク

21

デニス・ウィリアムソンの答えに注がれた努力に本当に感謝しています。しかし、この質問に対する答えとしてそれを受け入れたかったのは、エレガントでシンプルだからです。

  • 最終的には、セットアップに必要な手順が多すぎると感じました。
  • ルートアクセスが必要です。

彼のソリューションは、Linuxディストリビューションのすぐに使える機能として素晴らしいものになると思います。

そうは言っても、デニスのソリューションとほぼ同じことを達成するために、私は自分のスクリプトを書きました。追加のセットアップ手順は必要なく、ルートアクセスも必要ありません。

#!/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を使用すると、期待どおりに機能します。次回の再起動後にサーバーを1回だけ起動するのに便利です。

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"

いくつかのメモ:

  • このスクリプトは、起動された環境(PATH、作業ディレクトリ、ユーザー)を複製します。
  • コマンドは、次のブートシーケンスの後まで「ここで今すぐ」実行されるため、基本的にコマンドの実行を延期するように設計されています。

あなたのスクリプトは本当に便利に見えます。注意すべきことの1つは、crontabからコメントを破壊的に削除することです。
追って通知があるまで一時停止します。

@デニス:ありがとう。もともとそこに余分なgrep呼び出しはありませんでしたが、すべてのコメントが蓄積されていました。スクリプトを実行するたびに3つ。これら3つの自動生成されたコメントのように見えるコメント行を常に削除するようにスクリプトを変更すると思います。
クリストファーパーカー

@デニス:できた。パターンはおそらくもっと良いかもしれませんが、私にとってはうまくいきます。
クリストファーパーカー

@Dennis:実際、crontab.cに基づいて、私のパターンは問題ないと思います。(opensource.apple.com/source/cron/cron-35/crontab/crontab.cで「このファイルを編集しないでください」を検索してください
クリストファーパーカー

5

作成例/root/runonce.sh

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

に追加/etc/rc.local

/root/runonce.sh

これは純粋な天才です。/root/runonce.shをchmod + xすることを忘れないでください。これは、walinuxagentがdpkgをブロックするためにハングするAzureマシンでのapt-getアップグレードに最適です
-CarComp

これはあまりにもハックです(最初に思いついたものでもありますが)。
iBug

2

S99を使用して/etc/rc5.dにスクリプトをセットアップし、実行後に自分自身を削除します。


2

atコマンドでこれを行うことができますが、(少なくとも私がテストしたRHEL 5では)at @rebootorを使用できないことに気付きますがat rebootat now + 2 minutesand を使用することはできますshutdown -r now

これにより、システムの実行に2分以上かかることはありません。

「runonce」コマンドが標準キットであることを望みますが、0のセットアップが必要な場合に役立ちます。


システムatdが停止するまで2分以上かかる場合、シャットダウン中にコマンドが実行される可能性があることに注意してください。これはatd、コマンドを実行する前に停止しatd nowてから再起動することで回避できます。
mleu

2

この答えは最もエレガントだと思います:

スクリプトを配置/etc/init.d/scriptし、最後の行で自己削除します。rm $0

スクリプトが100%フェールプルーフでない限り、致命的なエラーループを回避するために例外を処理することをお勧めします。


2

以前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コマンドでいつでもスクリプトを再度有効にすることができます。

このソリューションが気に入っているのは、システムにファイルを1つだけ配置し、必要に応じて1回実行コマンドを再発行できるためです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.