लिनक्स: रिबूट के बाद एक बार चलने के लिए शेड्यूल कमांड (रनऑन समतुल्य)


26

मैं लिनक्स बॉक्स पर रिबूट के बाद चलने के लिए एक कमांड शेड्यूल करना चाहता हूं। मुझे पता है कि यह कैसे करना है ताकि कमांड लगातार हर रिबूट के बाद एक @rebootकॉन्टैब प्रविष्टि के साथ चले , हालांकि मैं केवल यह चाहता हूं कि कमांड एक बार चले। इसे चलाने के बाद, इसे चलाने के लिए आदेशों की कतार से हटा दिया जाना चाहिए। मैं अनिवार्य रूप से विंडोज दुनिया में RunOnce के बराबर लिनक्स की तलाश में हूं ।

मामले में यह मायने रखता है:

$ 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 एक रिबूट से पहले कॉन्फ़िगरेशन को पूरा करने में समस्याओं के परिणामस्वरूप विंडोज की एक कलाकृति है। क्या कोई कारण है कि आप रिबूट से पहले अपनी स्क्रिप्ट नहीं चला सकते हैं? उपरोक्त समाधान RunOnce का एक उचित क्लोन प्रतीत होता है।
BillThor

जवाबों:


38

बनाओ @rebootनामक स्क्रिप्ट को चलाने के लिए अपने कॉन्टैब में प्रविष्टि/usr/local/bin/runonce

निर्देशिका संरचना बनाएं /etc/local/runonce.d/ran का उपयोग करके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
आपके उत्तर के लिए धन्यवाद। यह समाधान महान है। यह तकनीकी रूप से मेरी समस्या को हल करता है, हालांकि ऐसा लगता है कि इस काम को करने के लिए आवश्यक बुनियादी ढाँचे की बहुत तैयारी है। यह पोर्टेबल नहीं है। मुझे लगता है कि आपका समाधान आदर्श रूप से लिनक्स वितरण में बेक किया जाएगा (मुझे यकीन नहीं है कि यह क्यों नहीं है!)। आपके उत्तर ने मेरे अंतिम समाधान को प्रेरित किया, जिसे मैंने उत्तर के रूप में भी पोस्ट किया है। एक बार फिर धन्यवाद!
क्रिस्टोफर पार्कर

आपने 0 और 7 के बीच अन्य सुविधाओं में से कौन सा, स्थानीय 3 का चयन किया?
क्रिस्टोफर पार्कर

3
@ क्रिस्टोफर: एक पासा रोल हमेशा सबसे अच्छा तरीका है। गंभीरता से, हालांकि, एक उदाहरण के लिए यह कोई फर्क नहीं पड़ता था और यह कुंजी मेरी उंगली पर उतरा। इसके अलावा, मैं किसी भी आठ-पक्षीय मरने का मालिक नहीं हूं।
अगली सूचना तक रोक दिया गया।

@ डेनिस: मिल गया, धन्यवाद। संयोग से, स्थानीय 3 स्थानीय सुविधा है जो इसमें दिखाई देती है man logger
क्रिस्टोफर पार्कर

क्या $fileचर में पूर्ण पथ या केवल फ़ाइल नाम है?
एंड्रयू सविनाख

21

मैं वास्तव में डेनिस विलियमसन के जवाब में डाले गए प्रयास की सराहना करता हूं । मैं इसे इस प्रश्न के उत्तर के रूप में स्वीकार करना चाहता था, क्योंकि यह सुरुचिपूर्ण और सरल है, हालांकि:

  • मैंने अंततः महसूस किया कि इसे स्थापित करने के लिए बहुत अधिक कदमों की आवश्यकता है।
  • इसे रूट एक्सेस की आवश्यकता है।

मुझे लगता है कि उसका समाधान लिनक्स वितरण के एक आउट-ऑफ-द-बॉक्स सुविधा के रूप में महान होगा।

