วิธีง่ายๆในการปล่อยให้คำสั่งทำงานเป็นเวลา 5 นาทีคืออะไร? [ซ้ำ]


66

คำถามนี้มีคำตอบอยู่ที่นี่แล้ว:

มีวิธีง่าย ๆ ในการปล่อยให้คำสั่งเฉพาะ (สามารถยกเลิกได้ผ่านCtrl-C) เรียกใช้โดยอัตโนมัติเป็นเวลา 5 นาทีหรือไม่?

ตัวอย่างเช่น:

minute-command 5-minutes ping www.google.com

หรือคำสั่งอื่นใดที่ไม่ได้ยุติลง

ฉันต้องการที่จะสามารถระบุการ จำกัด เวลาไม่เพียง 5 นาที

คำตอบ:


67

มี (อย่างน้อย) สองโปรแกรมที่ให้ฟังก์ชันการทำงานนี้:

ชื่อ

timelimit - จำกัด เวลาดำเนินการของกระบวนการอย่างมีประสิทธิภาพ

สรุป

timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]

และ

ชื่อ

timeout - รันคำสั่งด้วยการ จำกัด เวลา

สรุป

timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]

พวกเขาจะถูกบรรจุดังนี้:

$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout

เปรียบเทียบ:

/-----------------------------+------------+----------------\
|            Feature          |  timelimit |     timeout    |
+=============================+============+================+
|   time to run               | -t time    | first argument |
+-----------------------------+------------+----------------+
|   terminate signal          | -s signal  | -s signal      |
+-----------------------------+------------+----------------+
|   grace period              | -T time    | -k time        |
+-----------------------------+------------+----------------+
|   kill signal               | -S signal  | (note 1)       |
+-----------------------------+------------+----------------+
|   propagate signals         | -p         | (note 2)       |
\-----------------------------+------------+----------------/

หมายเหตุ:

  1. timeoutใช้SIGKILLเป็นสัญญาณสุดท้ายเสมอ
  2. timeout ไม่มีฟังก์ชั่นใด ๆ เพื่อออกจากสัญญาณเมื่อโปรแกรมลูกทำงาน

สถานะการออกของทั้งสองโปรแกรมนั้นแตกต่างกันไป แต่ก็ยากที่จะสรุปอย่างเรียบร้อยดังนั้นฉันขอแนะนำให้คุณศึกษาหน้าคู่มือด้วยตนเอง

ขณะที่timeoutมีการติดตั้งในระบบมากขึ้นโดยเริ่มต้น ( coreutilsเป็นแพคเกจมาตรฐานในการกระจายจำนวนมาก) timelimitผมขอแนะนำให้คุณใช้ว่าถ้าคุณต้องทำงานพิเศษให้โดย


10
ทำไมคุณถึงใช้อันใดอันหนึ่งมากกว่าอีกอันหนึ่ง?
Brice M. Dempsey

2
@ BriceM.Dempsey บนเครื่องของฉันหมดเวลาแล้ว แต่ timelimit ไม่ได้ (แม้ว่า repo จะพร้อมใช้งาน) ดังนั้นหากหนึ่งในนั้นติดตั้งมาล่วงหน้า ... นอกเหนือจากนั้นเพียงแค่ดูที่ลายเซ็นวิธีที่ฉันเห็นว่าพวกเขาทำสิ่งต่าง ๆ และมีกรณีการใช้ที่แตกต่างกัน
Benubird

โปรดทราบว่ามีการใช้งานอย่างน้อยสองtimelimitรายการ ดูฉันจะฆ่ากระบวนการได้อย่างไรและตรวจสอบให้แน่ใจว่า PID ไม่ได้ถูกนำมาใช้ซ้ำสำหรับข้อมูลเพิ่มเติมเกี่ยวกับพวกเขาและการหมดเวลาของ GNU
sch

