একটি "ঘুম" সময় কী পরিমাণ নির্ধারণ করবেন?


11

আমার আছে:

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
নোট করুন যে প্রক্রিয়াগুলি তাদের জীবদ্দশায় একাধিক কমান্ড চালাতে পারে (এবং প্রায়শই করতে পারে)। উদাহরণস্বরূপ sh -c 'sleep 1; sleep 2'অনেকগুলি shবাস্তবায়ন সহ, এটি একই প্রক্রিয়া যা কার্যকর করে shএবং পরে সম্পাদন করে sleep 2(1 সেকেন্ড পরে)।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস আমি মনে করি না যে এখানে এটি ঘটতে পারে, সম্ভবত শেলটি কেবল এটিই শেষ করতে পারে যে এটি চালানো শেষ কমান্ডটিতে অপ্টিমাইজেশন করতে পারে (কারণ এটির পরে নিয়ন্ত্রণ ফিরে পাওয়ার কোনও উপায় নেই exec)। তবে এটি কোনও সাধারণ সমাধানের জন্য একটি ভাল পয়েন্ট।
ডারোবার্ট

আরও মনে রাখবেন যে বেশ কয়েকটি শেল ( mkshএবং ksh93কমপক্ষে) sleepবিল্ট-ইন রয়েছে (তাই এটি দেখায় না ps),, আপনাকে আগে থেকেই জানতে হবে আপনি কোনটি sleepপ্রয়োগের সাথে কাজ করছেন।
স্টাফেন চেজেলাস

উত্তর:


5

জিএনইউ বা সোলারিস ১১ টি sleepআর্গুমেন্টকে সমর্থন করা (এক বা একাধিক <double>[smhd]সময়সীমা, তাই traditionalতিহ্যবাহী বাস্তবায়নের সাথেও কাজ করবে যা কেবলমাত্র একটি দশমিক পূর্ণসংখ্যার সংখ্যা সমর্থন করে (যেমন ফ্রিবিএসডি-তে যেমন), তবে আইএসও -8601 সময়কালের মতো আরও জটিল যুক্তি স্বীকারকারীদের সাথে নয় ))। এর চেয়ে বেশি পোর্টেবল (স্ট্যান্ডার্ড ইউনিক্স) হিসাবে ব্যবহার etimeকরা etimes

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হ'ল ?অক্ষরগুলি থেকে মুক্তি দেওয়া যা procps' psনিয়ন্ত্রণের অক্ষরগুলির প্রতিস্থাপন হিসাবে ব্যবহার করে it এটি ব্যতীত, এটি বিশ্লেষণ করতে ব্যর্থ হবে sleep $'\r1d'বা sleep $'\t1d'... দুর্ভাগ্যক্রমে, Cলোকেল সহ কিছু লোকেলগুলিতে এটি এর .পরিবর্তে ব্যবহার করে ?। আমরা বেশি কিছু করতে পারি না সেই ক্ষেত্রে যেমন একটি \t5dথেকে কোনও বলার উপায় নেই.5d (অর্ধ দিন) ।

তর্ক হিসাবে পিড পাস।

যে অনুমান 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;

1
0xffp-6d... এখন, এটি একটি পরীক্ষার কেস! তবে প্রকৃতপক্ষে জিএনইউ sleep 1h 30m
স্লিপও এ জাতীয়

@derobert। দোহ আমি শপথ করতে পারি আমি চেষ্টা করেছিলাম। আমি চেষ্টা করেছি আবশ্যক অনুমান sleep 1h -1mযা সোলারিস 11 কিন্তু গনুহ সাথে কাজ করে sleep। অঙ্কন বোর্ড ফিরে। কমপক্ষে এটি ksh93 এর মতো আইসো 8601 সময়কাল সমর্থন করে না যা অনেক বেশি শক্ত হবে।
স্টাফেন চেজেলাস

@ আর্ডারবার্ট, বেশ কয়েকটি যুক্তি সমর্থন করার জন্য আপডেট করেছেন
স্টাফেন চ্যাজেলাস

@ স্টাফেনচেজেলাস আপনার সমাধানটি ভাল, যদিও এটি sleepবিরতিতে দেওয়া হলে এটি কাজ করবে না । এটি এমনকি এই ক্ষেত্রে নেতিবাচক মান প্রদর্শন করতে পারে।
নলখাগড়া

এই জরিমানাটি এক সপ্তাহ ধরে ব্যবহার করছেন তবে আজ remaining_sleep_time 12838ফিরে এসেছেন -40642। এটি "বিরতি" তে থাকতে পারে যেমন @ রাশ বলেছেন তবে কীভাবে ডিবাগ করবেন তা নিশ্চিত নন?
WinEunuuchs2Unix

3

এটি সমাধান করার মতো একটি মজাদার সমস্যা মনে হয়েছিল; যেহেতু থ্রিগ একটি পার্ল বিকল্পটি কভার করেছে তাই এখানে একটি বাশ স্ক্রিপ্ট রয়েছে যা একই রকম কিছু করে। এটি যথেষ্ট ত্রুটি-পরীক্ষা করে না (এটি ধরে নেওয়া হয় যে আপনি একটি স্লিপ কমান্ডের একটি বৈধ পিআইডি দিয়ে যাচ্ছেন)। এটি জিএনইউর কোর্টিলগুলি ঘুমের মতো একই সিনট্যাক্সটি পরিচালনা করে, যথা:

  • s | মি | এইচ | ডি সেকেন্ড / মিনিট / ঘন্টা / দিনের জন্য প্রত্যয়
  • একাধিক সময়ের পরামিতি একসাথে যুক্ত হয়

#!/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))

