จะเปลี่ยนเส้นทางเอาต์พุตของคำสั่ง time ไปยังไฟล์ใน Linux ได้อย่างไร?


202

เพียงคำถามเล็กน้อยเกี่ยวกับโปรแกรมกำหนดเวลาบน Linux: คำสั่ง time ช่วยให้สามารถวัดเวลาดำเนินการของโปรแกรมได้:

[ed@lbox200 ~]$ time sleep 1

real    0m1.004s
user    0m0.000s
sys     0m0.004s

ซึ่งใช้งานได้ดี แต่ถ้าฉันพยายามเปลี่ยนเส้นทางไปยังไฟล์มันจะล้มเหลว

[ed@lbox200 ~]$ time sleep 1 > time.txt

real    0m1.004s
user    0m0.001s
sys     0m0.004s

[ed@lbox200 ~]$ cat time.txt 
[ed@lbox200 ~]$ 

ฉันรู้ว่ามีการใช้งานอื่น ๆ ของเวลาด้วยตัวเลือก -o เพื่อเขียนไฟล์ แต่คำถามของฉันเกี่ยวกับคำสั่งโดยไม่มีตัวเลือกเหล่านั้น

ข้อเสนอแนะใด ๆ


3
ซ้ำกันเป็นไปได้ของสคริปต์ทุบตีเขียนเวลาดำเนินการในไฟล์และฉันก็ยังห่างไกลจากความเชื่อมั่นว่านี่เป็นคำถามแรก
Jonathan Leffler

1
นี่เป็นข้อมูลซ้ำซ้อนของstackoverflow.com/questions/2408981/…
codeforester

คำตอบ:


266

ลอง

{ time sleep 1 ; } 2> time.txt

ซึ่งรวม STDERR ของ "เวลา" และคำสั่งของคุณลงใน time.txt

หรือใช้

{ time sleep 1 2> sleep.stderr ; } 2> time.txt

ซึ่งทำให้ STDERR จาก "sleep" ลงในไฟล์ "sleep.stderr" และมีเพียง STDERR จาก "time" เท่านั้นที่จะเข้าสู่ "time.txt"


2
ขอบคุณที่ตอบคำถามของฉันอย่างแม่นยำ หากฉันเข้าใจถูกต้องผลลัพธ์ของคำสั่ง time สามารถรับได้จาก stderr
ed82

7
ใช่ แต่คุณต้องวางไว้ในวงเล็บปีกกามิฉะนั้นการเปลี่ยนเส้นทางจะเป็นส่วนหนึ่งของคำสั่งที่timeประเมิน
มกราคม

5
@Daniel คุณสามารถเปลี่ยนเส้นทางผลลัพธ์คำสั่งภายในแยกต่างหาก (เช่น {time sleep 1 2> sleepStdErr.txt;} 2> time.txt) และนั่นจะทำให้คุณได้รับผลลัพธ์เวลาเท่านั้น ฉันไม่แน่ใจว่ามีวิธีที่จะแยกเป็นอิสระหรือไม่
gms7777

10
หากคุณต้องการที่จะใช้เวลากับสิ่งที่ต้องการ grep ที่อ่านออกจาก stdout { time sleep 1; } 2>&1 | grep realลอง ส่ง stderr ไปที่ stdout ซึ่ง grep สามารถอ่านได้
clayzermk1

9
อย่าลืม ';' ตัวละครก่อนที่จะปิด '}' มันจะไม่ทำงานถ้าไม่มี (ฉันทำแล้ว ... สงสัยว่าทำไมมันไม่ทำงาน :))
THESorcerer

38

Wrap timeและคำสั่งที่คุณกำหนดเวลาไว้ในชุดของวงเล็บ

ตัวอย่างเช่นเวลาต่อไปนี้lsและเขียนผลลัพธ์ของlsและผลลัพธ์ของการจับเวลาลงในoutfile:

$ (time ls) > outfile 2>&1

หรือหากคุณต้องการแยกเอาต์พุตของคำสั่งจากเอาต์พุตที่จับจากtime:

$ (time ls) > ls_results 2> time_results

12
ไม่จำเป็นต้องแนะนำ subshell ที่นี่
มกราคม

1
@ sampson-chen ใช้งานได้เพราะ ls ไม่ได้เขียนอะไรถึง stderr ใช่มั้ย คุณจะ "แยก" เอาต์พุตของ 'เวลา' จากคำสั่งที่จะรันได้อย่างไรหากคำสั่งเขียนไปยัง stdout และ stderr
David Doria

36

ง่าย timeยูทิลิตี้GNU มีตัวเลือกสำหรับสิ่งนั้น

แต่คุณต้องมั่นใจว่าคุณไม่ได้ใช้timeคำสั่งbuiltin ของเชลล์อย่างน้อยbashbuiltin จะไม่ให้ตัวเลือกนั้น! นั่นเป็นเหตุผลที่คุณต้องให้เส้นทางแบบเต็มของtimeยูทิลิตี้:

/usr/bin/time -o time.txt sleep 1

