ทดสอบงาน cron รายสัปดาห์ [ปิด]


237

ฉันมี#!/bin/bashไฟล์ในไดเรกทอรี cron.week

มีวิธีทดสอบว่าใช้ได้หรือไม่ รอไม่ได้ 1 สัปดาห์

ฉันอยู่บนเดเบียน 6 ด้วยรูท


4
คุณไม่สามารถทดสอบสคริปต์ด้วยการรันสคริปต์บนบรรทัดคำสั่งหรือไม่
Frédéric Hamidi

5
เพียงเพิ่มรายการแยกต่างหากในcrontabไฟล์ของคุณที่รันทุกสองสามนาทีดูว่ามีผลลัพธ์ที่คาดไว้หรือไม่จากนั้นลบรายการทดสอบออกจาก crontab ของคุณ ลองcrontab -e
davin

61
ไม่การรันจากบรรทัดคำสั่งไม่ใช่วิธีที่ดี เพียงแค่เรียกใช้สคริปต์จากบรรทัดคำสั่งไม่รับประกันว่ามันจะได้รับการเรียกใช้เป็นผู้ใช้เดียวกันเมื่อรันจาก cron แม้ว่าจะได้รับการเรียกใช้ในฐานะผู้ใช้รายเดียวกันคุณไม่สามารถมั่นใจได้ว่าทุกสิ่งจะเหมือนเดิม สคริปต์ที่ทำงานจากบรรทัดคำสั่งสามารถล้มเหลวได้ด้วยเหตุผลทุกประเภทเมื่อเรียกใช้จาก cron
andynormancx

8
"ทุกประเภท" อาจเกินความจริงเล็กน้อย ... การอนุญาตและตัวแปรสภาพแวดล้อมเป็นสองสิ่งที่ทำให้คุณนึกถึงได้อย่างง่ายดายคุณสามารถมีเงื่อนไขเริ่มต้นอื่น ๆ ที่แตกต่างกันเช่นนามแฝง
andynormancx

3
ฉันเพิ่งผ่านการทดสอบงาน cron ใหม่ฉันจะเพิ่มรายการอื่นลงใน "ทุกประเภท" หากคุณมีสิ่งต่าง ๆ ใน bash_profile พวกเขาจะไม่ถูกเรียกใช้ครั้งเดียวในงาน cron ในขณะที่การทดสอบงานจากบรรทัดคำสั่งทำงานได้อย่างสมบูรณ์ การทดสอบงาน cron ในบรรทัดคำสั่งมาตรฐานนั้นไม่ใช่การทดสอบที่ดีเลย
andynormancx

คำตอบ:


233

ทำในสิ่งที่ cron ทำต่อไปนี้root:

run-parts -v /etc/cron.weekly

... หรือรายการถัดไปหากคุณได้รับข้อผิดพลาด "ไม่ใช่ไดเรกทอรี: -v":

run-parts /etc/cron.weekly -v

ตัวเลือก-vพิมพ์ชื่อสคริปต์ก่อนที่จะทำงาน


4
หากฉันใช้ตัวเลือก -v มันแสดงข้อผิดพลาด "ไม่ใช่ไดเรกทอรี: -v" จะไม่มี man page สำหรับคำสั่งนี้ในระบบของฉัน -v หมายถึง verbose ใช่ไหม? ฉันใช้ centos 6.4
สูงสุด

3
เพื่อหลีกเลี่ยงข้อผิดพลาด "ไม่ใช่ไดเรกทอรี" ฉันต้องทำเช่นนี้แทน: run-parts /etc/cron.weekly -v
Craig Hyatt

22
แต่สิ่งนี้ไม่ได้คำนึงถึงตัวแปรสภาพแวดล้อมที่สามารถตั้งค่าใน crontab
fcurella

34
run-partsเพียงแค่เรียกใช้สคริปต์ของไดเรกทอรีที่กำหนด ไม่มีอะไรเกี่ยวข้องกับ cron
Nicolas

23
สิ่งนี้ไม่ควรได้รับการยอมรับและยอมรับเกินกว่าการรันสคริปต์มันไม่ได้มีอะไรจะบอกคุณว่าสคริปต์จะใช้งานได้จริงเมื่อทำงานจาก cron หรือไม่ ใช้สคริปต์ที่ดีที่สุดในคำตอบหนึ่งในคำถามนี้
andynormancx

87

เล็กน้อยเกินขอบเขตคำถามของคุณ ... แต่นี่คือสิ่งที่ฉันทำ

