เพิ่มบางอย่างลงใน crontab โดยทางโปรแกรม (ผ่าน 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ไฟล์ (ดาวน์โหลดเขียนใหม่อัปโหลดใหม่อีกครั้ง)

PS: นี่คือ cronjob เฉพาะผู้ใช้ "webadmin" จะทำมันและเขาไม่ควรใช้ sudo ทำ


1
ต้องอยู่ใน crontab เฉพาะของผู้ใช้หรือไม่ งาน cron ที่ได้รับการบรรจุล่วงหน้าส่วนใหญ่จะเข้าสู่หนึ่งในไดเรกทอรี /etc/cron.*
CVn

CentOS มี/etc/cron.dหรือไม่? ถ้าเป็นเช่นนั้นให้ใส่สคริปต์ของคุณโดยใช้ชื่อที่ไม่ซ้ำกับแอปพลิเคชันของคุณ
roaima

ใช่มันเฉพาะผู้ใช้ ฉันไม่สามารถเพิ่มลงใน /etc/cron.d เพราะเป็นไฟล์รูทดังนั้นงานของรูทเท่านั้นที่จะถูกฝังไว้ข้างใน (ฉันสามารถ sudo ได้ แต่นั่นเป็นวิธีปฏิบัติที่ไม่ดีที่ฉันได้รับการบอกเล่า)
sliders_alpha

1
เช่นเดียวกับ/etc/crontabไฟล์ใน/etc/cron.d/มีเขตข้อมูลพิเศษสำหรับชื่อผู้ใช้ทันทีหลังจากสเปคกำหนดเวลา * * * * * username /path/to/scriptเช่น ดูและค้นหาman 5 crontab SYSTEM CRON
cas

คำตอบ:


15

ความคิดที่ดีที่สุดของฉันจนถึงตอนนี้

เพื่อตรวจสอบก่อนว่าเนื้อหาตรงกับสิ่งที่ควรมีในนั้นและอัปเดตเฉพาะในกรณีที่ไม่มี:

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

แต่สิ่งนี้จะซับซ้อนพอที่จะสร้างสคริปต์แยกรอบงาน cron นั้น

ความคิดอื่น ๆ

คุณสามารถส่งสตริงผ่าน stdin ไปยัง crontab (ระวังนี่จะเป็นการลบรายการ crontab ก่อนหน้านี้):

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 -"

ขึ้นอยู่กับว่า: คุณต้องการสิ่งที่จะอยู่ในนั้นหรือไม่? :)
Phillip -Zyan K Lee- Stockmann

awww ... ไม่ได้ทำงานเหมือนรูท? ... ฉันจะเขียนใหม่ ...
Phillip -Zyan K Lee- Stockmann

ใช่ฉันชอบสิ่งนั้น: D
sliders_alpha

ฉันมีสองปัญหาด้วยวิธีนี้: 1) echo '*...ขยาย*ไปยังรายการของไฟล์ 2) การสิ้นสุดบรรทัดใน crontab ถูกลบ
Heath Raftery

ฉันสามารถแก้ไขปัญหาเหล่านี้ได้โดย: 1) เปลี่ยนเป็นecho "*...และ 2) ลบออกecho $จากจุดเริ่มต้นของบรรทัด
Heath Raftery

3