1
@ BriceM.Dempsey timeoutจะรวมอยู่ใน GNU coreutils , timelimitไม่ได้ คุณสามารถติดตั้งได้ไม่อย่างใดอย่างหนึ่งหรือทั้งสอง สำหรับวินาทีนั้นมีการรายงานtimelimit ดำเนินการคำสั่งและยุติกระบวนการที่เกิดหลังจากช่วงเวลาที่กำหนดด้วยสัญญาณที่กำหนด สัญญาณ“ คำเตือน” จะถูกส่งก่อนจากนั้นหลังจากหมดเวลาสัญญาณ“ ฆ่า” ซึ่งคล้ายกับวิธีที่ init (8) ทำงานเมื่อปิดเครื่อง ดังนั้นแม้จะมีความแตกต่างในพฤติกรรมตรงกลาง
Hastur

เนื่องจาก GNU coreutils ติดตั้งไว้แล้วใน GNU / Linux ทุกเครื่องtimeoutเป็นวิธีที่จะไป
rexkogitans

87

จริงๆแล้วนี่คือสิ่งที่timeoutมีไว้สำหรับ:

TIMEOUT(1)                          User Commands                         TIMEOUT(1)

NAME
       timeout - run a command with a time limit

SYNOPSIS
       timeout [OPTION] DURATION COMMAND [ARG]...
       timeout [OPTION]

DESCRIPTION
       Start COMMAND, and kill it if still running after DURATION.

lx@lxtp:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout

16

bashสร้างขึ้นในบริสุทธิ์โดยไม่ต้องcoreutils

ฉันพบว่าโซลูชันนี้ทำงานbashโดยอาศัยคำสั่งในตัวโดยไม่ต้องเรียกใช้งานจากภายนอก มันทำงานบนระบบที่ไม่ได้ติดตั้งcoreutils ในที่สุด [ 1 ]

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 

คำอธิบาย : ตามปกติเมื่อคุณส่งคำสั่งในพื้นหลังที่มี&, PID ของมันจะถูกเก็บไว้ในตัวแปรภายใน$!(ปัจจุบันในรุ่นที่ทันสมัยdash, csh, bash, tcsh, zsh... )
จริงๆสิ่งที่ทำให้ความแตกต่างระหว่างเปลือกหอยคือการปรากฏตัวของในตัวคำสั่งread[ 2 ]-tและตัวเลือก ในรุ่นที่ 1 หากผู้ใช้จะไม่กรอกข้อมูลในบรรทัดก่อนจำนวนวินาทีที่ระบุคำสั่งจะถูกยกเลิกและรหัสการส่งคืนข้อผิดพลาดจะถูกสร้างขึ้น

-t TIMEOUT สาเหตุที่อ่านเพื่อหมดเวลาและส่งคืนความล้มเหลวหากไม่ได้อ่านบรรทัดที่สมบูรณ์ของอินพุตภายใน TIMEOUT วินาที

รุ่นที่สองทำงานเป็นที่ 1 enterแต่คุณสามารถยกเลิกหมดเวลาการฆ่าเพียงแค่กด
อันที่จริงหรือผู้||ดำเนินการดำเนินการkillคำสั่งเฉพาะในกรณีที่readคำสั่งออกด้วยรหัสกลับแตกต่างจากศูนย์เช่นเมื่อหมดเวลาการหมดอายุ หากคุณกดenterก่อนเวลานั้นมันจะคืนค่า 0 และจะไม่ฆ่าคำสั่งก่อนหน้าของคุณ


วิธีแก้ปัญหา Coreutils [ 1 ]

เมื่อcoreutilsที่มีอยู่ในระบบของคุณและคุณไม่จำเป็นต้องประหยัดเวลาและทรัพยากรที่จะเรียกใช้โปรแกรมภายนอก, timeoutและsleepและมีทั้งวิธีการที่สมบูรณ์แบบเพื่อบรรลุเป้าหมายของคุณ

timeoutการใช้timeoutตรงไปตรงมา
ในที่สุดคุณสามารถพิจารณาที่จะใช้-kตัวเลือกในการส่งสัญญาณฆ่าเพิ่มเติมถ้าครั้งแรกล้มเหลว