"ฉันจะทดสอบงาน cron ได้อย่างไร" คำถามมีการเชื่อมต่ออย่างใกล้ชิดกับ "ฉันจะทดสอบสคริปต์ที่ทำงานในบริบทที่ไม่ใช่แบบโต้ตอบที่เปิดตัวโดยโปรแกรมอื่นได้อย่างไร" ใน cron ทริกเกอร์เป็นเงื่อนไขบางเวลา แต่สิ่งอำนวยความสะดวก * nix อื่น ๆ จำนวนมากเปิดใช้งานสคริปต์หรือแฟรกเมนต์สคริปต์ในวิธีที่ไม่โต้ตอบและบ่อยครั้งที่เงื่อนไขที่สคริปต์เหล่านั้นทำงานมีสิ่งที่ไม่คาดคิดและทำให้เกิดการแตก (ดูเพิ่มเติมที่: https://stackoverflow.com/a/17805088/237059 )

วิธีการทั่วไปในการแก้ไขปัญหานี้มีประโยชน์

หนึ่งในเทคนิคที่ฉันโปรดปรานคือการใช้สคริปต์ที่ฉันเขียนว่า ' crontest ' มันเริ่มต้นคำสั่งเป้าหมายภายในเซสชันหน้าจอ GNU จากภายใน cron เพื่อให้คุณสามารถแนบกับเทอร์มินัลแยกต่างหากเพื่อดูว่าเกิดอะไรขึ้นโต้ตอบกับสคริปต์หรือแม้แต่ใช้ดีบักเกอร์

ในการตั้งค่านี้คุณจะต้องใช้ "all stars" ในรายการ crontab ของคุณและระบุ crontest เป็นคำสั่งแรกในบรรทัดคำสั่งเช่น:

* * * * * crontest /command/to/be/tested --param1 --param2

ดังนั้นตอนนี้ cron จะรันคำสั่งของคุณทุกนาที แต่ crontest จะรับประกันได้ว่าจะมีเพียงหนึ่งอินสแตนซ์ที่ทำงานในแต่ละครั้ง หากคำสั่งใช้เวลาในการรันคุณสามารถทำ "screen -x" เพื่อแนบและดูคำสั่งนั้นได้ หากคำสั่งเป็นสคริปต์คุณสามารถวางคำสั่ง "read" ที่ด้านบนเพื่อหยุดและรอให้การแนบหน้าจอเสร็จสมบูรณ์ (กด Enter หลังจากติด)

หากคำสั่งของคุณเป็นสคริปต์ทุบตีคุณสามารถทำได้ดังนี้:

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2

ตอนนี้ถ้าคุณแนบกับ "screen -x" คุณจะต้องเผชิญกับเซสชัน bashdb แบบโต้ตอบและคุณสามารถก้าวผ่านโค้ดตรวจสอบตัวแปร ฯลฯ

#!/bin/bash

# crontest
# See https://github.com/Stabledog/crontest for canonical source.

# Test wrapper for cron tasks.  The suggested use is:
#
#  1. When adding your cron job, use all 5 stars to make it run every minute
#  2. Wrap the command in crontest
#        
#
#  Example:
#
#  $ crontab -e
#     * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams
#
#  Now, cron will run your job every minute, but crontest will only allow one
#  instance to run at a time.  
#
#  crontest always wraps the command in "screen -d -m" if possible, so you can
#  use "screen -x" to attach and interact with the job.   
#
#  If --bashdb is used, the command line will be passed to bashdb.  Thus you
#  can attach with "screen -x" and debug the remaining command in context.
#
#  NOTES:
#   - crontest can be used in other contexts, it doesn't have to be a cron job.
#       Any place where commands are invoked without an interactive terminal and
#       may need to be debugged.
#
#   - crontest writes its own stuff to /tmp/crontest.log
#
#   - If GNU screen isn't available, neither is --bashdb
#

crontestLog=/tmp/crontest.log
lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi )
useBashdb=false
useScreen=$( if which screen &>/dev/null; then echo true; else echo false; fi )
innerArgs="$@"
screenBin=$(which screen 2>/dev/null)

function errExit {
    echo "[-err-] $@" | tee -a $crontestLog >&2
}

function log {
    echo "[-stat-] $@" >> $crontestLog
}