कहा जा रहा है, मैंने डेनिस के समाधान के रूप में कमोबेश उसी चीज को पूरा करने के लिए अपनी स्क्रिप्ट लिखी। इसके लिए किसी भी अतिरिक्त सेटअप चरणों की आवश्यकता नहीं है और इसे रूट एक्सेस की आवश्यकता नहीं है।

#!/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 fop
$ runonce -r fop
$ runonce foo

सुडो का उपयोग करने से आपके काम करने के तरीके की उम्मीद होती है। अगले रिबूट के बाद एक बार सर्वर शुरू करने के लिए उपयोगी है।

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, वर्किंग डायरेक्टरी, उपयोगकर्ता) की प्रतिकृति बनाती है।
  • यह मूल रूप से एक कमांड के निष्पादन को स्थगित करने के लिए डिज़ाइन किया गया है क्योंकि इसे अगले बूट अनुक्रम के बाद "सही यहीं, अभी" निष्पादित किया जाएगा।

आपकी स्क्रिप्ट वास्तव में बहुत आसान है। एक बात ध्यान देने योग्य है कि यह विध्वंसक रूप से स्ट्रिप्स कोरेबट से बाहर आती है।
अगली सूचना तक रोक दिया गया।

@ डेनिस: धन्यवाद। मेरे पास मूल रूप से उस अतिरिक्त grep कॉल नहीं था, लेकिन सभी टिप्पणियां जमा हो रही थीं; तीन बार हर बार मैंने स्क्रिप्ट चलाई। मुझे लगता है कि मैं स्क्रिप्ट को हमेशा उन तीन-स्वचालित टिप्पणियों की तरह दिखने वाली टिप्पणी लाइनों को हमेशा के लिए हटा दूंगा।
क्रिस्टोफर पार्कर

@ डेनिस: हो गया। पैटर्न शायद बेहतर हो सकता है, लेकिन यह मेरे लिए काम करता है।
क्रिस्टोफर पार्कर

@ डेनिस: दरअसल, crontab.c पर आधारित, मुझे लगता है कि मेरे पैटर्न ठीक हैं। ( Openource.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

यह शुद्ध प्रतिभा है। Chmod + x the /root/runonce.sh को मत भूलना। यह azure मशीनों पर एप्ट-गेट अपग्रेड के लिए एकदम सही है जो लटकता है क्योंकि Walinuxagent dpkg को रोकता है
CarComp

यह बहुत अधिक हैक है (हालांकि यह भी है कि मैं पहले किसके साथ आया था)।
जुग

2

Set के साथ /etc/rc5.d में स्क्रिप्ट सेट करें और चलाने के बाद इसे हटा दें।


2

आप इसे atकमांड के साथ कर सकते हैं , हालांकि मुझे लगता है कि आप (कम से कम आरएचईएल 5 पर, जिसे मैंने परीक्षण किया था) का उपयोग कर सकते हैं at @rebootया at reboot, लेकिन आप उपयोग कर सकते हैं at now + 2 minutesऔर फिर shutdown -r now

इसके लिए जरूरी नहीं है कि आपको सिस्टम को चलाने में 2 मिनट से अधिक समय लगे।

यह उपयोगी हो सकता है जहां आप 0 सेट-अप चाहते हैं, हालांकि मैं चाहता हूं कि 'रनऑनस' कमांड मानक किट था।


सावधान रहें कि यदि आपका सिस्टम atdबंद होने तक 2 मिनट से अधिक समय लेता है, तो शटडाउन के दौरान आपकी कमांड चल सकती है। इसके atdसाथ कमांड को शेड्यूल करने से पहले रोककर atd nowऔर फिर रिबूट करने से बचा जा सकता है ।
मल्लेउ

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

redhat और डेबियन सिस्टम में आप ऐसा कर सकते हैं /etc/rc.local से, यह एक तरह का autoexec.bat है।


7
यह केवल अगले एक ही नहीं प्रत्येक बूट पर निष्पादित किया जा रहा है ।
अगली सूचना तक रोक दिया गया।

1
मेरा बुरा, मैंने सवाल को गलत बताया। सुधार के लिए धन्यवाद
natxo asenjo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.