ฉันจะสร้างงาน cron ใหม่โดยทางโปรแกรมได้อย่างไร


130

ฉันต้องการเพิ่มงาน cron ใหม่ด้วยโปรแกรมวิธีใดที่ดีที่สุดในการดำเนินการนี้

จากการวิจัยของฉันดูเหมือนว่าฉันสามารถทิ้ง crontab ปัจจุบันแล้วต่อท้ายอันใหม่โดยวางท่อนั้นกลับเข้าไปใน crontab:

(crontab -l ; echo "0 * * * * wget -O - -q http://www.example.com/cron.php") | crontab -

มีวิธีที่ดีกว่า?


2
ทางออกของคุณดูเหมือนจะดี
Craig S

บน Solaris เพียงแค่ลบเส้นประสำหรับ crontab สุดท้าย คุณสามารถเพิ่ม grep เพื่อหลีกเลี่ยงการเพิ่มบรรทัดที่นั่น
lacroix1547


วงเล็บปีกกาแทนวงเล็บจะทำได้โดยไม่ต้องมีกระบวนการวางไข่ อย่าลืมเว้นช่องว่างรอบ ๆ วงเล็บ {... ; }
Jay Winston

คำตอบ:


-25

มันทำงานได้ดีสำหรับฉันเสมอ

คุณควรพิจารณาสคริปต์ที่ซับซ้อนกว่าเล็กน้อยซึ่งสามารถทำสามสิ่งได้

  1. ต่อท้ายบรรทัด crontab รับรองว่าไม่มีอยู่จริง การเพิ่มเมื่อมีอยู่แล้วไม่ดี

  2. เอาเส้น crontab บางทีอาจเป็นเพียงคำเตือนหากไม่มีอยู่จริง

  3. การรวมกันของคุณสมบัติสองประการข้างต้นเพื่อแทนที่เส้น crontab


78
เขาถามว่าคุณบอกเขาว่าอย่างไร?
Cerin

1
จะเกิดอะไรขึ้นถ้าผู้ใช้ยังไม่มี crontab?
Maxim Egorushkin

132

วิธีที่ดีที่สุดหากคุณใช้งานในฐานะรูทคือวางไฟล์ใน /etc/cron.d

หากคุณใช้ตัวจัดการแพ็กเกจเพื่อทำแพ็กเกจซอฟต์แวร์ของคุณคุณสามารถวางไฟล์ในไดเร็กทอรีนั้นได้และไฟล์เหล่านั้นจะถูกตีความว่าเป็น crontabs แต่มีฟิลด์พิเศษสำหรับชื่อผู้ใช้เช่น:

ชื่อไฟล์: /etc/cron.d/per_minute

เนื้อหา: * * * * * root /bin/sh /home/root/script.sh


5
ตรวจสอบให้แน่ใจว่าเวอร์ชันของ cron ที่ใช้นั้นรองรับ /etc/cron.d/ ลีนุกซ์รุ่นใหม่ส่วนใหญ่ทำ
sleske

8
นี่เป็นวิธีแก้ปัญหาที่เรียบง่ายและสง่างามที่สุด แน่นอนว่าจะต้องแยกวิเคราะห์และแก้ไข crontab ที่มีอยู่กับรายการอื่น ๆ ที่ไม่เกี่ยวข้อง
Cerin

13
ข้อแม้ที่เป็นไปได้อย่างหนึ่งคือความถี่ที่ cron หยิบข้อมูลเพิ่มเติมใหม่ในโฟลเดอร์นี้ (หนึ่งครั้งต่อชั่วโมง) หากคุณคาดหวังว่างานของคุณจะเริ่มทำงานทันทีโปรดระวัง
JonathanK