function parseArgs {
    while [[ ! -z $1 ]]; do
        case $1 in
            --bashdb)
                if ! $useScreen; then
                    errExit "--bashdb invalid in crontest because GNU screen not installed"
                fi
                if ! which bashdb &>/dev/null; then
                    errExit "--bashdb invalid in crontest: no bashdb on the PATH"
                fi

                useBashdb=true
                ;;
            --)
                shift
                innerArgs="$@"
                return 0
                ;;
            *)
                innerArgs="$@"
                return 0
                ;;
        esac
        shift
    done
}

if [[ -z  $sourceMe ]]; then
    # Lock the lockfile (no, we do not wish to follow the standard
    # advice of wrapping this in a subshell!)
    exec 9>$lockfile
    flock -n 9 || exit 1

    # Zap any old log data:
    [[ -f $crontestLog ]] && rm -f $crontestLog

    parseArgs "$@"

    log "crontest starting at $(date)"
    log "Raw command line: $@"
    log "Inner args: $@"
    log "screenBin: $screenBin"
    log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )"
    log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )"

    # Were building a command line.
    cmdline=""

    # If screen is available, put the task inside a pseudo-terminal
    # owned by screen.  That allows the developer to do a "screen -x" to
    # interact with the running command:
    if $useScreen; then
        cmdline="$screenBin -D -m "
    fi

    # If bashdb is installed and --bashdb is specified on the command line,
    # pass the command to bashdb.  This allows the developer to do a "screen -x" to
    # interactively debug a bash shell script:
    if $useBashdb; then
        cmdline="$cmdline $(which bashdb) "
    fi

    # Finally, append the target command and params:
    cmdline="$cmdline $innerArgs"

    log "cmdline: $cmdline"


    # And run the whole schlock:
    $cmdline 

    res=$?

    log "Command result: $res"


    echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" >> $crontestLog

    # Release the lock:
    9<&-
fi

2
สุดยอดโซลูชั่นที่สมบูรณ์แบบ เทคนิคอื่น ๆ ทั้งหมดที่ฉันได้ลองใช้ไม่ได้ผลจริง ๆ crontest แก้ปัญหาได้อย่างง่ายดาย
andynormancx

1
นี่เป็นวิธีที่มากกว่าที่ฉันต้องการ แต่ +1 สำหรับโซลูชันที่ยอดเยี่ยมอยู่ดี การตั้งค่า cron ให้ทำงานบ่อยขึ้นและดัมพ์เอาต์พุตไปยัง / tmp นั้นดีพอที่จะตรวจสอบปัญหาของฉัน
jcollum

2
เย็น. ใช่ไม่มีเหตุผลที่จะยิงรถปราบดินหากคุณต้องการมือจอบ :)
Stabledog

2
สิ่งที่ยอดเยี่ยม หมายเหตุเกี่ยวกับ mac ฉันต้องbrew tap discoteq/discoteq; brew install flockแล้วปรับเปลี่ยนสคริปต์เพื่อใช้/usr/local/bin/flock
Claudiu

1
ยูทิลิตี้ที่ดี! มีประโยชน์มากในการวินิจฉัยปัญหาการตรวจสอบสิทธิ์ในบริบทที่ไม่โต้ตอบ
Eric Blum

44

หลังจากพูดคุยกับบางสิ่งใน cron ซึ่งไม่สามารถใช้งานได้ทันทีฉันพบว่าวิธีการต่อไปนี้ดีสำหรับการดีบัก

crontab -e

* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log

สิ่งนี้จะรันภารกิจหนึ่งครั้งต่อนาทีและคุณสามารถดู/tmp/cron_debug_log.logไฟล์เพื่อหาว่าเกิดอะไรขึ้น

มันไม่ใช่ "fire fire" ที่คุณอาจกำลังมองหา แต่สิ่งนี้ช่วยฉันได้มากเมื่อทำการดีบั๊กสคริปต์ที่ไม่ได้ทำงานใน cron ในตอนแรก


9
ฉันอยากจะแนะนำวิธีนี้ ปัญหาส่วนใหญ่คือคุณไม่เห็นข้อผิดพลาด
Yauhen Yakimovich

8
บรรทัดไม่ถูกต้องไม่มีการแจกแจงใด ๆ ที่ใช้ bash สำหรับ cron shell ดังนั้น & & >> ก็ไม่ทำงาน ฉันแนะนำให้ใช้ >>/tmp/cron_debug_log.log 2>&1แทน
drizzt

1
คุณหมายถึงอะไร/path/to/prog- prog ใด
นาธาน

3
โปรแกรมที่คุณจะรันด้วย cron สิ่งนี้สามารถเป็นได้usr/home/myFancyScript.shหรืออาจเป็นแบบเรียบง่ายlsหรือสิ่งที่คุณต้องการเรียกใช้เป็นประจำ
Automatico

