क्रॉटाब से प्रोग्रामेटिक रूप से कुछ जोड़ें (ssh के ऊपर)


13

मेरे पास एक परिनियोजन स्क्रिप्ट है, इसमें एक उपयोगकर्ता को कुछ जोड़ना होगा crontab(एक स्क्रिप्ट को ट्रिगर करें जो हर XXX दिनों में लॉग को साफ करता है), हालांकि यह केवल पहली तैनाती के दौरान किया जाना चाहिए, या जब इसे अपडेट करने की आवश्यकता हो।

(मैं चला सकते हैं xxx.py deploy envया xxx.py update env)

इसलिए मुझे यह करना होगा:

Check if my cronJob already exist
Put my cronJob if it does not already exist
or
update my cronjob if one of the parameter of the command is different

मैं फ़ाइल crontabका उपयोग crontab -eया संपादन किए बिना कुछ जोड़ना / जांचना / हटाना नहीं देखता crontab(इसे डाउनलोड करें, इसे फिर से लिखें, पुनः अपलोड करें)

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


1
क्या यह एक उपयोगकर्ता-विशिष्ट crontab में होना चाहिए? अधिकांश प्रीपैक्ड क्रॉन जॉब्स /etc/cron.* निर्देशिकाओं में से एक में जाते हैं।
एक CVn

CentOS है /etc/cron.d? यदि ऐसा है, तो अपने स्क्रिप्ट को अपने आवेदन के लिए एक नाम अद्वितीय का उपयोग करके वहां
रखें

हाँ यह उपयोगकर्ता विशिष्ट है। मैं इसे /etc/cron.d में नहीं जोड़ सकता, क्योंकि यह एक रूट फ़ाइल है, इस प्रकार केवल रूट की नौकरी अंदर ही बदल जाती है (मैं
सूद

1
उसी तरह /etc/crontab, फाइलें /etc/cron.d/शेड्यूल स्पेक के तुरंत बाद उपयोगकर्ता नाम के लिए एक अतिरिक्त क्षेत्र रखती हैं। उदा * * * * * username /path/to/script। देखें man 5 crontabऔर खोजें SYSTEM CRON
कैस

यह भी देखें stackoverflow.com/questions/610839/...
rogerdpack

जवाबों:


15

मेरा अब तक का सबसे अच्छा विचार

यह देखने के लिए कि क्या सामग्री वहां से मेल खाती है और केवल अपडेट होना चाहिए अगर यह नहीं है:

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    echo $(crontab -l ; echo '* 1 * * * some_command') | crontab -
fi

लेकिन यह काफी जटिल हो जाता है ताकि उस क्रोन कार्य के चारों ओर एक अलग स्क्रिप्ट का निर्माण किया जा सके।

अन्य विचार

आप स्ट्रेन के माध्यम से कॉन्ट्राब को तार भेज सकते हैं (सावधान रहें, यह किसी भी पिछले क्रॉस्टब प्रविष्टियों को साफ करता है):

echo "* 1 * * * some_command" | crontab -

यह भी ssh के माध्यम से सही काम करना चाहिए:

echo "* 1 * * * some_command" | ssh user@host "crontab -"

यदि आप उस फ़ाइल को जोड़ना चाहते हैं जिसका आप उपयोग कर सकते हैं:

# on the machine itself
echo "$(echo '* 1 * * * some_command' ; crontab -l)" | crontab -
# via ssh
echo "$(echo '* 1 * * * some_command' ; ssh user@host crontab -l)" | ssh user@host "crontab -"

यह निर्भर करता है: क्या आपको वहां क्या चाहिए होता है? :)
फिलिप -जैन के ली- स्टॉकमैन

awww ... रूट के रूप में नहीं चल रहा है? ... मैं इसे फिर से
लिखूंगा

एह, मुझे यह पसंद है: D
sliders_alpha

मेरे पास इस समाधान के साथ दो मुद्दे थे: 1) फ़ाइलों की एक सूची का echo '*...विस्तार किया *। 2) क्रॉस्टैब में लाइन एंडिंग हट गई।
हीथ राफ्टी

मैं इन मुद्दों को ठीक करने में सक्षम था: 1) से echo "*...और 2) echo $लाइन की शुरुआत से हटा दें ।
हीथ राफ्टी

3

रिकॉर्ड के लिए मैं उपयोग करने का सुझाव देने जा रहा हूं /etc/cron.d/। केवल रूट ही यहां फाइलें लिख सकता है लेकिन प्रविष्टियां किसी भी उपयोगकर्ता (बिना आवश्यकता के sudo) के रूप में चलाई जा सकती हैं ।

echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' > ~/webadmin.cron
scp -p ~/webadmin.cron root@remote_host:/etc/cron.d/webadmin

इसे कई बार लागू किया जा सकता है, webadmin.cronइसे भरकर कॉपी करने से पहले स्थानीय फ़ाइल को अपडेट करना आवश्यक है।

आप प्रावधान भी हटा सकते हैं:

ssh -q root@remote_host rm -f /etc/cron.d/webadmin

ध्यान दें कि कई मामलों में आप scp/ sshआज्ञाओं के लिए रूट का पासवर्ड प्रदान नहीं कर सकते हैं । इसके बजाय आपको सार्वजनिक / निजी कुंजी प्रमाणपत्र सेट करने की आवश्यकता है। इसके अलावा, स्थानीय खाते के निहितार्थ (जो कुछ भी है) में दूरस्थ सर्वर तक पूर्ण रूट पहुंच होगी। यह इस समय स्पष्ट नहीं है कि आपके विशिष्ट परिदृश्य के लिए शो-स्टॉपर होगा या नहीं।


यह मेरा क्लाइंट सर्वर है, मैं रूट के रूप में लॉग इन नहीं कर सकता, मैं इसे BUT कर सकता हूं, अगर मैं ऐसा करता हूं तो वे मुझे मार देंगे। यह एक webadlmin काम है इसलिए यह केवल webadmin सामान में होना चाहिए, यही मुझे sysadmin ने बताया।
स्लाइडर्स_ल्पा

@sliders_alpha नौकरी केवल वेबडैम के रूप में चलती है। यह प्रावधान है कि रूट तुल्यता की आवश्यकता है। हालाँकि, मैं एक गैर-रूट समाधान की भी तलाश करूँगा।
15:48 पर रोइमा

1
+1। /etc/cron.d/वास्तव में इस उद्देश्य के लिए मौजूद है - ताकि पैकेज / तैनाती यहां केवल एक crontab फ़ाइल को छोड़ सकें।
कैस

3

मैं अत्यधिक अपने स्वयं के रोल के बजाय इसके लिए Ansible * का उपयोग करने की सलाह देता हूं। या कठपुतली या रसोइया - लेकिन इस तरह से जीरो-इन्फ्रास्ट्रक्चर परिनियोजित स्क्रिप्ट के लिए एंसिबल अच्छी तरह से अनुकूल है।

ऐसा इसलिए है क्योंकि इस तरह की समस्याओं को हल करने के लिए पहले से ही मॉड्यूल हैं, और कॉन्फ़िगर प्रबंधन टूल में एक मूल डिजाइन लक्ष्य के रूप में idempotence है - यह केवल तब बदलने की संपत्ति है जब इसे गलती से भी जरूरत पड़ती है (या जानबूझकर) इसे फिर से चलाएं।

विशेष रूप से, Ansible का क्रोन मॉड्यूल उपयोगकर्ता crontabs को संशोधित कर सकता है। एक बोनस के रूप में, यदि आप सिस्टम क्रॉस्टैब का उपयोग करने के लिए बाद में समायोजित करना चाहते हैं, तो यह फिर से लिखने के बजाय एक बहुत ही आसान ट्विस्ट होगा।


* अस्वीकरण: मैं Red Hat के लिए काम करता हूं, और Ansible एक Red Hat प्रायोजित परियोजना है।


हाँ, बात यह है, मैं 2 महीने पहले ansible के बारे में नहीं जानता था, और अब हमारे पास एक विशाल अजगर की तैनाती की स्क्रिप्ट है (लेकिन वह MAGNIFICIENT, पठनीय, maintanable;) है) अगली बार, मैं ansible का उपयोग करूँगा, लेकिन अभी जा रहा हूँ वापस असंभव है (पैसा पैसा पैसा)
sliders_alpha

1

