我想获取最后使用的命令及其执行时间。这将用作通知别名的一部分。
答案1
注意:我假设bash
是外壳。
适应其他 shell 应该不难。
获取最后使用的命令很简单:它存储在 shell 中事件指示符 !!
,也可以使用 shell 内置命令获得fc
(fc -s
)或history
(使用一些字符串操作:)history 1 | awk '{$1=""}1'
。
但是,除非采取某些操作,否则无法获取执行时间或运行时间前命令已执行。一旦运行命令,就什么也做不了了——马儿已经跑了。
要获取执行时间,可以执行以下操作之一:
- 设置
HISTTIMEFORMAT
变量,这将使bash
执行时间保存在历史记录中,然后使用文本处理从输出中提取时间history
。 - 使用包装器手动保存执行时间。
为了获取运行时间,也可以:
- 如果您
HISTTIMEFORMAT
在运行命令之前已经设置,您可以解析输出以history
获取执行时间,然后计算运行时间。 - 使用包装器运行命令
time
:time some-command
。如果你想离开,处理的输出time
有点混乱命令的输出未受影响。 - 使用包装器根据手动保存的执行时间计算运行时间。
带HISTTIMEFORMAT
套装
如果您设置了HISTTIMEFORMAT
变量,则无需使用包装器。首先,在您的 中.bashrc
,设置HISTTIMEFORMAT
。您可以将其设置为任何内容,只要它不为空即可。如果您不希望命令history
显示时间,可以将其设置为空格 ( HISTTIMEFORMAT=" "
)。
.bashrc
现在, Ubuntu默认有一个别名:
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
我们可以将其调整以适合我们的目的:
alert_post ()
{
RET=$?;
END=$(date '+%s');
LAST_COMM="$(HISTTIMEFORMAT='%s '; history 1)";
START=$(awk '{print $2}' <<<"$LAST_COMM");
START_TIME=$(date -d"@$START" '+%T %D');
COMM=$(awk '{print $3}' <<<"$LAST_COMM");
notify-send --urgency=low -i "$([ $RET = 0 ] && echo terminal || echo error)" "$COMM started at $START_TIME finished in $((END - START)) seconds.";
return $RET
}
alias a=alert_post
你可以这样使用它:
$ sleep 10; a
包装函数
使用函数或脚本来包装命令:
alert_wrapper ()
{
START=$SECONDS;
START_TIME=$(date '+%T %D');
COMM="$1";
"$@";
RET=$?;
END=$SECONDS;
notify-send --urgency=low -i "$([ $RET = 0 ] && echo terminal || echo error)" "$COMM started at $START_TIME finished in $((END - START)) seconds."
return $RET
}
alias a=alertwrapper
然后运行以下列命令为前缀的命令a
:
$ a sleep 10
笔记:
- 获取时间的方法有很多,包括执行时间和运行时时间。我使用了
$SECONDS
特殊变量和date
命令。你也可以只使用命令date
。 - 我已经使用了
notify-usd
,它应该在标准 Ubuntu 上可用。您可以查看其他生成通知的方法。 - 我已将命令的退出状态保存
$RET
在归还了它,所以您应该能够依赖退出代码:do-something; a || echo "Couldn't do something."
或者如果退出状态为非零a do-something || echo "Couldn't do something."
则会。echo
do-something
答案2
最后一条命令会保存在历史记录中。Bash 有一个fc
命令可让您访问该信息(来自man bash
):
fc [-e ename] [-lnr] [first] [last]
fc -s [pat=rep] [cmd]
第一种形式从历史列表中选择从 first 到 last 的一系列命令,并显示或编辑并重新执行它们。First 和 last 可以指定为字符串(用于定位以该字符串开头的最后一个命令)或数字(历史列表中的索引,其中负数用作当前命令号的偏移量)。如果没有指定 last,则将其设置为当前命令以进行列出(因此“fc -l -10”会打印最后 10 条命令),否则设置为 first。如果没有指定 first,则将其设置为上一个命令以进行编辑,并设置为 -16 以进行列出。
-n 选项在列出时隐藏命令编号。-r 选项反转命令的顺序。如果指定了 -l 选项,命令将列在标准输出中。否则,将对包含这些命令的文件调用 ename 指定的编辑器。如果没有指定 ename,则使用 FCEDIT 变量的值,如果未设置 FCEDIT,则使用 EDITOR 的值。如果两个变量均未设置,则使用 vi。编辑完成后,将回显并执行编辑的命令。
在第二种形式中,在用 rep 替换每个 pat 实例后,都会重新执行命令。命令的解释与上面的第一个命令相同。与此一起使用的一个有用的别名是
r="fc -s"'', so that typing
r cc'' 运行最后一个以 r'' 开头的命令,cc'' and typing
重新执行最后一个命令。如果使用第一种形式,则返回值为 0,除非遇到无效选项或 first 或 last 指定超出范围的历史记录行。如果提供了 -e 选项,则返回值为最后执行的命令的值,或者如果命令的临时文件发生错误则返回失败。如果使用第二种形式,则返回状态是重新执行的命令的状态,除非 cmd 未指定有效的历史记录行,在这种情况下 fc 返回失败。
还有一个名为的命令history
。手册对此进行了详细解释。我不太确定哪一个更适合您的需求。
此外,要获取时间,您可能需要研究设置 HISTTIMEFORMAT。但是,我不太确定如何访问进程所花费的时间。也许应该使用 TIMEFORMAT。否则,Unix 方法是使用命令运行命令time
。这将生成进程在运行时使用的各种时间和资源的输出。
摘自手册(man time
):
time 使用任何给定的参数 ARG 运行程序 COMMAND.... 当 COMMAND 完成时,time 将显示有关 COMMAND 使用的资源的信息(默认情况下在标准错误输出上)。如果 COMMAND 以非零状态退出,time 将显示警告消息和退出状态。