timeout 5m YourCommand                                         # 3rd version 

sleep ด้วยsleepคุณสามารถใช้จินตนาการของคุณหรือใช้แรงบันดาลใจบาง[ 3 ] โปรดทราบว่าคุณสามารถออกจากคำสั่งของคุณในพื้นหลังหรือเบื้องหน้า (เช่นtopมักจะต้องอยู่ในเบื้องหน้า)

YourCommand & sleep 5m; kill $!                                # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) &                # 5th Background

bash -c '(sleep 5m; kill $$) & exec YourCommand'               # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground

คำอธิบาย

  • ในเวอร์ชั่นที่ 4 คุณดำเนินการในพื้นหลังYourCommandแล้วเชลล์ของคุณsleepเป็นเวลา 5 นาที เมื่อมันจะเสร็จสิ้นกระบวนการพื้นหลังสุดท้าย ( $!) จะถูกฆ่า คุณหยุดเปลือกของคุณ
  • ในรุ่นที่ 5 แทนคุณดำเนินการในพื้นหลังYourCommandและคุณสามารถจัดเก็บได้ทันทีว่า PID $pidในตัวแปร จากนั้นคุณดำเนินการงีบหลับในพื้นหลัง5 นาทีและคำสั่งที่ตามมาที่จะฆ่า PID ที่เก็บไว้ เมื่อคุณส่งคำสั่งกลุ่มนี้ในพื้นหลังคุณจะไม่หยุดเชลล์ คุณต้องจัดเก็บ PID ในตัวแปรเนื่องจาก$!สามารถอัปเดตค่าได้โดยการดำเนินการในที่สุดของโปรแกรมอื่นในพื้นหลัง ในคำง่ายๆคุณหลีกเลี่ยงความเสี่ยงที่จะฆ่ากระบวนการที่ผิดหรือไม่มีกระบวนการเลย
  • ในรุ่นที่ 6 เรียกว่า bash shell ใหม่ที่จะฆ่าตัวตายใน 5 นาที$$จากนั้นจะถูกดำเนินการตามคำสั่งของคุณที่ยังคงอยู่เบื้องหน้า
  • ในรุ่นที่ 7 จะมีการเรียกใช้ subshell ()ที่เก็บ PID ของมันในตัวแปร ( cmdpid) และฆ่าตัวเองด้วย subshell อื่นที่ส่งในการดำเนินการพื้นหลังแล้วรัน YourCommand ในเบื้องหน้า

แน่นอนในแต่ละรุ่นคุณสามารถส่งสัญญาณการฆ่าที่คุณต้องการจากค่าเริ่มต้นไปยังสุดขีด kill -9เพื่อใช้เมื่อจำเป็นจริงๆเท่านั้น

อ้างอิง

  • [ 1 ] The Coreutils
  • [ 2 ] The Bash Beginners Guide
  • [ 3 ] The BashFAQ

2
"ด้วยการนอนหลับคุณสามารถใช้จินตนาการของคุณหรือรับแรงบันดาลใจ [ลิงก์ไปยังคำถามที่พบบ่อยเกี่ยวกับ Bash]" +1 #thatsenoughinternetfortoday
joeytwiddle

11

สำหรับกรณีเฉพาะของคุณการpingสนับสนุนการใช้งานส่วนใหญ่-cหรือ--countการยกเลิกหลังจากการ Ping จำนวนหนึ่ง:

ping -c 300 host.example.com

สำหรับคำตอบทั่วไปเพิ่มเติมดูคำตอบอื่น ๆ


7
ฉันได้รับความประทับใจจาก OP ที่ให้pingไว้เพื่อเป็นตัวอย่าง เขาไม่ต้องการโซลูชันเป็นกรณี ๆ สำหรับโปรแกรมที่แตกต่างกัน
user1717828

8

คุณสามารถทำได้ด้วยสคริปต์ง่ายๆเช่นนี้:

#!/bin/bash

#
# $1 is the time to let the program run, and $2, $3, ... are the command itself.
#

