Bagaimana menjalankan waktu pada banyak perintah DAN menulis keluaran waktu ke file?

66

Saya ingin menjalankan timeperintah untuk mengukur waktu beberapa perintah.

Yang ingin saya lakukan adalah:

  • Ukur waktu berlari mereka semua ditambahkan bersama-sama
  • Tulis timeoutput ke file
  • Tulis STDERRdari perintah yang saya ukurSTDERR

Apa yang saya tidak ingin lakukan adalah

  • Tulis beberapa perintah ke dalam skrip terpisah (mengapa? Karena semua ini sudah menjadi skrip yang saya hasilkan secara terprogram, dan membuat skrip temporer LAIN akan lebih berantakan daripada yang saya inginkan)

Apa yang saya coba sejauh ini:

/usr/bin/time --output=outtime -p echo "a"; echo "b";

Tidak berfungsi, timedijalankan hanya pada yang pertama.

/usr/bin/time --output=outtime -p ( echo "a"; echo "b"; )

Tidak berfungsi, (adalah token yang tidak terduga.

/usr/bin/time --output=outtime -p { echo "a"; echo "b"; }

Tidak berfungsi, "tidak ada file atau direktori seperti itu".

/usr/bin/time --output=outtime -p ' echo "a"; echo "b";'

Tidak berfungsi, "tidak ada file atau direktori seperti itu".

time ( echo "a"; echo "b"; ) 2>outtime

Tidak berfungsi, karena mengalihkan semua STDERRke outtime; Saya hanya ingin timeoutput di sana.

Dan tentu saja,

time --output=outime echo "a";

Sejak itu tidak berfungsi --output=outime: command not found.

Bagaimana saya bisa melakukannya?

Karel Bílek
sumber

Jawaban:

90

Gunakan sh -c 'commands'sebagai perintah, misalnya:

/usr/bin/time --output=outtime -p sh -c 'echo "a"; echo "b"'
Jim Paris
sumber
2
versi yang lebih pendek:time -p sh -c 'echo "a"; echo "b"'
Geo
8

Coba ini:

% (time ( { echas z; echo 2 } 2>&3 ) ) 3>&2 2>timeoutput
zsh: command not found: echas
2
% cat timeoutput                                
( { echas z; echo 2; } 2>&3; )  0.00s user 0.00s system 0% cpu 0.004 total

Penjelasan:

Pertama, kita harus menemukan cara untuk mengarahkan ulang output dari time. Karena timeshell adalah builtin, dibutuhkan baris perintah penuh sebagai perintah yang akan diukur, termasuk pengalihan. Jadi,

% time whatever 2>timeoutput
whatever 2> timeoutput  0.00s user 0.00s system 0% cpu 0.018 total
% cat timeoutput 
zsh: command not found: whatever

[Catatan: komentar janos menyiratkan ini bukan kasus untuk bash.] Kita dapat mencapai redirection dari timeoutput dengan menjalankan timedalam subkulit dan kemudian mengarahkan output dari subkulit itu.

% (time whatever) 2> timeoutput
% cat timeoutput 
zsh: command not found: whatever
whatever  0.00s user 0.00s system 0% cpu 0.018 total

Sekarang kita telah berhasil mengalihkan keluaran time, tetapi keluarannya dicampur dengan keluaran kesalahan dari perintah yang kita ukur. Untuk memisahkan keduanya, kami menggunakan deskriptor file tambahan.

Di "luar" yang kita miliki

% (time ... ) 3>&2 2>timeout

Ini berarti: apa pun yang ditulis ke file descriptor 3, akan di-output ke file deskriptor 2 tempat yang sama (standard error) sedang menghasilkan sekarang (terminal). Dan kemudian kita mengarahkan kesalahan standar ke file timeout.

Jadi sekarang kita punya: semuanya ditulis ke stdout dan fd 3 akan pergi ke terminal, dan semua yang ditulis ke stderr akan pergi ke file. Yang tersisa adalah mengarahkan ulang stderr perintah terukur ke fd 3.

% (time whatever 2>&3) 3>&2 2>timeout

Sekarang, untuk membuat waktu mengukur lebih dari satu perintah, kita perlu menjalankannya dalam subkulit (lainnya!) (Di dalam tanda kurung). Dan untuk mengarahkan output kesalahan dari semuanya ke fd 3, kita perlu mengelompokkannya di dalam kurung keriting.

Jadi, akhirnya, kami tiba di:

% (time ( { whatever; ls } 2>&3 ) ) 3>&2 2>timeoutput

Itu dia.

angus
sumber
Ini adalah kesalahan sintaksis dalam shell POSIX. Mungkin bashism?
josch
@ josch shell yang digunakan di sini adalah zsh.
angus
6

Bukan jawaban yang benar tetapi sangat terkait dengan pertanyaan itu.
Diperlukan statistik waktu untuk beberapa program tanda kurung gabungan. Pisahkan perintah dengan titik koma.

time ( command1 ; command2 )
Martin T.
sumber
1
Ini bagus. Lebih baik lagi, gunakan && di antara perintah - seperti agar time ( command1 && command2 )jika perintah pertama gagal; itu tidak akan melanjutkan untuk mengeksekusi yang lain.
bikashg