Linux: Yeniden başlattıktan sonra bir kez çalıştırılacak komutu zamanla


26

Bir Linux kutusunda yeniden başlattıktan sonra çalıştırılacak bir komut zamanlamak istiyorum. Bunu nasıl yapacağımı biliyorum, böylece komut bir crontab girişiyle her yeniden başlatmanın ardından sürekli olarak çalışır@reboot , ancak komutun yalnızca bir kez çalışmasını istiyorum. Çalıştıktan sonra, çalıştırılacak komutlar sırasından kaldırılmalıdır. Aslında Windows dünyasında RunOnce'ye eşdeğer bir Linux arıyorum .

Önemli olması durumunda:

$ 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

Bunu yapmanın kolay, komut dosyası bir yolu var mı?


1
RunOnce, yeniden başlatmadan önce yapılandırmayı tamamlama sorunlarından kaynaklanan bir Windows eseridir. Senaryoyu yeniden başlatmadan önce çalıştıramamak için bir neden var mı? Yukarıdaki çözüm makul bir RunOnce klonu gibi görünüyor.
BillThor

Yanıtlar:


38

@rebootBir komut dosyasını çalıştırmak için crontab'ınızda bir giriş oluşturun /usr/local/bin/runonce.

/etc/local/runonce.d/ranKullanarak adlandırılmış bir dizin yapısı oluşturun mkdir -p.

Komut dosyasını /usr/local/bin/runonceaşağıdaki gibi oluşturun :

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

Şimdi dizinde sonraki yeniden başlatma (sadece bir kez) çalıştırmak istediğiniz herhangi bir komut dosyası yerleştirin /etc/local/runonce.dve chownve chmod +xuygun şekilde. Çalıştırıldıktan sonra, ranalt dizine taşındığını ve adına eklenen tarih ve saati görürsünüz . Ayrıca bir giriş olacaktır syslog.


2
Cevabınız için teşekkürler. Bu çözüm harika. Teknik olarak sorunumu çözüyor, ancak bu işi yapmak için gereken bir çok altyapı hazırlığı var gibi görünüyor. Taşınabilir değil. Bence çözümünüz ideal olarak bir Linux dağıtımına dönüştürülecekti (Neden olmadığından emin değilim!). Cevabınız, aynı zamanda bir cevap olarak gönderdiğim nihai çözümüme ilham verdi. Tekrar teşekkürler!
Christopher Parker,

0 ile 7 arasındaki diğer olanaklardan herhangi birine karşı local3'ü ne seçtiniz?
Christopher Parker,

3
@Christopher: Bir zar rulosu her zaman en iyi yöntemdir. Cidden, yine de, bir önemi yoktu ve parmağımın üzerine konduğu anahtar bu. Ayrıca, sekiz taraflı bir kalıbım yok.
sonraki duyuruya kadar duraklatıldı.

@Dennis: Anladım, teşekkürler. Tesadüfen, local3, ortaya çıkan yerel tesistir man logger.
Christopher Parker,

$fileDeğişken tam yol mu yoksa sadece dosya adı mı içeriyor?
Andrew Savinykh

21

Dennis Williamson'ın cevabına vermiş olduğu çabayı gerçekten takdir ediyorum . Bununla birlikte, bu sorunun cevabı olarak kabul etmek istedim, bununla birlikte şık ve basit:

  • Sonunda, kurulması için çok fazla adım yapılması gerektiğini hissettim.
  • Root erişimi gerektirir.

Onun çözümünün bir Linux dağıtımının kullanıma hazır bir özelliği olarak mükemmel olacağını düşünüyorum.

Olduğu söyleniyor, Dennis'in çözümüyle aynı şeyi yapmak için kendi senaryomu yazdım. Herhangi bir ilave kurulum adımı gerektirmez ve kök erişimi gerektirmez.

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

Bu komut dosyasını kaydedin (örn: runonce) chmod +xve çalıştırma:

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

Bir yazım hatası durumunda, -r bayrağıyla runonce kuyruğundan bir komutu kaldırabilirsiniz:

$ runonce fop
$ runonce -r fop
$ runonce foo