นอกจากนี้คุณยังสามารถใช้ตัวเครื่องได้โดยไม่ต้องระบุเส้นทางแบบเต็ม: stackoverflow.com/questions/29540540/…
Ciro Santilli 郝海东冠状病病六四事件法轮功

14

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

{ time your_command 2> command.err ; } 2> time.log

หรือ

{ time your_command 2>1 ; } 2> time.log

เมื่อคุณเห็นข้อผิดพลาดของคำสั่งให้ไปที่ไฟล์ (เนื่องจากstderrใช้สำหรับtime)

น่าเสียดายที่คุณไม่สามารถส่งไปที่หมายเลขอ้างอิงอื่น (เช่น3>&2) เนื่องจากจะไม่มีอยู่อีกต่อไปนอก{...}

ที่กล่าวว่าหากคุณสามารถใช้เวลา GNU เพียงทำในสิ่งที่ @Tim Ludwinski พูด

\time -o time.log command

8

เนื่องจากเอาต์พุตของคำสั่ง 'time' คือเอาต์พุตข้อผิดพลาดให้เปลี่ยนทิศทางเนื่องจากเอาต์พุตมาตรฐานจะใช้งานได้ง่ายกว่าในการประมวลผลเพิ่มเติม

{ time sleep 1; } 2>&1 |  cat > time.txt

6

หากคุณใช้เวลา GNU แทน bash ในตัวให้ลอง

time -o outfile command

(หมายเหตุ: รูปแบบเวลาของ GNU แตกต่างจาก bash ในตัวเล็กน้อย)


1
นี่ขอบคุณ และคุณสามารถใช้\time -o outfile command(พร้อม ``) เพื่อใช้ GNU แทนการใช้งานได้ในตัว
ทำเครื่องหมาย

3
&>out time command >/dev/null

ในกรณีของคุณ

&>out time sleep 1 >/dev/null

แล้วก็

cat out

3
แนวคิดหรูหรา แต่นำไปสู่เชลล์ไม่ได้ใช้คำสั่งในตัว หากคุณไม่ได้มีจริงtimeไบนารีติดตั้งจะมีสิ่งที่ชอบout bash: time: command not found
scy

รูปแบบสำหรับเวลา GNU นั้นไม่เหมือนกับ bash builtin ซึ่งทำให้เกิดปัญหาในการวิเคราะห์คำอัตโนมัติ
Guss

3

ฉันสิ้นสุดการใช้:

/usr/bin/time -ao output_file.txt -f "Operation took: %E" echo lol
  • ที่ "a" ต่อท้ายอยู่ที่ไหน
  • ตำแหน่ง "o" ถูกดำเนินการโดยชื่อไฟล์ที่ต้องการผนวก
  • โดยที่ "f" เป็นรูปแบบที่มีไวยากรณ์เหมือน printf
  • ที่ "% E" ผลิต 0:00:00; ชั่วโมง: นาที: วินาที
  • ฉันต้องเรียกใช้ / usr / bin / time เพราะ bash "time" ถูกเหยียบย่ำและไม่มีตัวเลือกเดียวกัน
  • ฉันแค่พยายามเอาท์พุทไปที่ไฟล์ไม่ใช่สิ่งเดียวกับ OP

2
#!/bin/bash

set -e

_onexit() {
    [[ $TMPD ]] && rm -rf "$TMPD"
}

TMPD="$(mktemp -d)"
trap _onexit EXIT

_time_2() {
    "$@" 2>&3
}

_time_1() {
    time _time_2 "$@"
}

_time() {
    declare time_label="$1"
    shift
    exec 3>&2
    _time_1 "$@" 2>"$TMPD/timing.$time_label"
    echo "time[$time_label]"
    cat "$TMPD/timing.$time_label"
}

_time a _do_something
_time b _do_another_thing
_time c _finish_up

สิ่งนี้มีประโยชน์ในการไม่วางไข่เชลล์ย่อยและไปป์ไลน์สุดท้ายมี stderr ที่คืนค่าเป็น stderr จริง


0

หากคุณไม่ต้องการสัมผัส stdout ของกระบวนการดั้งเดิมและ stderr คุณสามารถเปลี่ยนเส้นทาง stderr ไปยัง file descriptor 3 และย้อนกลับได้:

$ { time { perl -le "print 'foo'; warn 'bar';" 2>&3; }; } 3>&2 2> time.out
foo
bar at -e line 1.
$ cat time.out

real    0m0.009s
user    0m0.004s
sys     0m0.000s

คุณสามารถใช้สิ่งนั้นสำหรับ wrapper (เช่น cronjobs) เพื่อตรวจสอบ runtimes:

#!/bin/bash

echo "[$(date)]" "$@" >> /my/runtime.log

{ time { "$@" 2>&3; }; } 3>&2 2>> /my/runtime.log

0

หากคุณใช้cshคุณสามารถใช้:

/usr/bin/time --output=outfile -p $SHELL  -c 'your command'

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

/usr/bin/time --output=outtime.txt -p csh -c 'cat file'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.