এমনকি জিএনইউ স্লিপ সীমাবদ্ধ থাকলেও (সোলারিস 11 বা ksh93 বিল্টিনের মতো কিছু ঘুম বাস্তবায়ন আরও অনেক জটিল সময়কাল এক্সপ্রেশন সমর্থন করে), এটি অসম্পূর্ণ কারণ এটি ভাসমান পয়েন্ট সংখ্যার (যেমন sleep 0.5dবা sleep 1e5বা sleep infinity) কাজ করে না । bashZsh, ksh93 বা যশের মতো ভাসমান পয়েন্টগুলিকে সমর্থনকারী শেল থেকে স্যুইচ করা সহায়তা করবে। এটি etimesপোর্টেবল নয়।
স্টাফেন চেজেলাস

ভাসমান পয়েন্টটি পার্সিংয়ের খরগোশের ছিদ্রটি আমার যেতে ইচ্ছুক চেয়ে গভীরতর হয়েছিল, তাই আমি এই সীমাবদ্ধতাগুলি রেখে যেতে পারি এবং ওপির পরামর্শের তুলনায় এটি কেবলমাত্র একটি সামান্য উন্নতি (এটি পিআইডি থেকে ঘুমের সময় নির্ধারণ করতে পারে) বনাম হার্ড-কোডিং এতে)।
জেফ শ্যাচলার


1

এটি কোনও স্ক্রিপ্টের সাথে আরও ভালভাবে করা যেতে পারে যা কোনও QUIT(সাধারণত control+\) বা INFOসিগন্যালের সাহায্যে অবশিষ্ট সময়টি প্রদর্শন করতে পারে ।

#!/usr/bin/env perl
#
# snooze - sleep for a given duration, with SIGINFO or SIGQUIT
# (control+\ typically) showing how much time remains. Usage:
#
#   snooze 3m; make-noise-somehow
#
# or with
#
#   snooze 25m bread; make-noise-somehow
#
# one can then elsewhere
#
#   pkill -INFO snooze-bread

use strict;
use warnings;
use Term::ReadKey qw(ReadMode);

my %factors = ( s => 1, m => 60, h => 3600, d => 86400 );

my $arg = shift or die "Usage: $0 sleep-time [label]\n";
my $to_sleep = 0;
while ( $arg =~ m/([0-9]+)([smhd])?/g ) {
    my $value  = $1;
    my $factor = $2;
    $value *= $factors{$factor} if $factor;
    $to_sleep += $value;
}
die "nothing to die to sleep to sleep no more for\n" if $to_sleep == 0;

my $label = shift;
$0 = $label ? "snooze-$label" : "snooze";

ReadMode 2;    # noecho to hide control+\s from gunking up the message

sub remainder { warn "$0: " . deltatimefmt($to_sleep) . " remaining\n" }

sub restore {
    ReadMode 0;
    warn "$0: " . deltatimefmt($to_sleep) . " remainds\n";
    exit 1;
}

# expect user to mash on control+\ or whatever generates SIGINFO
for my $name (qw/ALRM INFO QUIT/) {
    $SIG{$name} = \&remainder;
}

# back to original term settings if get blown away
for my $name (qw/HUP INT TERM USR1 USR2/) {
    $SIG{$name} = \&restore;
}

$SIG{TSTP} = 'IGNORE';    # no Zees for you!

while ( $to_sleep > 0 ) {
    $to_sleep -= sleep $to_sleep;
}

ReadMode 0;
exit;

sub deltatimefmt {
    my $difference = shift;

    return "0s" if $difference == 0;

    my $seconds = $difference % 60;
    $difference = ( $difference - $seconds ) / 60;
    my $minutes = $difference % 60;
    $difference = ( $difference - $minutes ) / 60;

    #  my $hours = $difference;
    my $hours = $difference % 24;
    $difference = ( $difference - $hours ) / 24;
    my $days  = $difference % 7;
    my $weeks = ( $difference - $days ) / 7;

    # better way to do this?
    my $temp = ($weeks) ? "${weeks}w " : q{};
    $temp .= ($days)    ? "${days}d "    : q{};
    $temp .= ($hours)   ? "${hours}h "   : q{};
    $temp .= ($minutes) ? "${minutes}m " : q{};
    $temp .= ($seconds) ? "${seconds}s"  : q{};
    return $temp;
}

সত্যই প্রশ্নের উত্তর দেয় না (যেহেতু আমার ঘুম ইতিমধ্যে চলছিল) তবে ভবিষ্যতে এটি এড়ানো যায়, তাই এখনও কার্যকর। যদি কোথাও একটি টার্মিনাল কাউন্টডাউন এলার্ম ইউটিলিটি থাকে তা
অবাক হোন

আরও দেখুন zsh'র schedএবং atআরেকটি পন্থা সেই সময় অনুসন্ধান অনুমতি দেয় জন্য কমান্ড।
স্টাফেন চেজেলাস

0

Tqdm পাইথন মডিউল সহ যথেষ্ট সহজ হওয়া উচিত।

একটি দুর্দান্ত চাক্ষুষ অগ্রগতি বার দেখায় এবং ইউনিক্স পাইপ হিসাবে ব্যবহার করা যেতে পারে।

https://pypi.python.org/pypi/tqdm

নিম্নলিখিত অজগর স্নিপেট 100 সেকেন্ড গণনা করে

import time
from tqdm import tqdm
for i in tqdm(range(100)):
    time.sleep(1)

55% | ██████████ | 55/100 [00:55 <00:45, 1.00 সেকেন্ড / এটি]


পৃষ্ঠাটি দেখার থেকে কীভাবে সহজ হবে তা আমি দেখতে পাই না (যদিও আমি পাইথন প্রোগ্রামার নই)। আপনার মনে মনে কিছু আছে — দয়া করে আপনার উত্তরে এটি যুক্ত করুন।
ডারোবার্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.