Tulis output `waktu` dalam file, mengapa tanda kurung diperlukan?


18

timemenulis ke stderr, jadi orang akan menganggap bahwa menambahkan 2>&1ke baris perintah harus merutekan outputnya stdout. Tetapi ini tidak berhasil:

test@debian:~$ cat file 
one two three four
test@debian:~$ time wc file > wc.out 2>&1

real    0m0.022s
user    0m0.000s
sys     0m0.000s
test@debian:~$ cat wc.out 
 1  4 19 file

Hanya dengan tanda kurung ia berfungsi:

test@debian:~$ (time wc file) > wc.out 2>&1
test@debian:~$ cat wc.out 
 1  4 19 file

real    0m0.005s
user    0m0.000s
sys     0m0.000s

Mengapa tanda kurung diperlukan dalam kasus ini? Mengapa tidak time wcditafsirkan sebagai satu perintah tunggal ?


3
Perhatikan bahwa hasilnya akan berbeda tergantung pada apakah timekata kunci shell, atau /usr/bin/time. Mungkin ada beberapa set deskriptor yang terlibat di sini (shell, dan yang dilampirkan pada suatu timeproses). Dan jangan lupa tentang yang tersirat dalam ()subkulit. ( menunggu spesialis bash : p)
John WH Smith

Jawaban:


24

Dalam ksh, bashdan zsh, timebukan perintah (builtin atau tidak), itu kata reserved dalam bahasa seperti foratau while.

Ini digunakan untuk mengatur waktu pipa 1 .

Di:

time for i in 1 2; do cmd1 "$i"; done | cmd2 > redir

Anda memiliki sintaks khusus yang memberi tahu shell untuk menjalankan saluran pipa itu:

for i in 1 2; do cmd1 "$i"; done | cmd2 > redir

Dan melaporkan statistik waktu untuk itu.

Di:

time cmd > output 2> error

Ini sama, Anda waktu yang cmd > output 2> errorperintah, dan statistik waktu masih terus stderr shell.

Anda membutuhkan:

{ time cmd > output 2> error; } 2> timing-output

Atau:

exec 3>&2 2> timing-output
time cmd > output 2> error 3>&-
exec 2>&3 3>&-

Untuk stderr shell yang akan diarahkan ke timing-outputsebelum waktu membangun (sekali lagi, bukan perintah ) digunakan (di sini ke waktu cmd > output 2> error 3>&-).

Anda juga dapat menjalankan timekonstruk tersebut dalam subkulit yang stderrnya dialihkan:

(time cmd > output 2> error) 2> timing-output

Tapi subkulit itu tidak diperlukan di sini, Anda hanya perlu stderr untuk diarahkan pada saat timekonstruksi dipanggil.

Sebagian besar sistem juga memiliki timeperintah. Anda dapat memanggil yang itu dengan menonaktifkan timekata kunci. Yang perlu Anda lakukan adalah mengutip kata kunci itu, entah bagaimana, sebagai kata kunci, hanya dikenali saat harfiah.

'time' cmd > output 2> error-and-timing-output

Namun berhati-hatilah formatnya mungkin berbeda dan stderr keduanya timedan cmdakan digabung menjadi error-and-timing-output.

Juga, timeperintah, sebagai lawan timekonstruk tidak dapat mengatur waktu pipa atau perintah majemuk atau fungsi atau builtin shell ...

Jika itu adalah perintah builtin, itu mungkin bisa mengatur waktu fungsi atau builtin, tetapi tidak bisa mengatur waktu pengalihan atau jalur pipa atau perintah majemuk.


1 Catatan yang bashmemiliki (apa yang dapat dianggap sebagai) bug di mana time (cmd) 2> file(tetapi tidak time cmd | (cmd2) 2> filemisalnya) mengarahkan kembali output waktu kefile


Yah, saya sering menekankan kepala saya untuk mengingat bahwa itu timeadalah kata kunci, bukan shell builtin.
cuonglm

Terima kasih atas tip tentang penggunaan 'time'untuk mendapatkan file executable-- handier daripada menulis /usr/bin/time(atau bahkan command time:-)).
Alex

@ Alex juga \time.
ctrl-alt-delor

7

Tidak ada perintah yang bernama time wc, timedan wcdipisahkan kata dalam shell.

Sekarang, sering ada dua program terpisah bernama time, yang satu adalah kata kunci shell, yang lain adalah perintah eksternal . Dalam shell yang timemerupakan kata kunci shell, saat Anda mengetik time wc ..., shell menggunakan kata kunci timealih-alih utilitas waktu eksternal .

Ketika shell menggunakan timekata kunci, itu tidak perlu fork () proses baru, timestandar saat ini dan kesalahan standar tidak berubah. Bagian pengalihan dalam:

time wc file > wc.out 2>&1

wchanya mempengaruhi .

Saat Anda menggunakan perintah majemuk(list) :

(time wc file) > wc.out 2>&1

shell berlari time wc filedi dalam subkulit, (time wc file)dianggap sebagai perintah tunggal , dan bagian pengalihan mempengaruhi output standar dan kesalahan standar, yang sekarang termasuk keduanya timedan wc.


Anda dapat membuat efek yang sama, tanpa biaya forking proses baru dengan menggunakan bentuk lain dari perintah pengelompokan {list;}:

{time wc file;} > wc.out 2>&1

Jika Anda menggunakan eksternal time, maka Anda tidak menghadapi masalah ini, karena dijalankan dalam proses baru:

/usr/bin/time wc file > wc.out 2>&1

Apakah ada perbedaan praktis antara menggunakan timedan /usr/bin/time? Apakah executable yang dipanggil secara fungsional sama?
Hashim

2

Karena timeAnda mengeksekusi adalah bash builtin. Bash memprosesnya dengan cara khusus.

Jika Anda akan menggunakan timebiner nyata , itu akan bertindak persis seperti yang Anda harapkan:

/usr/bin/time wc file > wc.out 2>&1

Meskipun output kali ini sedikit berbeda:

 $ /usr/bin/time wc file > wc.out 
0.00user 0.00system 0:00.00elapsed ?%CPU (0avgtext+0avgdata1900maxresident)k
0inputs+8outputs (0major+82minor)pagefaults 0swaps

9
Jika itu adalah builtin, itu tidak akan menjadi masalah. Masalahnya adalah kata kunci dalam bahasa tersebut. time cmd > outputkali cmd > outputperintah, dan time foo | barkali foo | bar.
Stéphane Chazelas

1

Bukan timeyang menulis informasi waktu. Builtin timemembuat shell menulis ini setelah perintah selesai. Tetapi pengalihan hanya mempengaruhi perintah.

Dalam (time ...)hal pengalihan diterapkan ke seluruh subkulit.


0

Karena waktu adalah shell bawaan, ia menulis ke stderr shell , bukan stderr perintah.

Menggunakan tanda kurung memaksa seluruh perintah menjadi shell anak yang stderrnya dapat diarahkan.

menggunakan kurung keriting menghasilkan hasil yang serupa tanpa benar-benar memulai subkulit

  { time who ; } > /tmp/timwho >& /tmp/xx 

(ya, Anda membutuhkan titik koma)

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.