สิ่งนี้ใช้ได้สำหรับฉัน มันเป็นวิธีที่ง่ายที่สุดในการทำแบบทดสอบอย่างรวดเร็วเพื่อตรวจสอบว่าทุกอย่างเรียบร้อยดีหรือไม่
abhijit

25

ฉันจะใช้ไฟล์ล็อคแล้วตั้งค่างาน cron ให้ทำงานทุกนาที (ใช้ crontab -e และ * * * * * / path / to / job) วิธีที่คุณสามารถแก้ไขไฟล์ต่อไปและทุกนาทีที่จะถูกทดสอบ นอกจากนี้คุณสามารถหยุด cronjob ได้โดยเพียงแค่แตะล็อคไฟล์

    #!/bin/sh
    if [ -e /tmp/cronlock ]
    then
        echo "cronjob locked"
        exit 1
    fi

    touch /tmp/cronlock
    <...do your regular cron here ....>
    rm -f /tmp/cronlock

4
คุณยังสามารถใช้flock(1)จากเชลล์ เห็นman 1 flockไหม ค่อนข้างมีประโยชน์สำหรับการใช้งานดังกล่าวเนื่องจากมีการบล็อกอัตโนมัติ
Craig Ringer

5

สิ่งที่เกี่ยวกับการใส่ลงไปcron.hourlyรอจนกว่าจะทำงาน cron รายชั่วโมงต่อไปแล้วลบมัน? ที่จะทำงานครั้งเดียวภายในหนึ่งชั่วโมงและในสภาพแวดล้อม cron นอกจากนี้คุณยังสามารถเรียกใช้./your_scriptแต่จะไม่มีสภาพแวดล้อมเดียวกันภายใต้ cron


นี่มันค่อนข้างเหมือนกับคำตอบของ @ Cort3z โดยมีรายละเอียดน้อยกว่า
jcollum

5

คำตอบเหล่านี้ไม่ตรงกับสถานการณ์เฉพาะของฉันซึ่งฉันต้องการทำงาน cron หนึ่งงานเพียงครั้งเดียวและทำงานทันที

ฉันอยู่บนเซิร์ฟเวอร์ Ubuntu และฉันใช้ cPanel เพื่อตั้งค่างาน cron ของฉัน

ฉันเพิ่งเขียนการตั้งค่าปัจจุบันของฉันแล้วแก้ไขให้เป็นหนึ่งนาทีจากนี้ เมื่อฉันแก้ไขข้อผิดพลาดอื่นฉันเพิ่งแก้ไขอีกครั้งหนึ่งนาทีจากนี้ และเมื่อฉันทำเสร็จแล้วฉันเพิ่งรีเซ็ตการตั้งค่ากลับไปเป็นแบบเดิม

ตัวอย่าง: ตอนนี้เป็น 16:34 น. ดังนั้นฉันจึงใส่ 35 16 * * * เพื่อให้มันทำงานเวลา 16:35

มันใช้งานได้อย่างมีเสน่ห์และสิ่งที่ฉันต้องรอคือน้อยกว่าหนึ่งนาที

ฉันคิดว่านี่เป็นตัวเลือกที่ดีกว่าคำตอบอื่น ๆ เพราะฉันไม่ต้องการทำงาน crons รายสัปดาห์ทั้งหมดของฉันและฉันไม่ต้องการให้งานวิ่งทุกนาที ฉันใช้เวลาสองสามนาทีเพื่อแก้ไขปัญหาที่เกิดขึ้นก่อนที่ฉันจะพร้อมทดสอบอีกครั้ง หวังว่านี่จะช่วยใครซักคน


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

4

นอกจากนั้นคุณยังสามารถใช้:

http://pypi.python.org/pypi/cronwrap

เพื่อห่อ cron ของคุณเพื่อส่งอีเมลถึงคุณเมื่อสำเร็จหรือล้มเหลว


10
Cron ไม่ได้ส่งอีเมลและออกจากสคริปต์เมื่อมีการดำเนินการแล้ว
Erik

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

3

วิธีการแก้ปัญหาที่ฉันใช้มีดังนี้:

  1. แก้ไข crontab (ใช้คำสั่ง: crontab -e) เพื่อรันงานบ่อยเท่าที่ต้องการ (ทุกๆ 1 นาทีหรือ 5 นาที)
  2. ปรับเปลี่ยนเชลล์สคริปต์ที่ควรดำเนินการโดยใช้ cron เพื่อพิมพ์ผลลัพธ์ลงในไฟล์บางไฟล์ (เช่น: echo "Working fine" >>
    output.txt)
  3. ตรวจสอบไฟล์ output.txt โดยใช้คำสั่ง: tail -f output.txt ซึ่งจะพิมพ์ข้อมูลเพิ่มเติมล่าสุดลงในไฟล์นี้และทำให้คุณสามารถติดตามการทำงานของสคริปต์

