是否可以向 中的每个命令强制添加计时别名(由于缺乏更好的表达方式)bash
?
例如,我希望有一个特定的用户,每当运行命令时,它总是用date
before 和 after 或time
.
这可能吗?如果可能的话,如何实现?
答案1
您可以记录命令行启动的时间和显示提示的时间。 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 +"%s.%N - $date_before" | bc)"
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_wall_clock_time
即使有了DEBUG
陷阱,我也不认为有一种方法可以自动显示每个命令的处理器时间,或者比提示更具区别性。
如果您愿意使用不同的 shell,以下是如何获取 zsh 中每个命令的时间报告(这不适用于其他任务):
REPORTTIME=0
您可以设置REPORTTIME
为任何整数值,只有使用超过这么多秒处理器时间的命令才会显示计时信息。
Zsh 从 csh 中继承了这个功能,其中变量被称为time
。
答案2
您此处的选项将取决于您的 shell。其中zsh
有一个方便的钩子函数,preexec()
它在任何交互式 shell 命令之前运行。通过创建具有此名称的函数,您可以执行一些事情。您还可以跟进一个名为的函数,precmd()
该函数将在绘制下一个提示之前运行,该提示将在下一个提示之后运行你的命令完成。
通过创建这对函数,您可以在提示符下发出任何命令之前和之后运行您想要运行的任意命令。您可以使用它来记录 shell 使用情况、创建锁、测试环境,或者如示例中所示计算命令运行时所花费的时间或资源。
在此示例中,我们将在运行命令之前为自己创建一个基准时间戳,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()
,我使用它来查看 shell 是否正在内部运行tmux
,screen
如果是,则向上游发送有关当前正在运行的命令的信息,以显示在选项卡名称中。
答案3
最简单的方法可能是设置PROMPT_COMMAND
。请参阅Bash 变量:
PROMPT_COMMAND
如果设置,该值将被解释为在打印每个主提示 ($PS1
) 之前执行的命令。
例如,为了避免覆盖任何现有的提示命令,您可以执行以下操作:
PROMPT_COMMAND="date ; ${PROMPT_COMMAND}"
答案4
作为wjandrea 指出,吉尔斯的回答不起作用,
- 部分是因为外观原因,wjandrea 已经修复了这个问题,并且
- 部分原因是 DEBUG trap 命令在 PROMPT_COMMAND 命令运行之前立即运行,因此您会丢失要测量其运行时间的用户键入命令的开始时间。
幸运的是,DEBUG trap 命令可以知道什么时候发生这种情况 并能加以防范。因此,以 Gilles 的答案为基础(将其与 DNA 片段相结合)我在这里的答案非常相似),我们可以构造
call_date_before_command () {
if [ "$BASH_COMMAND" != "print_wall_clock_time" ]
then
command_flag=1
date_before=$(date +%s.%N)
fi
}
print_wall_clock_time () {
if [ "$command_flag" ]
then
echo "Wall clock time: $(date +"%s.%N - $date_before" | bc)"
fi
command_flag=
}
trap call_date_before_command DEBUG
PROMPT_COMMAND=print_wall_clock_time
如果在运行之前调用wherecall_date_before_command
则不会执行任何操作,并且仅在用户实际运行命令(而不仅仅是按 Enter 键)时才报告信息。print_wall_clock_time
print_wall_clock_time
您可能想要将call_date_before_command
,重命名为
command_flag
, and ,以减少无意中以交互方式重新定义其中之一的机会。print_wall_clock_time
Twas_brillig_and_the_slithy_toves
Did_gyre_and_gimble_in_the_wabe
All_mimsy_were_the_borogoves