Запишіть вихід у файл `time`, чому потрібні дужки?


18

timeпише до stderr, тож можна припустити, що додавання 2>&1до командного рядка повинно направляти його на вихід stdout. Але це не працює:

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

Тільки з дужками це працює:

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

Чому в цьому випадку потрібні дужки? Чому не time wcінтерпретується як одна єдина команда?


3
Зауважте, що результати будуть відрізнятися залежно від того time, ключове слово оболонки, або /usr/bin/time. Тут може бути задіяно кілька наборів дескрипторів (оболонки та ті, що додаються до timeпроцесу). І не будемо забувати про тих, що маються на увазі ()підгалузі. ( чекає спеціаліста з башти : p)
Джон У. Сміт

Відповіді:


24

В ksh, bashі zsh, timeне є командою (вбудованою чи ні), це зарезервоване слово на мові, як forабо while.

Він звик до часу 1 трубопроводу .

В:

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

У вас є спеціальний синтаксис, який повідомляє оболонці виконувати цю трубопровід:

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

І повідомте про це статистику часу.

В:

time cmd > output 2> error

Це те ж саме, що ви синхронізації з cmd > output 2> errorкомандою, і статистика синхронізації до сих пір йдуть на потік помилок оболонки.

Тобі потрібно:

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

Або:

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

Щоб stderr оболонки був перенаправлений до того, timing-outputяк буде використана конструкція часу (знову ж таки, не команда ) (тут час від часу cmd > output 2> error 3>&-).

Ви також можете запустити цю timeконструкцію в підшалі, на яку перенаправлений stderr:

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

Але ця додаткова оболонка тут не потрібна, вам потрібно лише перенаправити stderr під час timeвиклику конструкції.

Більшість систем також мають timeкоманду. Ви можете викликати це, відключивши timeключове слово. Все, що вам потрібно зробити, - це якось цитувати це ключове слово, оскільки ключові слова розпізнаються як такі лише в прямому сенсі.

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

Але будьте обережні, формат може бути різним, і жорсткішим обох, timeі cmdвони будуть об'єднані в error-and-timing-output.

Крім того, timeкоманда, на відміну від timeконструкції, не може здійснювати трубопроводи чи складні команди чи функції чи вбудовані оболонки ...

Якби це була вбудована команда, вона могла б функціонувати викликами часу або вбудованими, але вона не могла би вчасно переспрямувати або конвеєри чи складені команди.


1 Зауважте, що bashмає (що можна вважати) помилку, за допомогою якої time (cmd) 2> file(але не, time cmd | (cmd2) 2> fileнаприклад) перенаправляє вихідний сигнал наfile


Ну, я часто підкреслюю голову, щоб пам'ятати, що timeце ключове слово, а не вбудована оболонка.
cuonglm

Дякуємо за пораду щодо використання 'time'виконуваного файлу - зручнішого, ніж написання /usr/bin/time(або навіть command time:-)).
alexis

@ Алексис також \time.
ctrl-alt-delor

7

Немає жодної команди time wc , timeі wcце розділене слово в оболонці.

Зараз часто є дві окремі програми з назвою time: одна - ключове слово оболонки, інша - зовнішня команда . У оболонках, що timeє ключовим словом оболонки, під час введення time wc ...оболонки використовували ключове слово timeзамість зовнішньої утиліти часу .

Коли оболонка використовує timeключове слово, їй не потрібно fork () новий процес, поточний timeстандарт в і стандартна помилка не змінюються. Частина переспрямування в:

time wc file > wc.out 2>&1

впливає wcлише.

Коли ви використовуєте складні команди(list) :

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

оболонка, що пролягала time wc fileвсередині підклітини, (time wc file)вважалася єдиною командою, і частина перенаправлення впливає на її стандартний вихід і стандартну помилку, які тепер включають і timeі, і wc.


Ви можете зробити той же ефект без витрат на розгортання нового процесу, використовуючи іншу форму команди групування {list;}:

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

Якщо ви використовуєте зовнішню time, ви не зіткнетеся з цією проблемою, оскільки вона була запущена в новому процесі:

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

Чи є якась практична різниця між використанням timeта /usr/bin/time? Чи виконуються функції виконуваного файлу однаково?
Хашим

2

Оскільки time що ви виконуєте це bash вбудований. Баш обробляє його таким особливим чином.

Якщо ви будете використовувати справжній timeбінарний файл, він буде діяти саме так, як ви очікуєте:

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

Хоча результат цього часу дещо інший:

 $ /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
Якби це вбудований, це не було б проблемою. Проблема в тому, що це ключове слово в мові. time cmd > outputраз cmd > outputкоманда та time foo | barраз foo | bar.
Стефан Шазелас

1

Це не timeте, що пише інформацію про час. Вбудований timeзмушує оболонку писати це після завершення команди. Але перенаправлення впливає лише на команду.

У (time ...)випадку, якщо перенаправлення застосовано до всієї нижньої частини.


0

Оскільки час є вбудованою оболонкою, він записує в stderr оболонки , а не на stderr команди.

Використання дужок змушує всю команду в дочірню оболонку, stderr яку можна переспрямувати.

використання фігурних дужок дає аналогічний результат, фактично не запускаючи підзарядку

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

(так, вам потрібна крапка з комою)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.