我希望每 10 秒执行一次命令,并让它在后台执行(从而消除watch
?)。所有答案都显示如下内容,但这将执行 11 到 14 秒。如何才能做到这一点?
while true; do
# perform command that takes between 1 and 4 seconds
sleep 10
done
答案1
怎么样:
( # In a subshell, for isolation, protecting $!
while true; do
perform-command & # in the background
sleep 10 ;
### If you want to wait for a perform-command
### that happens to run for more than ten seconds,
### uncomment the following line:
# wait $! ;
### If you prefer to kill a perform-command
### that happens to run for more than ten seconds,
### uncomment the following line instead:
# kill $! ;
### (If you prefer to ignore it, uncomment neither.)
done
)
ETA:有了所有这些评论、替代方案和用于额外保护的子 shell,这看起来比开始时要复杂得多。因此,为了进行比较,以下是我开始担心wait
或kill
以及它们的$!
隔离需求之前的情况:
while true; do perform-command & sleep 10 ; done
其余的只是在您需要时使用。
答案2
bash
您可以在、zsh
或中执行类似以下操作ksh
:
SECONDS=0
while command
do sleep "$((10-(SECONDS%10)))"
done
这是bash
手册的内容$SECONDS
:
$SECONDS
- 每次引用此参数时,都会返回自 shell 调用以来的秒数。如果将值分配给
$SECONDS
,则后续引用时返回的值是自分配以来的秒数加上所分配的值。如果$SECONDS
是unset
,它就会失去其特殊属性,即使它随后被重置。
这是一个工作示例:
( SECONDS=0
while sleep "$((RANDOM%10))"
do sleep "$((10-(SECONDS%10)))"
echo "$SECONDS"
done
)
10
20
30
40
50
60
70
80
90
100
答案3
仅限 BASH - 您还可以计算命令所花费的时间并从 10 中减去:
TIMEFORMAT=$'%0R'
while true; do
T=$({ time command; } 2>&1)
sleep $(( 10-T ))
来自 BASH 人:
TIMEFORMAT 此参数的值用作格式字符串,指定应如何显示以时间保留字为前缀的管道的计时信息。 % 字符引入了扩展为时间值或其他信息的转义序列。转义序列及其含义如下;大括号表示可选部分。
%% 字面量 %。
%[p][l]R 经过的时间(以秒为单位)。
%[p][l]U 在用户模式下花费的 CPU 秒数。
%[p][l]S 在系统模式下花费的 CPU 秒数。
%P CPU 百分比,计算公式为 (%U + %S) / %R。可选的 p 是指定精度的数字,即小数点后的小数位数。值为 0 会导致不输出小数点或分数。