Suportando os argumentos GNU ou Solaris 11 sleep
(um ou mais <double>[smhd]
de durações, também funcionaria com implementações tradicionais que suportam apenas um número inteiro decimal (como no FreeBSD), mas não com aqueles que aceitam argumentos mais complexos como Durações ISO-8601 ). Usando etime
em vez de etimes
, pois é mais portátil (Unix padrão).
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'
}
(o s/\?//g
é para se livrar dos caracteres ?
que procps
' ps
usa como substitutos dos caracteres de controle. Sem ele, não seria possível analisar sleep $'\r1d'
ou sleep $'\t1d'
. Infelizmente, em algumas localidades, incluindo o C
locale, ele usa .
em vez de ?
. Não há muito o que fazer nesse caso, pois não há como informar a \t5d
de .5d
(metade dia)).
Passe o pid como argumento.
Isso também pressupõe que o argv[0]
passado para sleep
não contenha espaços em branco e que o número de argumentos seja pequeno o suficiente para não ser truncado por ps
.
Exemplos:
$ sleep infinity & remaining_sleep_time "$!"
Inf
$ sleep 0xffp-6d &
$ remaining_sleep_time "$!"
344249
$ sleep 1m 1m 1m 1m 1m & remaining_sleep_time "$!"
300
Para uma saída [[[ddd-]HH:]MM:]SS
em vez de apenas o número de segundos, substitua o print $t
por:
$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;