6
@JonathanK คุณรู้หรือไม่ว่า cron สามารถขอให้สแกนซ้ำได้/etc/cron.d/*หรือไม่? ยากที่จะทราบว่ามีบางอย่างทำงานได้หรือไม่หากต้องรอตรวจสอบเป็นเวลาหนึ่งชั่วโมง!
ปิดฉาก

4
ควรตั้งค่า perms สำหรับไฟล์นี้อย่างไร chmod + x /etc/cron.d/per_minute?
giò

101

โซลูชันของ OP มีข้อบกพร่องอาจอนุญาตให้เพิ่มรายการได้สองครั้งใช้ด้านล่างเพื่อแก้ไข

(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -

5
นี่เป็นวิธีแก้ปัญหาที่ดีกว่าหากไม่ได้อธิบายไว้ เพื่อให้แน่ใจว่าคำสั่งจะไม่ถูกเพิ่มสองครั้งใน crontab
Bufke

2
นี่ไม่ใช่วิธีแก้ไขที่ดีสำหรับปัญหารายการที่ซ้ำกัน จะเกิดอะไรขึ้นถ้าในระหว่างนี้มีการเพิ่มบรรทัดอื่นใน crontab
hmn

6
เพื่อให้แน่ใจว่าเป็นเอกลักษณ์sortก่อนหน้าuniqนี้เช่น(crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | crontab -
mway

6
ไม่จำเป็นต้องuniq. ใช้ตัวเลือก-u sort
papiro

6
วิธีหลีกเลี่ยงการไม่มี crontab สำหรับผู้ใช้เมื่อฉันแก้ไข crontab ครั้งแรก
wyx

23

เพื่อเพิ่มบางสิ่งบางอย่างลงใน cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | sort | uniq | crontab -

เพื่อลบสิ่งนี้ออกจาก cron

(crontab -l ; echo "0 * * * * hupChannel.sh") 2>&1 | grep -v "no crontab" | grep -v hupChannel.sh |  sort | uniq | crontab -

หวังว่าจะช่วยใครสักคน


นี่คือสิ่งที่ฉันกำลังมองหาฉันจะเพิ่มสิ่งนี้: | grep -v '^ #' | เพื่อกรองความคิดเห็น
Tjunkie

2
จริงๆแล้วคุณไม่ควรต้องการ2>&1 | grep -v "no crontab"เพราะเมื่อไม่มี crontab สายเอาต์พุตcrontab: no crontab for...จะถูกส่งไปยัง stderr ไม่มีเหตุผลที่จะจับเอาท์พุทนั้นส่งไปยัง stdout แล้วกรองออกโดยใช้ grep ถ้าเป้าหมายของคุณคือการหลีกเลี่ยงการมองเห็นในการส่งออกของคุณแล้วใช้crontab: no crontab for... 2> /dev/null | sort....
matty


6

เพียงแค่เปลี่ยนตัวแก้ไขเป็นคำสั่งที:

export EDITOR="tee"
echo "0 * * * * /bin/echo 'Hello World'" | crontab -e

3
ระวัง - สิ่งนี้จะเช็ดรายการที่มีอยู่
starfry

5

สมมติว่ามีรายการใน crontab ของคุณอยู่แล้วคำสั่งต่อไปนี้ควรทำงานได้ดี โปรดทราบว่า$CMDตัวแปรนั้นมีไว้สำหรับการอ่านเท่านั้น การเรียงลำดับก่อนกรองรายการที่ซ้ำกันมีความสำคัญเนื่องจากuniqใช้ได้เฉพาะกับบรรทัดที่อยู่ติดกัน

CMD='wget -O - -q http://www.example.com/cron.php"'
(crontab -l ; echo "0 * * * * $CMD") | sort | uniq | crontab -

หากคุณมี crontab ว่างอยู่คุณจะได้รับข้อผิดพลาดต่อไปนี้ไปยัง stderr:

no crontab for user

หากคุณต้องการหลีกเลี่ยงสิ่งนี้คุณสามารถเพิ่มความซับซ้อนเล็กน้อยเพิ่มได้ดังนี้:

(crontab -l ; echo "0 * * * * $CMD") 2>&1 | sed "s/no crontab for $(whoami)//"  | sort | uniq | crontab -

5

วิธีแก้ปัญหาส่วนใหญ่มีไว้สำหรับการเพิ่มเส้นลงใน crontab หากคุณต้องการการควบคุมมากขึ้นคุณจะต้องสามารถควบคุมเนื้อหาทั้งหมดของ crontab ได้

คุณสามารถใช้ท่อเพื่อทำสิ่งนี้ได้อย่างสวยงาม

ในการเขียน crontab ใหม่ทั้งหมดให้ทำ

echo "2 2 2 2 2 /bin/echo foobar" |crontab -

สิ่งนี้ควรง่ายต่อการรวมกับคำตอบอื่น ๆ ที่อธิบายไว้ที่นี่เช่น

crontab -l | <something> | tee |crontab -

หรือหากคุณมีเนื้อหาในไฟล์ก็จะยิ่งง่ายกว่า

cat <file> |crontab -

3

นี่เป็นอีกวิธีหนึ่งที่หลีกเลี่ยงการทำซ้ำ

(crontab -l 2>/dev/null | fgrep -v "*/1 *  *  *  * your_command"; echo "*/1 *  *  *  * your_command") | crontab -

ต่อไปนี้เป็นวิธีตอบและหลีกเลี่ยงno crontab for userข้อความของ JohnZ หรือหากคุณจำเป็นต้องใช้งานในset -euสภาพแวดล้อมประเภทและไม่สามารถส่งคืนความล้มเหลวได้ (ในกรณีนี้2>/dev/nullส่วนนี้เป็นทางเลือก):

( (crontab -l 2>/dev/null || echo "")  ; echo "0 * * * * your_command") | sort -u - | crontab -

