简体   繁体   English

定时源bash脚本

[英]Timing a sourced bash script

Normally I simply call the time program when I want to profile a script or a command it runs. 通常,当我要分析脚本或运行的命令时,我只是简单地调用time程序。

But this time (no pun intended), I want to measure the time it takes to execute a sourced script, such as: 但是这次(没有双关语),我想测量执行源脚本所需的时间,例如:

/usr/bin/time source myscript.sh

But I get the following error: 但是我收到以下错误:

/usr/bin/time: cannot run source: No such file or directory

And sourcing it this way: 并以这种方式采购:

/usr/bin/time . myscript.sh

Simply gives me this error: 简单地给我这个错误:

/usr/bin/time: cannot run .: Permission denied

I can call it in the following two ways: 我可以通过以下两种方式调用它:

/usr/bin/time ./myscript.sh
/usr/bin/time bash myscript.sh

But it's really important that I source my script. 但是,我的脚本源非常重要。 Anyone know how I can do this? 有人知道我该怎么做吗?


Additional Context : 其他内容

We have many, many scripts which are somewhat complex and these scripts know how to source a specific 'set' of other 'client' scripts. 我们有许多非常复杂的脚本,这些脚本知道如何获取其他“客户端”脚本的特定“集合”。 We'll call these scripts 'bundles'. 我们将这些脚本称为“捆绑包”。

bundle-a.sh
bundle-b.sh
...
bundle-z.sh

That's not exactly how they are named, but it serves the purpose of showing 26 of them in this example. 这并不是确切的命名方式,但是它的目的是在此示例中显示其中的26个。 Each bundle contain a lot of logic and each bundle invoke a specific set of client scripts. 每个捆绑软件包含很多逻辑,每个捆绑软件都调用一组特定的客户端脚本。

There are hundreds of client scripts, some with a few lines of code and others that are really complex and take hours to execute. 客户端脚本有数百种,有些包含几行代码,而另一些却非常复杂,需要花费数小时才能执行。

client-000.sh
client-001.sh
...
client-300.sh

We also provide a script which serves as an API library for both our bundle scripts and our client scripts. 我们还提供了一个脚本,该脚本既用作捆绑包脚本又用于客户端脚本的API库。 Many, many functions in this API. 这个API中有很多功能。

api.sh

So the bundle scripts source the API library and so does each client script. 因此,捆绑包脚本可提供API库,每个客户端脚本也可提供。 We have it this way so that a bundle can be called (which call a set of client scripts) or at times we only need to call a specific client script directly. 我们采用这种方式,以便可以调用捆绑包(它调用一组客户端脚本),或者有时我们只需要直接调用特定的客户端脚本即可。 It is implemented in a way that if the bundle is executed, the API library is only sourced once (and not again from the client script). 它的实现方式是,如果执行捆绑软件,则仅一次(而不是再次从客户端脚本中)获取API库。

So all of this has worked well for a long time. 因此,所有这些在很长一段时间内都运作良好。 Its just that now I'm trying to add the /usr/bin/time to each sourcing of our client scripts from the bundle scripts. 只是现在我正尝试将/ usr / bin / time添加到捆绑脚本中每个我们的客户端脚本的来源。

If you really, really need to get the system and user times of a sourced script, you can use strace from a different shell to watch the one you're timing in, trace calls to getrusage , and inspect the return values. 如果确实需要获取源脚本的系统时间和用户时间,则可以使用其他外壳程序中的strace来查看您正在计时的脚本,跟踪对getrusage调用,并检查返回值。

Shell 1 (where you will time the script) Shell 1(您将在其中计时脚本)

$ echo $$
12345

Shell 2 (where you will trace) Shell 2(您将在其中跟踪)

$ strace -etrace=getrusage -v -p 12345
Process 12345 attached - interrupt to quit

Shell 1: 外壳1:

$ time : ; . myscript.sh ; time :
real 0m0.000s  
(( time output and script output, then time output again)

Shell 2: will output something like Shell 2:将输出类似

getrusage(RUSAGE_SELF, {ru_utime={0, 12000}, ru_stime={0, 16001}, ru_maxrss=2364, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=1551, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=1032, ru_nivcsw=3}) = 0
getrusage(RUSAGE_CHILDREN, {ru_utime={0, 0}, ru_stime={0, 4000}, ru_maxrss=1216, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=5143, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=57, ru_nivcsw=21}) = 0
getrusage(RUSAGE_SELF, {ru_utime={0, 448028}, ru_stime={0, 16001}, ru_maxrss=2364, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=1552, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=2141, ru_nivcsw=22}) = 0
getrusage(RUSAGE_CHILDREN, {ru_utime={0, 0}, ru_stime={0, 4000}, ru_maxrss=1216, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=5143, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=57, ru_nivcsw=21}) = 0

Notice how the values in the ru_utime structure element changed? 注意ru_utime结构元素中的值如何变化? The difference there is how much user CPU time the shell itself used. 区别在于外壳本身使用了多少用户CPU时间。 See man getrusage for the details on exactly what you are seeing. 有关您所看到的详细信息,请参见man getrusage From there, it's just a automatically extracting those and finding the difference. 从那里开始,这只是自动提取它们并发现差异的方法。

It's possibly just the lack of a ./ in your reference to myscript.sh (which I note you use in your working examples, but not elsewhere) 您对myscript.sh的引用中可能缺少./ (我注意到您在工作示例中使用了它,但在其他示例中没有使用)。


Have tested under Ubuntu (Trusty64), and Darwnin/BSD - just using the following works fine: 已经在Ubuntu(Trusty64)和Darwnin / BSD下进行了测试-仅使用以下方法即可正常工作:

time source ./myscript.sh

FWIW, I used the following script to just confirm that the source command was actually executing correctly: FWIW,我使用以下脚本来确认source命令是否正确执行:

#!/usr/bin/env sh

V_FIRST=1
export V_SECOND=2

Execution under darwin: 在达尔文下执行:

$ time source ./test.sh ; set | grep -i V_

real    0m0.000s
user    0m0.000s
sys 0m0.000s
RBENV_SHELL=bash
V_FIRST=1
V_SECOND=2

Execution under Ubuntu: 在Ubuntu下执行:

$ time source ./test.sh ; set | grep -i V_

real    0m0.000s
user    0m0.000s
sys 0m0.000s
V_FIRST=1
V_SECOND=2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM