是否可以向其中的每个命令强行添加定时别名(因为缺少更好的用短语表达的方式)bash
?
例如,我希望有一个特定的用户,每当运行命令时,该用户总是用date
之前和之后或包裹time
。
这可能吗?如果可以,怎么办?
preexec()
通过获取命令,从函数内部自己运行,然后返回某种错误,从而使外壳不再继续执行命令本身,来使用该函数实际包装正在执行的内容。
是否可以向其中的每个命令强行添加定时别名(因为缺少更好的用短语表达的方式)bash
?
例如,我希望有一个特定的用户,每当运行命令时,该用户总是用date
之前和之后或包裹time
。
这可能吗?如果可以,怎么办?
preexec()
通过获取命令,从函数内部自己运行,然后返回某种错误,从而使外壳不再继续执行命令本身,来使用该函数实际包装正在执行的内容。
Answers:
您可以记录命令行启动的时间和显示提示的时间。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
陷阱,我也不认为有一种方法可以自动显示每个命令的处理器时间,或者比提示提示更具区分性。
如果您愿意使用其他Shell,请按照以下方法为zsh中的每个命令获取时间报告(这不会推广到其他任务):
REPORTTIME=0
您可以将其设置REPORTTIME
为任何整数值,仅在处理器时间超过此秒数的命令中才会显示时序信息。
Zsh从名为的变量csh继承了此功能time
。
您在这里的选择将取决于您的外壳。其中zsh
有一个方便的挂钩函数preexec()
,它在任何交互式shell命令之前运行。通过使用该名称创建函数,可以使事情得以执行。您也可以通过调用函数跟进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
,如果运行,则将有关当前正在运行的命令的信息发送到上游,以在选项卡名称中显示。
preexec
,但是您不想在preexec
(例如preexec() { time $1; }
)内部运行它,因为shell在preexec
返回后仍会运行它。因此,我们能做的最好的事情就是类似的事情。