Sudo kullanmak, çalışmasını beklediğiniz şekilde çalışır. Bir sonraki yeniden başlatmanın hemen ardından bir sunucu başlatmak için kullanışlıdır.

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"

Bazı notlar:

  • Bu betik, çevrilen ortamı (PATH, çalışma dizini, kullanıcı) kopyalar.
  • Temel olarak bir komutun yürütülmesini ertelemek üzere tasarlanmıştır, çünkü bir sonraki önyükleme sırasına kadar "tam burada, şu anda" yürütülecektir.

Komut dosyanız gerçekten kullanışlı görünüyor. Unutulmaması gereken bir şey, yıkıcı olarak yorumları crontab'ın dışına çıkarmasıdır.
sonraki duyuruya kadar duraklatıldı.

@Dennis: Teşekkürler. Aslında orda fazladan bir telefon konuşması yapmamıştım, ama tüm yorumlar yığılmıştı; Her seferinde üç tane senaryo koştum. Ben sadece otomatik olarak oluşturulan bu üç yorum gibi görünen yorum satırlarını her zaman kaldırmak için komut dosyasını değiştiririm.
Christopher Parker

@Dennis: Yapıldı. Desenler muhtemelen daha iyi olabilirdi, ama benim için çalışıyor.
Christopher Parker,

@Dennis: Aslında, crontab.c'ye dayanarak, kalıplarımın gayet iyi olduğunu düşünüyorum. ( Opensource.apple.com/source/cron/cron-35/crontab/crontab.c adresindeki "BU DOSYAYI DÜZENLEMEYİN" arayın . )
Christopher Parker

5

Örneğin oluşturun /root/runonce.sh:

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

Ekle /etc/rc.local:

/root/runonce.sh

Bu saf dahi. Chmod + x /root/runonce.sh dosyasını unutma. Walinuxagent dpkg'ı bloke ettiği için takılan masmavi makinelerde apt-get yükseltme için mükemmel bir seçim
CarComp

Bu çok tehlikeli (yine de ilk başta bulduğum şey olsa da).
iBug

2

Komut dosyasını /etc/rc5.d dosyasında bir S99 ile ayarlayın ve çalıştırdıktan sonra kendisini silmesini sağlayın.


2

Sen ile yapabilirsiniz atben fark rağmen, komuta yapamazsın kullanım (ı üzerinde test RHEL 5, en azından) at @rebootveya at reboot, ancak kullanabilirsiniz at now + 2 minutessonra ve shutdown -r now.

Bu, sisteminizin çalışması 2 dakikadan daha uzun sürmesini gerektirmez.

Eğer 'runonce' komutunun standart kit olmasını diliyorum, ancak 0 kurulumunu istediğiniz yerlerde yararlı olabilir.


Sisteminizin atddurması 2 dakikadan uzun sürerse , komutunuzun kapatma işlemi sırasında çalışabileceğini unutmayın. Bu atd, komutu shedul etmeden önce durdurmak atd nowve sonra yeniden başlatmakla önlenebilir .
mleu

2

Bence bu cevap en şık:

Komut dosyasını yerleştirin /etc/init.d/scriptve son satırda kendiliğinden silin:rm $0

Komut dosyası% 100 hataya dayanıklı değilse, ölümcül bir hata döngüsünden kaçınmak için muhtemelen istisnaları işlemek akıllıca olacaktır.


2

Ben kullanılan chkconfigotomatik bir komut dosyası bir kez önyükleme sonra ve bir daha asla koşmak benim sistemine sahip. Sisteminiz ckconfig (Fedora, RedHat, CentOs vb.) Kullanıyorsa bu işe yarar.

İlk önce 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. Komut dosyasını adlandırın run-once
  2. Komut dosyasını yerleştir /etc/init.d/
  3. Komut dosyasını etkinleştir chkconfig run-once on
  4. reboot

Sistem önyüklenirken komut dosyanız bir kez ve bir daha asla çalışmaz.

İstediğin sürece bir daha asla. Komut dosyasını her zaman chkconfig run-once onkomutla yeniden etkinleştirebilirsiniz .

Bu çözümü seviyorum çünkü sisteme bir ve sadece bir dosya koyuyor ve gerekirse run-once komutu yeniden verilebiliyor.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.