/etc/cron.d/สำหรับบันทึกที่ผมจะแนะนำให้ใช้ เฉพาะ root เท่านั้นที่สามารถเขียนไฟล์ได้ที่นี่ แต่สามารถรันรายการในฐานะผู้ใช้คนใดก็ได้ (โดยไม่จำเป็นต้องใช้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แต่คุณต้องตั้งค่าใบรับรองกุญแจสาธารณะ / ส่วนตัว นอกจากนี้โดยนัยบัญชีท้องถิ่น (ไม่ว่าจะเป็นอะไร) จะมีสิทธิ์เข้าถึงแบบเต็มไปยังเซิร์ฟเวอร์ระยะไกล ในขณะนี้ยังไม่ชัดเจนว่าจะเป็นสิ่งที่แสดงให้เห็นถึงสถานการณ์ที่เฉพาะเจาะจงของคุณหรือไม่


เป็นเซิร์ฟเวอร์ลูกค้าของฉันฉันไม่สามารถเข้าสู่ระบบในฐานะ root ฉันสามารถ sudo ลงในนั้น แต่ถ้าฉันทำอย่างนั้นพวกเขาจะฆ่าฉัน นี่คืองาน webadlmin ดังนั้นควรอยู่ในสิ่งที่ webadmin เท่านั้นนั่นคือสิ่งที่ระบบดูแลระบบบอกฉัน
sliders_alpha

@sliders_alpha งานจะทำงานเป็น webadmin เท่านั้น มันเป็นบทบัญญัติที่ต้องมีการเทียบเท่าราก อย่างไรก็ตามฉันจะมองหาโซลูชันที่ไม่ใช่รูทด้วย
roaima

1
+1 /etc/cron.d/มีอยู่เพื่อจุดประสงค์นี้อย่างแท้จริง - เพื่อให้แพ็คเกจ / การปรับใช้สามารถวางไฟล์ crontab ได้ที่นี่
cas

3

ฉันขอแนะนำให้ใช้ Ansible * สำหรับสิ่งนี้แทนที่จะทำเอง หรือ Puppet หรือ Chef - แต่ Ansible เหมาะอย่างยิ่งสำหรับสคริปต์การปรับใช้โครงสร้างพื้นฐานแบบศูนย์

นั่นเป็นเพราะมีโมดูลที่มีไว้เพื่อแก้ไขปัญหาเช่นนี้และเครื่องมือจัดการการกำหนดค่ามีidempotenceเป็นเป้าหมายการออกแบบขั้นพื้นฐาน - นั่นเป็นคุณสมบัติของการเปลี่ยนแปลงเฉพาะเมื่อจำเป็นต้องใช้แม้ว่าคุณจะตั้งใจ (หรือตั้งใจ) เรียกใช้อีกครั้ง

โดยเฉพาะอย่างยิ่งโมดูล cronของ Ansible สามารถปรับเปลี่ยน crontabs ของผู้ใช้ได้ เป็นโบนัสหากคุณต้องการปรับการใช้ crontabs ของระบบในภายหลังมันจะเป็นการบิดที่ง่ายมากแทนที่จะเขียนซ้ำ


* ข้อจำกัดความรับผิดชอบ: ฉันทำงานให้ Red Hat และ Ansible เป็นโครงการที่ Red Hat ให้การสนับสนุน


ใช่สิ่งคือฉันไม่ทราบเกี่ยวกับ ansible 2 เดือนที่ผ่านมาและตอนนี้เรามีสคริปต์ตัวจัดวางไพ ธ อนขนาดใหญ่ (แต่เขาเป็น MAGNIFICIENT อ่านง่ายบำรุงรักษาได้);) ครั้งต่อไปฉันจะใช้ แต่ตอนนี้ กลับเป็นไปไม่ได้ (เงินเงินเงิน)
sliders_alpha

1

หากคุณต้องการที่จะเพิ่มงาน cron crontab -eผ่านบัญชีเป้าหมายที่ทำงาน คำสั่งนี้ส่ง crontab ผ่านตัวแก้ไข บอกให้ใช้คำสั่งแก้ไขที่ปรับเปลี่ยน crontab ตามที่คุณต้องการ คำสั่งเอดิเตอร์ถูกเรียกใช้งานเป็นเชลล์ข้อมูลโค้ดที่มีชื่อของไฟล์ชั่วคราวต่อท้าย

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 ได้รับการแก้ไขพร้อมกัน: การแก้ไขที่ทำระหว่างการเรียกไปยังcrontab -lและการเรียกเพื่อcrontab -ยกเลิก


1

นี่คือการปรับเปลี่ยนสิ่งที่@ phillip-zyan-k-lee-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

TL; DR: ใช้งานได้จริงทดสอบใน Bash 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 โซลูชันดังกล่าวจะขยายออก*เป็นไฟล์ทั้งหมดในไดเรกทอรีปัจจุบัน ฉันไม่สามารถรับคำแนะนำความคิดเห็นในการทำงาน ตั้งพิการ -f การขยายตัวแทนดูhttps://stackoverflow.com/a/11456496/915441

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.