![如何确定“睡眠”还剩多少时间?](https://linux22.com/image/95821/%E5%A6%82%E4%BD%95%E7%A1%AE%E5%AE%9A%E2%80%9C%E7%9D%A1%E7%9C%A0%E2%80%9D%E8%BF%98%E5%89%A9%E5%A4%9A%E5%B0%91%E6%97%B6%E9%97%B4%EF%BC%9F.png)
我有:
sleep 210m && for i in $(seq 1 5); do echo -e '\a'; sleep 0.5; done
作为一个简单、简洁的计时器运行来提醒我什么时候应该做某事。即sleep 210m
PID 25347。
我试图算出还剩下多少睡眠时间。加上我最初的睡眠时间(210 分钟),我想出的最好结果是:
$ echo "210 60 * $(ps -o etimes= 25347) - 60 ~ r n [:] P p" | dc
78:11
(说明:第一位计算原始睡眠的秒数;该$(ps…)
位获取自睡眠开始以来的时间(以秒为单位),然后其余位减去它们并以分钟和秒为单位显示。)
我认为这通常很有用;有一个更好的方法吗?或者至少有一种聪明的方法来解析睡眠时间ps -o args
?
答案1
支持 GNU 或 Solaris 11sleep
参数(一个或多个<double>[smhd]
持续时间,因此也适用于仅支持一个十进制整数的传统实现(如在 FreeBSD 上),但不适用于接受更复杂参数的实现,例如ISO-8601 持续时间)。使用etime
而不是etimes
因为它更便携(标准 Unix)。
remaining_sleep_time() { # arg: pid
ps -o etime= -o args= -p "$1" | perl -MPOSIX -lane '
%map = qw(d 86400 h 3600 m 60 s 1);
$F[0] =~ /(\d+-)?(\d+:)?(\d+):(\d+)/;
$t = -($4+60*($3+60*($2+24*$1)));
for (@F[2..$#F]) {
s/\?//g;
($n, $p) = strtod($_);
$n *= $map{substr($_, -$p)} if $p;
$t += $n
}
print $t'
}
(这s/\?//g
是为了摆脱'用作控制字符替换的?
字符。没有它,它将无法解析或......不幸的是,在某些语言环境中,包括语言环境,它使用而不是。我们无能为力在这种情况下,因为无法区分 a和 a (半天))。procps
ps
sleep $'\r1d'
sleep $'\t1d'
C
.
?
\t5d
.5d
将 pid 作为参数传递。
这还假设argv[0]
传递给的值sleep
不包含空格,并且参数的数量足够小,不会被 截断ps
。
例子:
$ sleep infinity & remaining_sleep_time "$!"
Inf
$ sleep 0xffp-6d &
$ remaining_sleep_time "$!"
344249
$ sleep 1m 1m 1m 1m 1m & remaining_sleep_time "$!"
300
对于[[[ddd-]HH:]MM:]SS
输出而不仅仅是秒数,请将其替换print $t
为:
$output = "";
for ([60,"%02d\n"],[60,"%02d:"],[24,"%02d:"],[inf,"%d-"]) {
last unless $t;
$output = sprintf($_->[1], $t % $_->[0]) . $output;
$t = int($t / $_->[0])
}
printf "%s", $output;
答案2
这似乎是一个有趣的问题。由于 thrig 涵盖了 perl 选项,因此这里有一个 bash 脚本可以执行类似的操作。它没有进行足够的错误检查(它假设您正在传递睡眠命令的有效 PID)。它处理相同的语法GNU 的 coreutils 睡眠确实,即:
- s|m|h|d 表示秒/分钟/小时/天的后缀
- 多个时间参数相加
#!/usr/bin/env bash
# input: PID of a sleep command
# output: seconds left in the sleep command
function parse_it_like_its_sleep {
# $1 = one sleep parameter
# print out the seconds it translates to
mult=1
[[ $1 =~ ([0-9][0-9]*)(s|m|h|d) ]] && {
n=${BASH_REMATCH[1]}
suffix=${BASH_REMATCH[2]}
} || {
n=$1
}
case $suffix in
# no change for 's'
(m) mult=60;;
(h) mult=$((60 * 60));;
(d) mult=$((60 * 60 * 24));;
esac
printf %d $((n * mult))
}
# TODO - some sanity-checking for $1
set -- $(ps -o etimes=,args= $1)
[[ $2 = "sleep" ]] || exit 1
elapsed=$1
shift 2
total=0
for arg
do
# TODO - sanity-check $arg
s=$(parse_it_like_its_sleep $arg)
total=$((total + s))
done
printf "%d seconds left\n" $((total - elapsed))
答案3
答案4
使用 tqdm python 模块应该很容易。
显示一个漂亮的视觉进度条,并且可以用作 unix 管道。
https://pypi.python.org/pypi/tqdm
以下 python 代码片段计算 100 秒
import time
from tqdm import tqdm
for i in tqdm(range(100)):
time.sleep(1)
55%|██████████ | 55/100 [00:55<00:45, 1.00s/it]