如何确定“睡眠”还剩多少时间?

如何确定“睡眠”还剩多少时间?

我有:

sleep 210m && for i in $(seq 1 5); do echo -e '\a'; sleep 0.5; done 

作为一个简单、简洁的计时器运行来提醒我什么时候应该做某事。即sleep 210mPID 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 (半天))。procpspssleep $'\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

如果您正在寻找一个简单的解决方案,您可以使用ps aux,它显示了开始时间。 但您可能只想将其用于快速近似,而不是运行精确值。

在此示例中,开始时间为 15:47。所以睡眠会在15点57分左右结束

在此输入图像描述

答案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]

相关内容