หรือหากคุณต้องการแยกสิ่งต่างๆเพื่อให้อ่านง่ายขึ้น:

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
(echo "$preceding_cron_jobs" ; echo "$new_job") | sort - | uniq - | crontab -

หรือเลือกที่จะลบการอ้างอิงไปยัง your_command (เช่น: หากกำหนดการมีการเปลี่ยนแปลงคุณต้องการให้มีการอ้างอิงเพียงครั้งเดียวเท่านั้น) ในกรณีนี้เราไม่ต้องการอีกต่อไปuniq(โบนัสเพิ่มเติมคำสั่งการแทรกจะยังคงอยู่)

new_job="0 * * * * your_command"
preceding_cron_jobs=$(crontab -l || echo "")
preceding_cron_jobs=$(echo "$preceding_cron_jobs" | grep -v your_command )
(echo "$preceding_cron_jobs" ; echo "$new_job") | crontab -

2

man crontab ยังมีประโยชน์:

crontab (1)

ชื่อ

   crontab - manipulate per-user crontabs (Dillon's Cron)

สรุป

   crontab file [-u user] - replace crontab from file

   crontab - [-u user] - replace crontab from stdin

   crontab -l [user] - list crontab for user

3
ส่วนที่ระบุว่า "แทนที่ crontab จาก stdin" เป็นคำตอบเพียงครึ่งเดียว :-)
Grodriguez

2

การเพิ่มคำตอบของ JohnZ นี่คือไวยากรณ์ที่จะกำหนดเวลาเป็นรูทหากคุณเป็น sudoer:

(sudo crontab -l ; echo "0 * * * * your_command") | sort - | uniq - | sudo crontab -

1
function cronjob_exists($command){

    $cronjob_exists=false;

    exec('crontab -l', $crontab);


    if(isset($crontab)&&is_array($crontab)){

        $crontab = array_flip($crontab);

        if(isset($crontab[$command])){

            $cronjob_exists=true;

        }

    }
    return $cronjob_exists;
}

function append_cronjob($command){

    if(is_string($command)&&!empty($command)&&cronjob_exists($command)===FALSE){

        //add job to crontab
        exec('echo -e "`crontab -l`\n'.$command.'" | crontab -', $output);


    }

    return $output;
}

    append_cronjob('* * * * * curl -s http://localhost/cron/test.php');

1

สิ่งนี้จะตรวจสอบเพื่อให้แน่ใจว่าไม่มีคำสั่งของคุณก่อนที่จะเพิ่ม

crontab -l 2>/dev/null | grep -q '/path/to/script' || echo "5 * * * * /path/to/script" | crontab -

ไชโย


0

การวางท่อ stdout เข้าไปcrontabไม่ได้ติดตั้ง crontab ใหม่สำหรับฉันบน macOS ดังนั้นฉันจึงพบวิธีแก้ปัญหานี้แทนโดยใช้ตัวteeแก้ไขในเชลล์ย่อย:

(EDITOR=tee && (crontab -l ; echo "@daily ~/my-script.sh" ) | uniq - | crontab -e)

0

หากคุณต้องการให้งานรันในฐานะผู้ใช้:

crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | crontab -

หากคุณต้องการให้งานรันด้วยสิทธิพิเศษ:

sudo crontab -l | { cat; echo "@weekly what_you_want_to_execute"; } | sudo crontab -

และตรวจสอบงาน (มีหรือไม่มี 'sudo'):

crontab -l | sed '/^$/d; /#/d'


-2

คุณยังสามารถแก้ไขไฟล์ข้อความตาราง cron ได้โดยตรง แต่โซลูชันของคุณดูเหมือนจะยอมรับได้อย่างสมบูรณ์


1
ฉันจะบ่นเรื่องนี้เนื่องจากความกังวลเกี่ยวกับโอกาสของการแก้ไขพร้อมกันที่ทำให้ไฟล์เสียหาย การใช้คำสั่ง crontab บรรทัดคำสั่งควรหลีกเลี่ยงปัญหานั้น
Craig S

เครกหากไม่มีการวิจัยเพิ่มเติมฉันคงไม่แน่ใจว่าเวอร์ชันบรรทัดคำสั่งนั้นปลอดภัยต่ออะตอมและสภาพการแข่งขัน น่าจะ "ค่อนข้างปลอดภัย" อยู่ดี
tuomassalo

"การแก้ไขไฟล์โดยตรง" ไม่สามารถทำได้หากไม่มีการเข้าถึงรูท (หากคุณสามารถทราบได้ว่าไฟล์ crontab ของผู้ใช้อยู่ที่ใดและจะแน่ใจได้อย่างไรว่า cron daemon ได้รับการเปลี่ยนแปลงของคุณอย่างถูกต้อง) และ "การแก้ไข" โดยทางโปรแกรมดูเหมือนจะเป็นคำถาม ต้องการคำแนะนำในตอนแรก
tripleee
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.