我在用如何在 zsh 中定义并加载自己的 shell 函数将我的 zsh 脚本转换为 shell 函数。
这脚本我试图转换的是:
#! /bin/zsh -
trap true INT QUIT
zmodload zsh/datetime
TIMEFMT='Total duration: %*E'
strftime -s start 'Start Time: %d/%m/%y %I:%M%P'
{
duration=$(
exec 4>&2 2>&1 1>&3 3>&-
time "$@" 2>&4 4>&-
)
} 3>&1
ret=$?
strftime -s end 'End Time: %d/%m/%y %I:%M%P'
echo -e
print -rlu2 $start $end $duration
return $ret
因此,我删除了 shebang 并将脚本放入我的fpath
.
问题是,它不再显示$duration
:
% reporttime tail -f ~/.xsession-errors
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
Cinnamon warning: Log level 128: posix_spawn avoided (fd close requested)
^C
Start Time: 03/01/21 03:15pm
End Time: 03/01/21 03:15pm
我能做些什么?
答案1
我无法重现你的问题。但是,如果您想使其成为可自动加载函数,则需要将陷阱和变量设置为该函数的本地函数。的输出echo -e
也应该像报告的其余部分一样发送到 stderr,或者在调用中添加额外的换行符print
:
zmodload zsh/datetime
set -o localtraps
trap true INT QUIT
local TIMEFMT='Total duration: %*E' start end ret duration
strftime -s start 'Start Time: %d/%m/%y %I:%M%P'
{
duration=$(
exec 4>&2 2>&1 1>&3 3>&-
time "$@" 2>&4 4>&-
)
} 3>&1
ret=$?
strftime -s end 'End Time: %d/%m/%y %I:%M%P'
print -rlu2 '' $start $end $duration
return $ret
另一种选择是将整个内容包含在其中,(...)
以便它在子 shell 中运行。
请注意,正如您所指的答案中已经提到的,since报告zsh
了time
进程消耗的资源(不仅zsh
限于经过的时间和CPU时间,还可以包括内存使用情况、上下文切换、I/O操作.. .),它只能用于在子进程中运行的命令。因此,如果您希望能够使用time
某个函数,则需要替换time "$@"
为time ("$@")
,以便该函数在子 shell 进程中运行。
但由于您只对过去时间,而不是真正处理资源,您不妨使用我建议的其他方法,只需手动计算结束时间(并HH:MM:SS.TTT
手动进行格式化或使用,strftime
如果您愿意的话)。