ทำซ้ำคำสั่งทุกช่วงเวลา x ในเทอร์มินัลหรือไม่?


142

ฉันจะทำซ้ำคำสั่งทุกช่วงเวลาเพื่อที่จะให้ฉันเรียกใช้คำสั่งสำหรับการตรวจสอบ หรือตรวจสอบ ไดเรกทอรี?

ไม่จำเป็นต้องใช้สคริปต์ฉันต้องการเพียงคำสั่งง่ายๆที่จะดำเนินการใน terminal

คำตอบ:


219

คุณสามารถใช้ watchคำสั่งwatchถูกใช้เพื่อเรียกใช้คำสั่งที่กำหนดในช่วงเวลาปกติ

เปิด Terminal และประเภท:

watch -n x <your command>

เปลี่ยนxเป็นเวลาในหน่วยวินาทีที่คุณต้องการ

สำหรับความช่วยเหลือเพิ่มเติมโดยใช้watchคำสั่งและตัวเลือกของตนทำงานman watchหรือเยี่ยมชมนี้การเชื่อมโยง

ตัวอย่างเช่น:รายการต่อไปนี้จะแสดงทุก ๆ60sบนเทอร์มินัลเดียวกันเนื้อหาของไดเรกทอรีเดสก์ท็อปเพื่อให้คุณสามารถทราบว่ามีการเปลี่ยนแปลงเกิดขึ้นหรือไม่:

watch -n 60 ls -l ~/Desktop

34
+1 แต่ระวังเมื่อใช้ส่วนขยาย ตัวอย่างเช่นลองใช้ความแตกต่างระหว่างwatch -n 1 'echo $COLUMNS'และwatch -n 1 echo $COLUMNSเมื่อปรับขนาดเทอร์มินัล - ตัวเก่าจะถูกขยายทุกวินาที แต่ตัวหลังจะถูกขยายเพียงครั้งเดียวก่อนที่จะ watchเริ่ม
l0b0

มันใช้งานได้เหมือนมีเสน่ห์! Ty nux

ปัญหาที่ฉันมีกับวิธีนี้คือคุณไม่สามารถเรียกใช้การเฝ้าดูเป็นกระบวนการและปล่อยให้มันทำงานในพื้นหลัง (ตัวอย่างเช่นกับ & ปฏิเสธ)
เซสเตอร์เรียน

2
มีวิธีใช้watchกับคำสั่งชนิด "เปิดใช้งานประวัติ" หรือไม่ ฉันชอบที่จะใช้watchแต่บางครั้งฉันต้องการที่จะเห็นบันทึกการประหารชีวิตก่อนหน้านี้เช่นกันแทนที่จะเป็นแค่การบันทึกครั้งสุดท้าย และใช่ฉันรู้ว่าฉันสามารถใช้สคริปต์ ( while true) เพื่อทำสิ่งนี้ได้ แต่การใช้watchutilitiy นั้นสะอาดกว่ามาก!
rinogo

สิ่งนี้ใช้ได้กับคำสั่งที่ง่ายกว่า แต่ด้วยคำสั่ง pipelined การโยงนี้ไม่ทำงานสำหรับฉัน .. ต่อไปนี้คือคำสั่งที่ฉันลอง => cat api.log | grep 'calling' | wc -l
Sudip Bhandari

90

คุณยังสามารถใช้คำสั่งนี้ในเทอร์มินัลนอกเหนือจากคำตอบของ nux:

while true; do <your_command>; sleep <interval_in_seconds>; done

ตัวอย่าง

while true; do ls; sleep 2; done

คำสั่งนี้จะพิมพ์เอาต์พุตของlsช่วงเวลา 2 วินาที

ใช้Ctrl+ Cเพื่อหยุดกระบวนการ

มีข้อบกพร่องเล็กน้อย watch

  • มันไม่สามารถใช้คำสั่งนามแฝงใด ๆ
  • หากผลลัพธ์ของคำสั่งใด ๆ ค่อนข้างยาวการเลื่อนจะไม่ทำงานอย่างถูกต้อง
  • มีปัญหาในการตั้งค่าช่วงเวลาสูงสุดเกินกว่าค่าที่กำหนด
  • watchจะตีความลำดับสี ANSI ผ่านอักขระเลี่ยงโดยใช้-cหรือ--colorตัวเลือก ยกตัวอย่างเช่นการส่งออกของpygmentizeจะทำงาน ls --color=autoแต่มันจะล้มเหลว

ในสถานการณ์ข้างต้นอาจปรากฏเป็นตัวเลือกที่ดีกว่า


watchมีอยู่สำหรับสิ่งนี้มันไร้ประโยชน์นิดหน่อยที่ฉันจะบอกว่า
บรูโน่เปเรร่า

