Принудительное добавление псевдонима для каждой команды

11

Можно ли принудительно добавить псевдоним синхронизации (из-за отсутствия лучшего способа выразить его) для каждой команды в bash?

Например, я хотел бы иметь конкретного пользователя, который всякий раз, когда команда запускается, она всегда переносится либо с dateдо и после, либо time.

Возможно ли это, и если да, то как?

кроличий садок
источник
Я смотрел раньше и не мог найти способ сделать именно это. Как говорит Калеб, вы можете использовать preexec, но вы не хотите запускать его внутри preexec(например preexec() { time $1; }), потому что оболочка все еще запускает его после preexecвозврата. Поэтому лучшее, что мы можем сделать, это нечто подобное.
Микель
@Mikel Я думаю, что вы могли бы использовать preexec()функцию, чтобы фактически обернуть то, что выполнялось, извлекая команду, запуская ее изнутри функции, а затем возвращая какую-то ошибку, чтобы оболочка не выполняла саму команду.
Калеб

Ответы:

10

Вы можете записать время запуска командной строки и время отображения подсказки. Bash уже отслеживает дату начала каждой командной строки в своей истории, и вы можете отметить время, когда вы отображаете следующее приглашение.

print_command_wall_clock_time () {
  echo Wall clock time: \
    $(($(date +%s) - $(HISTTIMEFORMAT="%s ";
                       set -o noglob;
                       set $(history 1); echo $2)))
}
PROMPT_COMMAND=print_command_wall_clock_time$'\n'"$PROMPT_COMMAND"

Это дает вам только второе разрешение и только время настенных часов. Если вам нужно лучшее разрешение, вам нужно использовать внешнюю dateкоманду, которая поддерживает %Nформат наносекунд, и DEBUGловушку для вызова dateперед выполнением этой команды.

call_date_before_command () {
  date_before=$(date +%s.%N)
}
print_wall_clock_time () {
  echo Wall clock time: \
    $((date +"$date_before - %s.%N" | bc))
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_command_wall_clock_time

Даже с DEBUGловушкой я не думаю, что есть способ автоматически отображать время процессора для каждой команды или быть более разборчивым, чем подсказка для подсказки.


Если вы хотите использовать другую оболочку, вот как получить отчет о времени для каждой команды в zsh (это не распространяется на другие задачи):

REPORTTIME=0

Вы можете установить REPORTTIMEлюбое целочисленное значение, информация о синхронизации будет отображаться только для команд, которые использовали больше, чем это много секунд процессорного времени.

Zsh взял эту функцию из csh, где вызывается переменная time.

Жиль "ТАК - прекрати быть злым"
источник
3

Ваши варианты здесь будут зависеть от вашей оболочки. Там zshесть удобная функция ловушки, preexec()которая вызывается прямо перед любой интерактивной командой оболочки. Создав функцию с этим именем, вы можете заставить вещи выполняться. Вы также можете воспользоваться функцией, precmd()которая будет запущена непосредственно перед отображением следующего приглашения, которое будет выполнено сразу после завершения вашей команды.

Создав эту пару функций, вы можете иметь любые произвольные команды, которые вы хотите выполнить до и после любых команд, введенных в командной строке. Вы можете использовать это для регистрации использования оболочки, создания блокировок, тестирования среды или для расчета времени или ресурсов, потраченных во время выполнения команды.

В этом примере мы создадим метку времени для эталонного теста перед запуском команды с помощью, preexec()затем рассчитаем время, потраченное на выполнение команды с помощью, precmd()и выведем ее перед запросом или выйдем из системы. Пример:

preexec() {
   CMDSTART=$(date +%s%N)
}
precmd() {
   CMDRUNTIME=$(($(date +%s%N)-$CMDSTART))
   echo "Last command ran for $CMDRUNTIME nanoseconds."
}

Примечание: для этого конкретного примера есть еще более простая встроенная функция. Все, что вам нужно сделать, это включить отчеты о времени выполнения в ZSH, и это будет сделано автоматически.

$ export REPORTTIME=0
$ ls -d
./
ls -BF --color=auto -d  0.00s user 0.00s system 0% cpu 0.002 total

В более практической реализации preexec()я использую его, чтобы увидеть, работает ли оболочка внутри tmuxили, screenи, если да, для отправки информации о выполняющейся в данный момент команде в восходящем направлении для отображения в имени вкладки.

К сожалению, в bash этот маленький механизм не существует. Вот попытка одного человека повторить это . Также см . Ответ Жиля для подобного изящного маленького взлома.

Калеб
источник
1
А вот упрощенная версия трюка «precmd-through-DEBUG» .
Жиль "ТАК - перестань быть злым"
См. Также unix.stackexchange.com/questions/8607/…
Микель,
желаю, чтобы это было доступно в bash!
Уоррен
Смотрите ссылки Жиля и других, это реализуемо в bash с небольшим дополнительным вмешательством. Опять же, почему бы тебе просто не запустить zsh? Это раскачивающаяся оболочка с более вескими причинами для переключения, чем эта!
Калеб
2
Если вы используете zsh, есть еще лучший способ сделать это. Переменная среды REPORTTIME, если она установлена, будет выводить информацию о времени выполнения (как если бы вы выполнили команду с «time» перед ней) для любой команды, которая занимает более $ REPORTTIME секунд. Просто установите его на 0, и он должен сообщать вам время для каждой команды с разбивкой user / sys для загрузки.
Джозеф Гарвин
1

Самый простой способ, вероятно, установить PROMPT_COMMAND. Смотрите переменные Bash :

PROMPT_COMMAND
Если установлено, значение интерпретируется как команда, выполняемая перед печатью каждого основного приглашения ( $PS1).

Например, чтобы избежать перезаписи любой существующей команды приглашения, вы можете сделать:

PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"
CJM
источник
не знал о том , что один - выглядит как старт хороший, @cjm
садок
1
Это начало, но не решает проблему знания, когда команда была выполнена. Само приглашение может быть нарисовано за несколько минут, часов или дней до того, как команда была введена и запущена.
Калеб
0

csh/ tcshимеет лучшую поддержку для этой функции (и всегда имел ее).

  The `time` shell variable can be set to execute the time builtin  command
  after the completion of any process that takes more than a given number
  of CPU seconds.

Другими словами, set time=1будет распечатано время, затраченное (система, пользователь, истекшее) любой командой, которая заняла более 1 секунды времени процессора. Обычный set timeпозволит распечатать время для всех команд.

Alexis
источник