यदि आप लक्ष्य खाते के माध्यम से क्रोन नौकरी जोड़ना चाहते हैं, तो दौड़ें crontab -e। यह कमांड एक संपादक के माध्यम से क्रस्टैब को पारित करता है। इसे एक संपादक कमांड का उपयोग करने के लिए कहें जो आपकी इच्छा के अनुसार क्रॉस्टब को संशोधित करता है। संपादक कमांड को एक अस्थायी फ़ाइल के नाम के साथ शेल स्निपेट के रूप में निष्पादित किया जाता है।

unset VISUAL
EDITOR='update_crontab () {
  set -e
  new=$(mktemp)
  if <"$1" grep -v "^#" | grep -w do_stuff; then
    # Remove existing entries containing do_stuff
    grep -v -w do_stuff "$1" >"$new"
  else
    cp "$1" "$new"
  fi
  # Add the new entry
  echo "1 2 3 4 5 do_stuff --new-options" >>"$new"
  mv "$new" "$1"
}
update_crontab' crontab -e

यह दृष्टिकोण मूल निवासी की तुलना में अधिक विश्वसनीय है crontab -l | … | crontab -क्योंकि यह एक दौड़ की स्थिति के लिए असुरक्षित है अगर कॉन्ट्रैब को समवर्ती रूप से संपादित किया जाता है: कॉल crontab -lऔर कॉल के बीच किए गए संशोधनों को crontab -पूर्ववत किया जाएगा।


1

यह उनके "बेस्ट आइडिया अब तक" कोड के आधार पर, @ phillip-zyan-k-le-stockmann की पेशकश का एक रूपांतर है ।

उनके (उत्कृष्ट और सहायक स्निपेट) से मेरे बदलाव मूल रूप से हैं:

  • Regex न केवल कमांड नाम के लिए, बल्कि टाइम स्ट्रिंग्स सहित पूरी प्रविष्टि है। इस तरह यह एक कमांड जोड़ने का समर्थन कर सकता है, भले ही अन्य प्रविष्टियों में समान-नाम या अतिव्यापी नाम वाले आदेश हों। (यह अभी भी एक ही समय पर एक ही कमांड को दो बार नहीं जोड़ेगा।)
  • थोड़ा सा लॉगिंग
  • मैंने विभिन्न कारणों से प्रति घंटे मेरा (और नाम) स्विच किया; इसे प्रति crontab सिंटैक्स पर वापस समायोजित करना आसान है

और इसलिए यहाँ मेरा कोड है जिसे मैंने बुलाया crontab-add-hourly.sh:

#!/bin/bash

# PURPOSE:
# To allow simple, programmatic addition of commands/entries into the crontab (if not already present)

cmd=$1
entry="0 * * * * $cmd"
printf "we want to add this entry:\n$entry\n\n" 
escapedEntry=$(printf '%s\n' "$entry" | sed 's:[][\/.^$*]:\\&:g') #from: https://unix.stackexchange.com/a/129063/320236
printf "but first we'll see if it's already in there using this regex pattern:\n$escapedEntry\n\n"

if [[ $(crontab -l | egrep -v '^(#|$)' | grep -q "$escapedEntry"; echo $?) == 1 ]] # from: https://unix.stackexchange.com/a/297377/320236
then
    printf "all clear; pattern was not already present; adding command to crontab hourly:\n$cmd\n\n"
    (crontab -l ; printf "$entry\n\n") | crontab -
else
    printf "pattern already present; no action taken\n\n"
fi

उदाहरण का उपयोग और आउटपुट:

$ ./crontab-add-hourly.sh my-script.bash

we want to add this entry:
0 * * * * my-script.bash

but first we'll see if it's already in there using this regex pattern:
0 \* \* \* \* my-script\.bash

all clear; pattern was not already present; adding command to crontab hourly:
my-script.bash

0

टीएल; डीआर: यह वास्तव में काम करता है, बैश 4.4 में परीक्षण किया गया।

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    set -f
    printf "$(crontab -l ; echo '* * * * * some_command')\n" | crontab -
    set +f
fi

जैसा कि @Phillip -Zyan K Lee- Stockmann की टिप्पणियों में बताया गया है, यह समाधान *वर्तमान निर्देशिका की सभी फ़ाइलों में विस्तृत है । मुझे काम करने के लिए टिप्पणियों का सुझाव नहीं मिला। सेट-ऑफ़ वाइल्डकार्ड विस्तार को अक्षम करता है, https://stackoverflow.com/a/11456496/915441 देखें

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