14
ฉันไม่ได้อ้างว่าคำตอบนี้จะถูกใช้ตั้งแต่แรก watchเป็นสิ่งที่ดีในกรณีส่วนใหญ่ นั่นคือเหตุผลที่ฉันพูดถึง "นอกเหนือจากคำตอบของ nux" ที่จุดเริ่มต้น แต่มีปัญหาเล็กน้อยกับwatchตัวอย่างเช่น One ไม่สามารถใช้คำสั่ง aliasedwatchได้ ใช้ตัวอย่างllซึ่งเป็นนามแฝงแต่ไม่สามารถใช้กับls -laF watchนอกจากนี้ในกรณีที่ผลของคำสั่งใด ๆ watchที่ค่อนข้างนานคุณจะมีปัญหาในการเลื่อนการใช้ ในกรณีพิเศษเหล่านี้คำตอบนี้อาจเป็นตัวเลือกที่ดีกว่า
souravc

@souravc รุ่นของฉันwatchอย่างน้อยอนุญาต-cหรือ--colorตัวเลือกสำหรับผลลัพธ์ colorized
Lily Chung

8
while sleep xดีกว่า - ฆ่าง่ายกว่า
d33tah

3
นี่เป็นทางเลือกที่ดีและไม่เหมือนwatchกันที่มันเก็บประวัติคำสั่ง
adelriosantiago

34

แค่ต้องการที่จะเลือกคำตอบของsouravcและnux :

  1. ในขณะที่watchทำงานได้อย่างสมบูรณ์บน Ubuntu คุณอาจต้องการหลีกเลี่ยงถ้าคุณต้องการให้ "Unix-fu" ของคุณบริสุทธิ์ - บน FreeBSD ตัวอย่างเช่น watch คือคำสั่งให้ "สอดแนมในบรรทัด tty อื่น"
  2. while true; do command; sleep SECONDS; doneนอกจากนี้ยังมีข้อแม้ - คำสั่งของคุณอาจจะยากที่จะฆ่าโดยใช้CTR + C คุณอาจต้องการwhile sleep SECONDS; do command; done- ไม่เพียง แต่สั้นกว่า แต่ยังง่ายต่อการขัดจังหวะ ข้อแม้คือมันจะหลับก่อนแล้วจึงรันคำสั่งของคุณดังนั้นคุณจะต้องรอSECONDSก่อนที่คำสั่งแรกจะเกิดขึ้น

2
หวังว่ามันจะเป็นคำตอบที่ยอมรับได้แทนที่จะเป็นความคิดเห็น - ฉันต้องการแสดงวิธีแก้ไขปัญหาอื่นที่นี่และการแสดงความคิดเห็นจะทำให้ฉันสนใจน้อยลง
d33tah

ทำไมมันสำคัญไม่ว่าคุณใส่sleepในwhileวง? ฉันไม่พบความแตกต่างเลย Ctrl + C ก็วนลูปทันทีไม่ว่าจะเกิดอะไรขึ้น
ของหวาน

@ ขนมหวาน: ขึ้นอยู่กับสิ่งที่คุณพยายามจะแยกออกจากฉันเดา ปกติ CTRL + C ก็จะฆ่าคุณcommandและและมีเพียงทำลายถ้าคุณฆ่าsleep true
d33tah

11

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

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

ตัวอย่างเช่นหากคุณต้องการเรียกใช้สคริปต์ Python ในทุกวันอังคารเวลา 11.00 น.:

0 11 * * 1 python ~/yourscript.py

