รับเวลาดำเนินการโปรแกรมในเชลล์


407

ฉันต้องการดำเนินการบางอย่างใน linux shell ภายใต้เงื่อนไขที่แตกต่างกันเล็กน้อยและสามารถส่งออกเวลาดำเนินการของการดำเนินการแต่ละครั้ง

ฉันรู้ว่าฉันสามารถเขียนสคริปต์ Perl หรือหลามที่จะทำเช่นนี้ แต่มีวิธีที่ฉันสามารถทำได้ในเปลือก? (ซึ่งเกิดขึ้นจะทุบตี)



เป็นไปได้ที่จะได้รับTicksเช่นกรณี windows หรือไม่
freeforall tousez

คำตอบ:


534

ใช้timeคำสำคัญในตัว:

$ เวลาช่วยเหลือ

เวลา: เวลา [-p] PIPELINE
    ดำเนินการ PIPELINE และพิมพ์สรุปเวลาจริงเวลา CPU ของผู้ใช้
    และเวลา CPU ของระบบที่ใช้ในการดำเนินการ PIPELINE เมื่อสิ้นสุด
    สถานะการส่งคืนคือสถานะการส่งคืนของ PIPELINE ตัวเลือก `-p '
    พิมพ์ข้อมูลสรุปเวลาในรูปแบบที่แตกต่างกันเล็กน้อย สิ่งนี้ใช้
    ค่าของตัวแปร TIMEFORMAT เป็นรูปแบบเอาต์พุต

ตัวอย่าง:

$ time sleep 2
จริง 0m2.009s
ผู้ใช้ 0m0.000s
sys 0m0.004s

1
สิ่งนี้ถูกใช้กับคำสั่งtime -p i=x; while read line; do x=x; done < /path/to/file.txtอย่างไร มันจะคืน 0.00 ทันทีถ้าฉันไม่ใส่อะไรเลยก่อนลูป .. จะให้อะไร
natli

นี่เป็นรุ่น 'เวลา' ที่น่าสงสาร คำสั่ง 'เวลา' ภายนอกอยู่ที่ไหน
Znik

6
@ Znik ลอง / usr / bin / เวลา
Mark Rajcok

10
@natli: ในขณะที่timeสามารถตั้งเวลาไปป์ไลน์ทั้งหมดตามที่เป็นอยู่ (โดยอาศัยการเป็นคีย์เวิร์ด Bash ) คุณต้องใช้คำสั่งกลุ่ม ( { ...; ...; }) เพื่อใช้เวลากับคำสั่งหลายคำสั่ง:time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }
mklement0

2
หากต้องการดูเวลาทั้งหมดที่คุณติดตั้งบนระบบของคุณคุณสามารถใช้type -a time
spinup

120

คุณจะได้รับข้อมูลรายละเอียดมากขึ้นกว่าทุบตีในตัวtime(ซึ่งโรเบิร์ตกล่าว Gamble) โดยใช้เวลา (1) /usr/bin/timeปกตินี้คือ

หมายเหตุบรรณาธิการ: เพื่อให้แน่ใจว่าคุณกำลังเรียกใช้ยูทิลิตี้ภายนอก timeมากกว่าเปลือกของtime คำหลัก/usr/bin/timeขอร้องว่ามันเป็น
timeเป็นยูทิลิตี้ POSIX ได้รับคำสั่ง-pแต่ตัวเลือกเดียวที่จะต้องสนับสนุน
แพลตฟอร์มเฉพาะใช้ส่วนขยายเฉพาะที่ไม่ได้มาตรฐาน: -vทำงานร่วมกับยูทิลิตี้ของGNUtimeดังที่แสดงด้านล่าง (คำถามถูกติดแท็ก); BSD / MacOS ใช้การดำเนิน-lการผลิตผลผลิตที่คล้ายกัน - man 1 timeดู

ตัวอย่างของการส่งออก verbose:


$ /usr/bin/time -v sleep 1
       Command being timed: "sleep 1"
       User time (seconds): 0.00
       System time (seconds): 0.00
       Percent of CPU this job got: 1%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.05
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 0
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 210
       Voluntary context switches: 2
       Involuntary context switches: 1
       Swaps: 0
       File system inputs: 0
       File system outputs: 0
       Socket messages sent: 0
       Socket messages received: 0
       Signals delivered: 0
       Page size (bytes): 4096
       Exit status: 0


2
คุณจะไม่ทราบว่าแพ็กเกจเดเบียนอะไรที่จะมาจากไหน ดูเหมือนจะไม่ได้รับการติดตั้งเป็นค่าเริ่มต้น
ʞɔıu

1
ฉันอ้างอิงโพสต์ของคุณโรเบิร์ต ถ้าคุณหมายถึงคำสั่งที่คุณแนะนำไม่ใช่ bash ในตัว?
grepsedawk

24
น่าประหลาดใจที่มันถูกติดตั้งจากแพ็คเกจที่เรียกว่า "เวลา"
พอลทอมบลิน

2
ผลลัพธ์จาก / usr / bin / เวลาดูเหมือนว่า "0.00user 0.00system 0: 02.00 ที่ผ่านมา 0% CPU (0avgtext + 0avgdata 0maxresident) k 0inputs + 0 Outputs (0major + 172minor) pagefaults 0swaps"
Paul Tomblin

4
@Nick: "sudo apt-get เวลาติดตั้ง"
Robert Gamble

79
#!/bin/bash
START=$(date +%s)
# do something
# start your script work here
ls -R /etc > /tmp/x
rm -f /tmp/x
# your logic ends here
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

14
มีวิธีที่ง่ายกว่ามาก Bash คำนวณตัวแปรพิเศษ $ SECONDS โดยอัตโนมัติจากนั้นคำนวณใหม่ตามคำสั่งวันที่ภายนอกไม่จำเป็น ตัวแปร $ SECONDS เก็บจำนวนสคริปต์ bash ที่กำลังทำงานอยู่เมื่อเริ่มทำงาน ตัวแปรนี้มีคุณสมบัติพิเศษบางอย่าง ดูหน้าคน: D
Znik

ฉันได้ลองทั้งวิธีข้างต้นและวิธีการในความคิดเห็น ในวันที่ 1 ฉันได้รับข้อผิดพลาด 'ตัวแปรที่ผิดกฎหมาย' และอันดับที่ 2 ฉันได้รับ 'ตัวแปรที่ไม่ปรากฏชื่อ'
DrBwts

45

สำหรับบรรทัดโดยบรรทัดวัดเดลต้าพยายามแสงแดด

ยูทิลิตีบรรทัดคำสั่งซึ่งคล้ายกับ ts มากขึ้นของutilsเพื่อเตรียมข้อมูลการประทับเวลาให้กับเอาต์พุตมาตรฐานของคำสั่งอื่น มีประโยชน์สำหรับกระบวนการที่ต้องใช้เวลานานซึ่งคุณต้องการให้บันทึกประวัติของสิ่งที่ใช้เวลานาน

นอกจากนี้คุณยังสามารถใช้--highและ / หรือ--mediumตัวเลือกเพื่อระบุขีดจำกัดความยาวเป็นวินาทีซึ่ง gnomon จะเน้นเวลาประทับเป็นสีแดงหรือสีเหลือง และคุณสามารถทำสิ่งอื่น ๆ ได้เช่นกัน

ตัวอย่าง


3
เคล็ดลับที่ดี แต่ต้องชัดเจน: นี่เป็นประโยชน์สำหรับการกำหนดเวลาแบบบรรทัดต่อบรรทัดแต่ค่าโสหุ้ยในการกำหนดเวลาที่ละเอียดเช่นนี้จะเพิ่มเวลาโดยรวมอย่างมีนัยสำคัญ
mklement0

2
อรรถประโยชน์ที่ยอดเยี่ยม .. ขอบคุณสำหรับการแบ่งปัน
Kishan B

19

หากคุณต้องการความแม่นยำมากขึ้นให้ใช้%Nกับdate(และใช้bcสำหรับ diff เพราะ$(())จะจัดการเฉพาะจำนวนเต็ม)

นี่คือวิธีการ:

start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)

printf "Execution time: %.6f seconds" $dur

ตัวอย่าง:

start=$(date +%s.%N); \
  sleep 0.1s; \
  dur=$(echo "$(date +%s.%N) - $start" | bc); \
  printf "Execution time: %.6f seconds\n" $dur

ผลลัพธ์:

Execution time: 0.104623 seconds

15

หากคุณตั้งใจจะใช้เวลาในการคำนวณในภายหลังเรียนรู้วิธีใช้-fตัวเลือกใน/usr/bin/timeการส่งออกรหัสที่ช่วยประหยัดเวลา นี่คือโค้ดบางส่วนที่ฉันใช้เมื่อเร็ว ๆ นี้เพื่อรับและจัดเรียงเวลาดำเนินการของโปรแกรมนักเรียนที่มีระดับทั้งหมด:

fmt="run { date = '$(date)', user = '$who', test = '$test', host = '$(hostname)', times = { user = %U, system = %S, elapsed = %e } }"
/usr/bin/time -f "$fmt" -o $timefile command args...

ต่อมาฉันก็ตัดแบ่งทั้งหมด $timefileไฟล์และท่อส่งออกให้เป็นล่าม Lua คุณสามารถทำเช่นเดียวกันกับ Python หรือทุบตีหรือสิ่งที่ไวยากรณ์ที่คุณชื่นชอบคือ ฉันรักเทคนิคนี้


หมายเหตุ: เส้นทางแบบเต็ม/usr/bin/timeจำเป็นเนื่องจากแม้ว่าwhich timeจะบอกคุณเป็นอย่างอื่นหากคุณเพียงเรียกใช้timeมันจะเรียกใช้เวอร์ชันของเชลล์timeซึ่งไม่ยอมรับอาร์กิวเมนต์ใด ๆ
Kevin Dice

ฉันจะไปกับenv time:-)
Ciro Santilli 郝海东冠状病六四事件法轮功

13

หากคุณต้องการความแม่นยำเพียงวินาทีคุณสามารถใช้$SECONDSตัวแปรbuiltin ซึ่งนับจำนวนวินาทีที่เชลล์รันอยู่

while true; do
    start=$SECONDS
    some_long_running_command
    duration=$(( SECONDS - start ))
    echo "This run took $duration seconds"
    if some_condition; then break; fi
done

10

คุณสามารถใช้timeและsubshell () :

time (
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
)

หรือในเปลือกเดียวกัน{}:

time {
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
}

คุณโพสต์โค้ดสองชุดที่เหมือนกัน คุณต้องตั้งใจทำสิ่งที่แตกต่าง
stason

3
@StasBekman ไม่เป็นความจริงใช้(งานครั้งแรก& )(บริบทใหม่, subshell ), และอื่น ๆ ด้วย{& }(เชลล์เดียวกัน, บริบทเดียวกัน)
Eduardo Cuomo

Aha! ฉันดูหนักทั้งสองและไม่เห็นความแตกต่าง ขอบคุณสำหรับการชี้แจงว่า {} vs ()
stason

2

วิธีคือ

$ > g++ -lpthread perform.c -o per
$ > time ./per

ผลลัพธ์คือ >>

real    0m0.014s
user    0m0.010s
sys     0m0.002s

ไม่จำเป็นต้องใช้-lphtreadหรือ-oแท็ก เพียงแค่ต้องใช้timeคำสั่งซึ่งคำตอบที่ยอมรับนั้นอธิบายได้ดีกว่า
เดนนิส

7
มันเป็นตัวอย่างนั่นคือ perform.c ของฉันมีเธรดดังนั้นฉันต้องการ -lpthread และสำหรับตัวตนที่เรียบง่ายมันคือ -o ต่อ
Robel Sharma

0

วิธีการหนึ่งอาจเป็นวิธีง่าย ๆ (ที่อาจไม่ตรงกับความต้องการของผู้ใช้ที่แตกต่างกัน) คือการใช้เชลล์ PROMPT.it เป็นวิธีแก้ปัญหาง่ายๆที่อาจมีประโยชน์ในบางกรณี คุณสามารถใช้คุณสมบัติการแจ้งเตือน bash ดังตัวอย่างด้านล่าง:

ส่งออก PS1 = '[\ t \ u @ \ h] \ $' 

คำสั่งดังกล่าวจะส่งผลให้การเปลี่ยน shell prompt เป็น:

[HH: MM: SS ชื่อผู้ใช้ @ hostname] $ 

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

หมายเหตุ:
1)ระวังว่าถ้าคุณรอสักครู่ก่อนที่คุณจะพิมพ์คำสั่งถัดไปของคุณเวลานี้จะต้องพิจารณาเช่นเวลาที่แสดงใน shell prompt คือ timestamp เมื่อ shell prompt แสดงไม่ใช่เมื่อคุณป้อนคำสั่ง ผู้ใช้บางคนเลือกที่จะกดปุ่ม Enter เพื่อรับพรอมต์ใหม่ด้วยการประทับเวลาใหม่ก่อนที่พวกเขาจะพร้อมสำหรับคำสั่งต่อไป
2)มีตัวเลือกและโมดิฟายเออร์อื่น ๆ ที่สามารถใช้ในการเปลี่ยน bash prompt, อ้างถึง (man bash) สำหรับรายละเอียดเพิ่มเติม


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