"${@:2}" &
PID=$!
sleep "${@:1:1}"
kill -2 $PID

(สัญญาณ SIGINT = 2 ใช้ตามคำแนะนำของ Matija Nalis ในความคิดเห็นด้านล่าง)

คำอธิบายของนิพจน์ bash (ผิดปกติ?) $@:...: พารามิเตอร์ตำแหน่ง ( $*, $@, "$*", "$@") ยอมรับข้อกำหนดพิเศษต่อไปนี้ตัวอย่างเช่น:

"${@:START:COUNT}"

ซึ่งหมายความว่า: ของพารามิเตอร์ทั้งหมดใช้ COUNT ของพวกเขาคนแรกที่จะได้รับการที่ตำแหน่งเริ่มต้น; หากไม่นับ COUNT ให้ดำเนินการจนจบโดยเริ่มจากตำแหน่งเริ่มต้น จำไว้ว่า$0เป็นชื่อโปรแกรม ถ้าเริ่มเป็นลบเริ่มนับจากปลายและจำ COUNT ที่ไม่สามารถ"${@:-1}"เป็นลบจึงอาร์กิวเมนต์สุดท้ายคือ นอกจากนี้เพียงแค่เกี่ยวกับเสมอรวมถึงพารามิเตอร์ตำแหน่งภายในราคาคู่


1
ฉันอาจออกแบบสคริปต์เพื่อใช้เวลาเป็น arg แรกหรือสุดท้ายและเรียกใช้ args อื่น ๆ ทั้งหมดเป็นคำสั่ง การปล่อยให้แบ่งคำทุบตี$1เป็นขั้นต้นสวย นอกจากนี้คุณยังสามารถsleep "$1"หรือบางสิ่งบางอย่างcountdownค่ะ
Peter Cordes

1
@PeterCordes เสร็จตามความต้องการของคุณ
MariusMatutiae

เวลาในการหาเรื่องแรกให้คุณทำtime=$1; shiftแล้วคุณไม่จำเป็นต้องใช้ไวยากรณ์การแบ่งส่วนข้อมูลสำหรับพารามิเตอร์ตำแหน่ง แต่ใช่ว่าง่ายกว่ามาก
Peter Cordes

1
@PeterCordes เห็นด้วย แต่คุณขอให้ฉันดูว่าฉันรู้วิธีที่ปลอดภัยกว่าหรือไม่และฉันเพิ่งขี้เกียจหรือว่าฉันแค่ไม่รู้เฉย ฮ่า ๆ.
MariusMatutiae

ตามที่ผู้โพสต์ถามเกี่ยวกับโปรแกรมที่สามารถถูกขัดจังหวะctrl-cได้ควรลองkill -INTใช้แทนkill -9(หรืออย่างน้อยลอง-9หลังจากนั้นไม่กี่วินาทีหากโปรแกรมแรกไม่สำเร็จ - มันเปิดโอกาสให้โปรแกรมออกอย่างหมดจดและไม่ปล่อยไฟล์ชั่วคราว ฯลฯ )
Matija Nalis

5

เมื่อคุณพูดถึงpingในตัวอย่างของคุณ; คำสั่งนี้มีตัวเลือกให้หยุดหลังจากเวลาที่กำหนด:

  • w กำหนด เวลาหมดเวลาเป็นวินาทีก่อนที่pingจะออกโดยไม่คำนึงถึงจำนวนแพ็กเก็ตที่ได้รับหรือส่ง ในกรณีนี้pingไม่หยุดหลังจากส่งแพ็กเก็ตการนับมันจะรอจนกว่ากำหนดเวลาหมดอายุหรือจนกว่าจะมีการตอบรับการตรวจนับหรือการแจ้งเตือนข้อผิดพลาดบางอย่างจากเครือข่าย
  • W หมดเวลา เวลาในการรอการตอบสนองในไม่กี่วินาที ตัวเลือกมีผลต่อการหมดเวลาใช้งานหากไม่มีการตอบสนองใด ๆ มิฉะนั้นpingจะรอสอง RTT

-man ping

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