@rebootนอกจากนี้ยังมีบางชื่อพิเศษที่เปลี่ยนเวลาเช่น มีประโยชน์มากถ้าคุณต้องการสร้างไดเรกทอรีชั่วคราว จาก crontab ของฉัน (แสดงด้วยcrontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"

4
คำถามถามถึงวิธีการใช้งานบางสิ่งบางอย่างเป็นระยะ ๆ ในเครื่อง cronวิ่งตามเบื้องหลังมากกว่าในเทอร์มินัล
north-bradley

5

หากคุณกำลังตรวจสอบระบบไฟล์นั้นinotifywaitจะยอดเยี่ยมและแน่นอนจะเพิ่มการโหลดน้อยลงในระบบของคุณ

ตัวอย่าง:

ในเทอร์มินัลที่1พิมพ์คำสั่งนี้:

$ inotifywait .

จากนั้นในเทอร์มินัลที่2คำสั่งใด ๆ ที่มีผลต่อไดเรกทอรีปัจจุบัน

$ touch newfile

จากนั้นในเทอร์มินัลดั้งเดิมจะรอการแจ้งเตือนจะตื่นขึ้นมาและรายงานเหตุการณ์

./ CREATE newfile2

หรือเป็นวง

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.

ผู้ใช้บอกคุณว่าไม่มีสคริปต์และบางทีเขาอาจไม่ต้องการตรวจสอบสิ่งใดเลย
nux

3
ฉันไม่ได้บอกให้เขาเขียนสคริปต์ฉันแนะนำว่าถ้าพวกเขาวนลูป inorder เพื่อดูเหตุการณ์ระบบไฟล์เฉพาะ inotifywait นั้นมีประโยชน์และใช้ทรัพยากรน้อยกว่าการทำซ้ำคำสั่ง ฉันมักจะรันคำสั่งหลายคำสั่งในบรรทัดคำสั่งเช่นgrep something InALogFile|lessนั้นเป็นสคริปต์หรือไม่
X Tian

มันเป็นคำตอบที่ดีลองแก้ไขให้ดูง่ายขึ้น
nux

3
สิ่งที่อาจจะง่ายกว่าที่.ฉันไม่สามารถออกคำสั่ง
X Tian

ขอบคุณ @XTian คำสั่งที่ยอดเยี่ยม ตอนนี้ฉันเห็นในหน้าคนที่คุณสามารถเพิ่ม-mเพื่อตรวจสอบอย่างต่อเนื่องโดยไม่ต้องวนซ้ำ
yoniLavi

4

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

ก่อนอื่นให้เปิด.bash_aliasesไฟล์ของคุณ:

$ xdg-open ~/.bash-aliases

ประการที่สองวางบรรทัดเหล่านี้ที่ด้านล่างของไฟล์และบันทึก:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

ประการที่สามปิดและเปิดเทอร์มินัลของคุณอีกครั้งหรือพิมพ์:

$ source ~/.bash_aliases

และอื่น ๆ ! ตอนนี้คุณสามารถใช้มันได้เช่นนี้:

$ repeat 5 echo Hello World !!!

หรือ

$ repeat 5 ./myscript.sh

มีการพิมพ์ผิดขนาดเล็กในบรรทัด xdg-open ~ / .bash-aliases มันควรจะเป็น: xdg-open ~ / .bash_aliases (เช่น: ขีดเส้นใต้)
ssinfod

4

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

*/10 * * * *  /path-to-your-command

สิ่งนี้จะรันคำสั่งของคุณทุก ๆ 10 นาที

* */4 * * *  /path-to-your-command

สิ่งนี้จะรันคำสั่งของคุณทุก 4 ชั่วโมง

ทางออกที่เป็นไปได้อีกประการหนึ่ง

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

Xจำนวนครั้งที่จะทำซ้ำ

Yเวลารอที่จะทำซ้ำ

ตัวอย่าง:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done

เหตุใดการปรับปรุงจึงเป็นเช่นนี้ คุณเพิ่งเพิ่มขั้นตอนพิเศษที่ไม่จำเป็นโดยการบันทึกคำสั่งเป็นตัวแปร สิ่งเดียวที่ทำคือ i) ทำให้พิมพ์ได้นานขึ้น ii) บังคับให้คุณใช้คำสั่งง่าย ๆ เท่านั้นไม่มี
ไพพ์

ลบตัวแปรพิเศษ
Maythux

3

ข้อกังวลอีกประการหนึ่งของวิธีการ "เฝ้าดู" ที่เสนอข้างต้นก็คือมันจะแสดงผลลัพธ์เฉพาะเมื่อกระบวนการเสร็จสิ้น "date; sleep 58; date" จะแสดง 2 วันหลังจาก 59 วินาทีเท่านั้น ... หากคุณเริ่มบางสิ่งบางอย่างที่ทำงานเป็นเวลา 4 นาทีนั่นจะแสดงเนื้อหาหลายหน้าช้าคุณจะไม่เห็นมันจริงๆ

ในทางตรงกันข้ามความกังวลกับวิธี "ในขณะที่" คือการที่ไม่คำนึงถึงระยะเวลาของงานในการพิจารณา

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

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

ดังนั้นเมื่อต้องการดูเอาต์พุตบนเชลล์ในขณะที่มันถูกสร้างขึ้นและรอเวลาคำขอที่แน่นอนคุณต้องดูเวลาก่อนและหลังและวนลูปในขณะที่

สิ่งที่ต้องการ:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

สิ่งนี้จะเอาท์พุทนี้:

อย่างที่คุณเห็นคำสั่งรันทุกนาที:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

ดังนั้นเพียงแค่แทนที่echo $(( ( RANDOM % 30 ) + 1 ))คำสั่ง " sleep " ด้วยสิ่งที่คุณต้องการและจะรันบนเทอร์มินัล / เชลล์ทุกนาที หากคุณต้องการกำหนดการอื่นเพียงแค่เปลี่ยน "60" วินาทีกับสิ่งที่คุณต้องการ

เวอร์ชันที่สั้นกว่าโดยไม่มีบรรทัดดีบัก:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done

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