2

โดยปกติฉันจะทดสอบโดยใช้งานที่ฉันสร้างขึ้นเช่นนี้:

การใช้เทอร์มินัลสองเครื่องทำได้ง่ายกว่า

ทำงาน:

#./jobname.sh

ไปที่:

#/var/log and run 

เรียกใช้ต่อไปนี้:

#tailf /var/log/cron

สิ่งนี้ทำให้ฉันเห็นการอัพเดตบันทึก cron แบบเรียลไทม์ นอกจากนี้คุณยังสามารถตรวจสอบบันทึกหลังจากที่คุณเรียกใช้ฉันชอบดูในเวลาจริง

นี่คือตัวอย่างของงาน cron อย่างง่าย กำลังอัปเดตยำ ...

#!/bin/bash
YUM=/usr/bin/yum
$YUM -y -R 120 -d 0 -e 0 update yum
$YUM -y -R 10 -e 0 -d 0 update

นี่คือรายละเอียด:

คำสั่งแรกจะอัปเดต yum เองและถัดไปจะใช้การอัปเดตระบบ

-R 120: ตั้งค่าจำนวนเวลาสูงสุดที่ yum จะรอก่อนดำเนินการคำสั่ง

-e 0: ตั้งค่าระดับข้อผิดพลาดเป็น 0 (ช่วง 0 - 10) 0 หมายถึงพิมพ์เฉพาะข้อผิดพลาดที่สำคัญซึ่งคุณต้องบอก

-d 0: ตั้งค่าระดับการดีบักเป็น 0 - เปิดหรือลดจำนวนของสิ่งต่าง ๆ ที่พิมพ์ (ช่วง: 0 - 10)

-y: สมมติว่าใช่; สมมติว่าคำตอบสำหรับคำถามใด ๆ ที่จะถูกถามคือใช่

หลังจากที่ฉันสร้างงาน cron ฉันก็ใช้คำสั่งด้านล่างเพื่อให้งานของฉันทำงานได้

#chmod +x /etc/cron.daily/jobname.sh 

หวังว่านี่จะช่วยได้ Dorlack


2
sudo run-parts --test /var/spool/cron/crontabs/

ไฟล์ในcrontabs/ไดเรกทอรีนั้นจะต้องสามารถเรียกใช้งานได้โดย owner - octal700

แหล่งที่มา: man cronและNNRooth's


5
สองสิ่ง ข้อแรก: เมื่อต้องการเรียกใช้สิ่งต่าง ๆ เนื่องจาก sudo ใช้สภาพแวดล้อมที่แตกต่างกัน (ตัวแปรที่กำหนดไว้) ดังนั้นข้อบกพร่องใน crontab ของคุณสามารถทำงานได้เมื่อดำเนินการเป็น 'sudo' แต่จะไม่ทำงานเมื่อดำเนินการเป็น 'root' (และในทางกลับกัน) ข้อที่สอง: 'man cron' ไม่แสดงข้อมูลนี้ให้ฉัน (โอเคคนของฉันดูเหมือนจะเฉพาะเดเบียน) ... 'man run-parts' กล่าวว่า - การทดสอบไม่ได้รันสคริปต์ แต่พิมพ์เฉพาะชื่อของ พวกเขา ดังนั้นสคริปต์จะไม่ถูกทดสอบ สิ่งเล็กน้อย: 'เรียกใช้โดยเจ้าของ': เท่าที่ฉันรู้ cronjobs เท่านั้นจะถูกดำเนินการในฐานะรูท
Alex

-1

ฉันใช้Webminเพราะมันเป็นอัญมณีแห่งการเพิ่มผลผลิตสำหรับผู้ที่พบว่าการดูแลบรรทัดคำสั่งค่อนข้างน่ากลัวและไม่ยอมรับ

มีปุ่ม "บันทึกและเรียกใช้ตอนนี้" ในเว็บ "ระบบ> งาน Cron ตามกำหนดเวลา> แก้ไขเว็บ Cron Job"

มันแสดงผลลัพธ์ของคำสั่งและเป็นสิ่งที่ฉันต้องการ

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