นามธรรม
รหัสที่ถูกต้องควรเป็น:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
เรียกสคริปต์นี้end_of_month.sh
และการเรียกเป็น cron เป็นเพียง:
00 12 28-31 * * /path/to/script/end_of_month.sh command
ที่จะเรียกใช้สคริปต์end_of_month
(ซึ่งภายในจะตรวจสอบว่าวันนี้เป็นวันสุดท้ายของเดือน) เฉพาะในวันที่ 28, 29, 30 และ 31 ไม่จำเป็นต้องตรวจสอบปลายเดือนในวันอื่น ๆ
โพสต์เก่า
นั่นคือคำพูดจากหนังสือ "Linux Command Line และ Shell Scripting Bible" โดย Richard Blum, Christine Bresnahan pp 442, รุ่นที่สาม, John Wiley & Sons © 2015
ใช่นั่นคือสิ่งที่มันพูด แต่นั่นผิด / ไม่สมบูรณ์:
fi
ที่ขาดหายไปปิด
- ต้องการพื้นที่ระหว่างและต่อไปนี้
[
`
- มันเป็นเรื่องที่ขอแนะนำให้ใช้ $ ( ... )
`…`
แทน
- มันเป็นสิ่งสำคัญที่คุณจะต้องใช้เครื่องหมายคำพูดรอบการขยายเช่น
"$(…)"
- มีเพิ่มเติม
;
หลังจากthen
ฉันจะรู้ได้อย่างไร (โดยประสบการณ์☺) แต่คุณสามารถลองใช้Shellcheckได้ วางรหัสจากหนังสือ (หลังเครื่องหมายดอกจัน) แล้วมันจะแสดงข้อผิดพลาดตามรายการข้างต้นพร้อมกับ "shebang ที่หายไป" สคริปต์ที่ไม่มีข้อผิดพลาดใน Shellcheck คือ:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
ไซต์นั้นใช้งานได้เพราะสิ่งที่เขียนคือ "รหัสเชลล์" นั่นคือไวยากรณ์ที่ใช้งานได้ในหลาย ๆ เชลล์
ปัญหาบางอย่างที่ shellcheck ไม่ได้กล่าวถึงคือ:
มันสันนิษฐานว่าคำสั่ง date เป็นเวอร์ชั่นของ GNU หนึ่งที่มี-d
ตัวเลือกที่ยอมรับtomorrow
เป็นค่า (busybox มีตัวเลือก -d แต่ไม่เข้าใจในวันพรุ่งนี้และ BSD มี-d
ตัวเลือก แต่ไม่เกี่ยวข้องกับ "แสดง" เวลา)
มันเป็นการดีกว่าที่จะกำหนดรูปแบบหลังจากตัวเลือกdate -d tomorrow +'%d'
ทั้งหมด
เวลาเริ่มต้น cron อยู่ในเวลาท้องถิ่นเสมอซึ่งอาจทำให้หนึ่งงานเริ่มต้นก่อนหน้า 1 ชั่วโมงช้ากว่าการนับวันที่แน่นอนถ้า DST (การปรับเวลาตามฤดูกาล) ถูกตั้งค่าหรือยกเลิกการตั้งค่า
สิ่งที่เราทำคือเชลล์สคริปต์ที่สามารถเรียกได้ด้วย cron เราสามารถแก้ไขสคริปต์เพิ่มเติมเพื่อยอมรับข้อโต้แย้งของโปรแกรมหรือคำสั่งเพื่อดำเนินการเช่นนี้ (ในที่สุดรหัสที่ถูกต้อง):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
เรียกสคริปต์นี้end_of_month.sh
และการเรียกเป็น cron เป็นเพียง:
00 12 28-31 * * /path/to/script/end_of_month.sh command
ที่จะเรียกใช้สคริปต์end_of_month
(ซึ่งภายในจะตรวจสอบว่าวันนี้เป็นวันสุดท้ายของเดือน) เฉพาะในวันที่ 28, 29, 30 และ 31 ไม่จำเป็นต้องตรวจสอบปลายเดือนในวันอื่น ๆ
ตรวจสอบให้แน่ใจว่ามีเส้นทางที่ถูกต้อง PATH ภายใน cron จะไม่ (ไม่น่าจะเป็น) เหมือนกับ PATH ของผู้ใช้
ทราบว่ามีหนึ่งในตอนท้ายของเดือนสคริปต์การทดสอบ (ตามที่ระบุไว้ด้านล่าง) ที่สามารถเรียกสาธารณูปโภคอื่น ๆ อีกมากมายหรือสคริปต์
นี่จะหลีกเลี่ยงปัญหาเพิ่มเติมที่ cron สร้างด้วยบรรทัดคำสั่งแบบเต็ม:
- Cron แยกบรรทัดคำสั่งใด ๆ
%
แม้ว่าจะยกมาด้วย'
หรือ"
(เฉพาะ\
งานที่นี่) นั่นเป็นวิธีการทั่วไปที่งาน cron ล้มเหลว
คุณสามารถทดสอบว่าend_of_month.sh
สคริปต์ทำงานอย่างถูกต้องในบางวันหรือไม่ (โดยไม่ต้องรอจนถึงสิ้นเดือนเพื่อตรวจสอบว่าสคริปต์ไม่ทำงาน) โดยการทดสอบด้วย faketime:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....