Bir komutun 5 dakika boyunca çalışmasına izin vermenin basit bir yolu nedir? [çift]


66

Belirli bir komutun (yalnızca sonlandırılabilir Ctrl-C) 5 dakika süreyle otomatik olarak çalışmasına izin vermenin kolay bir yolu var mı ?

Örneğin:

minute-command 5-minutes ping www.google.com

veya kendisini sonlandırmayan herhangi bir komut.

Sadece 5 dakika değil, bir süre de belirtmek istiyorum.

Yanıtlar:


67

Bu işlevi sağlayan (en az) iki program vardır:

ADI

timelimit - bir sürecin mutlak yürütme süresini etkin bir şekilde sınırlandırmak

ÖZET

timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]

ve

ADI

timeout - bir zaman sınırı ile bir komut çalıştırmak

ÖZET

timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]

Aşağıdaki şekilde paketlenirler:

$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout

karşılaştırma:

/-----------------------------+------------+----------------\
|            Feature          |  timelimit |     timeout    |
+=============================+============+================+
|   time to run               | -t time    | first argument |
+-----------------------------+------------+----------------+
|   terminate signal          | -s signal  | -s signal      |
+-----------------------------+------------+----------------+
|   grace period              | -T time    | -k time        |
+-----------------------------+------------+----------------+
|   kill signal               | -S signal  | (note 1)       |
+-----------------------------+------------+----------------+
|   propagate signals         | -p         | (note 2)       |
\-----------------------------+------------+----------------/

Notlar:

  1. timeoutdaima SIGKILLson çare olarak kullanır .
  2. timeout Çocuk programı böyle yaptığında bir sinyal ile çıkmak için herhangi bir işlevselliğe sahip değildir.

İki programın çıkış durumu farklıdır, ancak düzgün bir şekilde özetlenmesi zordur, bu yüzden bunun için kılavuz sayfalarına göz atmanızı öneririm.

As timeoutvarsayılan olarak daha sistemlerde yüklü ( coreutilsben kullanmak yönünde birçok dağılımları standart paket) belirlersiniz tarafından sağlanan ekstra işlevsellik gerekmedikçe timelimit.


10
Neden birini değil diğerini kullandın?
Brice M. Dempsey,

2
@ BriceM.Dempsey Yerel makinemde zaman aşımı var ancak zamanaşımı yok (her ne kadar depoda mevcut olsa da). Yani, eğer biri önceden kurulursa ... Bunun dışında, sadece yöntem imzalarına bakıp farklı şeyler yaptıklarını ve farklı kullanım durumları olduğunu görebiliyorum.
Benubird

Bunun en az iki uygulaması olduğunu unutmayın timelimit. Bkz Ben bir süreç öldürmek ve PID yeniden edilmemiştir emin olabilir nasıl onları ve GNU zaman aşımı konusunda daha fazla bilgi için.
sch,

1
@ BriceM.Dempsey timeoutGNU coreutils içinde bulunur timelimit, değildir. Bunlardan birini veya her ikisini de yükleyebilirsiniz. İkincisi için bir zamanlama işleminin bir komutu yerine getirdiği ve verilen bir süre sonra verilen bir sinyal ile ortaya çıkan süreci sonlandırdığı bildirilir . Önce bir "uyarı" sinyali gönderilir , daha sonra, bir zaman aşımından sonra, init (8) kapatma işlemine benzer şekilde bir "öldür" sinyali gönderilir. Yani orta davranışta bile farklı .
Hastur

GNU coreutils her GNU / Linux'a önceden kurulmuş timeoutolduğundan, oraya gitmek için yol budur.
rexkogitans

87

Aslında, bu ne timeoutiçin:

TIMEOUT(1)                          User Commands                         TIMEOUT(1)

NAME
       timeout - run a command with a time limit

SYNOPSIS
       timeout [OPTION] DURATION COMMAND [ARG]...
       timeout [OPTION]

DESCRIPTION
       Start COMMAND, and kill it if still running after DURATION.

lx@lxtp:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout

16

Coreutilsbash olmadan saf yerleşik

Bu çözümün harici bir yürütülebilir dosyayı çağırmadan yerleşikbash bir komuta güvenerek çalıştığını gördüm . Sonunda coreutils bile kurulmamış olan sistemde çalışır [ 1 ]

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 

Açıklamalar : zamanki gibi arka planda bir komut gönderirken &kendi PID iç değişken içine saklanır, $!(modern versiyonunda mevcut dash, csh, bash, tcsh, zsh...).
Kabuklar arasındaki farkı gerçekten yapan şey, yerleşik komutun read[ 2 ] ve seçeneğin varlığıdır -t. 1. versiyonda, kullanıcı belirtilen saniye miktarından önce bir girdi satırını tamamlamazsa, talimat sonlandırılacak ve bir hata dönüş kodu üretilecektir.

-t TIMEOUT TIMEOUT saniye içinde tam bir giriş satırı okunmazsa zaman aşımı ve geri dönüş hatası için okumaya neden olun.

İkinci versiyon 1 olarak çalışır, ancak sadece basarak öldürme zaman aşımını iptal edebilirsiniz enter.
Aslında, veya operatörü ifadeyi yalnızca komut, zamanaşımı süresi dolduğunda olduğu gibi sıfırdan farklı bir dönüş koduyla çıkarsa ||çalıştırır . O andan önce basarsanız , 0 değerini döndürür ve önceki komutunuzu öldürmez.killreadenter


Coreutils çözümleri [ 1 ]

Ne zaman coreutils sisteminizde mevcut ve harici bir program çağırmak için zaman ve kaynak tasarrufu hiç gerek yok, timeoutve sleepve hedefe ulaşmak için her iki mükemmel yollarıdır.

timeoutKullanımı timeoutbasittir.
Sonunda -k, ilk başarısız olursa ek bir öldürme sinyali gönderme seçeneğini kullanmayı düşünebilirsiniz .

timeout 5m YourCommand                                         # 3rd version 

sleep Seninle sleepfantezini kullanabilirsin ya da biraz ilham alabilirsin [ 3 ] . Komutunuzu arka planda veya ön planda bırakabileceğinizi unutmayın (örneğin topgenellikle ön planda olması gerekir).

YourCommand & sleep 5m; kill $!                                # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) &                # 5th Background

bash -c '(sleep 5m; kill $$) & exec YourCommand'               # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground

açıklamalar

  • Dördüncü versiyonda arka planda çalıştırıyorsunuz, YourCommandardından kabuğunuz sleep5 dak. Bittiğinde son arka plan süreci ( $!) öldürülecek. Kabuğunu durdur.
  • 5. versiyonda bunun yerine arka planda çalıştırıyorsunuz YourCommandve hemen bu PID'yi değişkende saklıyorsunuz $pid. Ardından, arka planda 5 dakikalık bir kestirmeden sonra saklanan PID'i öldürecek komutunu uygularsınız. Bu komut grubunu arka planda gönderdiğiniz için, kabuğunuzu durdurmazsınız. PID'i bir değişkende saklamanız gerekir, çünkü değeri $!arka planda başka bir programın sonunda çalıştırılmasıyla güncellenebilir. Basit bir deyişle , yanlış işlemi ya da hiç işlem yapmama riskini önlersiniz .
  • 6. versiyonda 5 dakika içinde intihar edecek olan yeni bir bash kabuğu denir $$, sonra ön planda kalan emrinizi yerine getirir.
  • 7. versiyonda , PID'sini ()bir değişkende ( cmdpid) saklayan ve arka plan yürütme sırasında gönderilen başka bir alt kabuk ile kendisini öldüren bir alt kabuk çağrılır, ardından YourCommand'ı ön planda çalıştırır.

Elbette her versiyonda , sadece gerçekten ihtiyaç duyulduğunda kullanılmak üzere varsayılandan aşırıya kadar ihtiyacınız olan öldürme sinyalini gönderebilirsiniz kill -9.

Referanslar

  • [ 1 ] Coreutils
  • [ 2 ] Bash Yeni Başlayanlar Rehberi
  • [ 3 ] BashFAQ

2
"Uykuyla fantezini kullanabilirsin ya da biraz ilham alabilirsin [Bash SSS sayfasına link ver") +1 #thatsenoughinternetfortoday
joeytwiddle

11

Özel durumunuz için, çoğu pingdestek uygulaması -cveya --countbelirli bir sayıdaki ping'den sonra sonlandırma:

ping -c 300 host.example.com

Daha genel bir çözüm için diğer cevaplara bakınız.


7
Sadece pingsomut bir örnek için sağlanan OP izlenimini alıyorum . Her farklı program için bir durum çözümü istemiyor.
user1717828

8

Bunu basit bir komut dosyasıyla yapabilirsiniz:

#!/bin/bash

#
# $1 is the time to let the program run, and $2, $3, ... are the command itself.
#

"${@:2}" &
PID=$!
sleep "${@:1:1}"
kill -2 $PID

(aşağıdaki yorumda Matija Nalis'in önerisine göre SIGINT = 2 sinyali kullanılmıştır).

(Yaygın değil mi?) Bash ifadesinin bir açıklaması $@:...: konumsal parametreler, ( $*, $@, "$*", "$@"), örneğin aşağıdaki ek belirtimi kabul eder:

"${@:START:COUNT}"

bunun anlamı şudur: tüm parametreler, bunlardan COUNT, ilk alınacak olan STARTth pozisyonunda; COUNT ihmal edilirse, hepsini BAŞLAT pozisyonundan başlayarak sonuna kadar alın. Unutma ki $0programın adı. BAŞLAT negatifse, en baştan saymaya başlayın ve COUNT'ın negatif olamayacağını unutmayın , bu nedenle son argümandır "${@:-1}". Ayrıca, hemen hemen her zaman çift ​​tırnak içine konumsal parametreleri ekleyin.


1
Muhtemelen senaryoyu ilk veya son argüman olarak ayıracak ve diğer tüm argümanları komut olarak çalıştıracağım. Kesik kelime bölünmesine izin vermek $1oldukça iğrençtir. Ayrıca, sadece sleep "$1"ya da içinde bir şey olabilir countdown.
Peter Cordes

1
@PeterCordes Dileklerinize göre tamamlandı.
MariusMatutiae

İlk argümandaki zaman yapmanıza izin verir time=$1; shift, ve sonra konumsal parametreler için dizi dilimleme sözdizimine ihtiyacınız yoktur. Ama evet, bu çok daha basit.
Peter Cordes

1
@PeterCordes Kabul etti, ancak bunu yapmanın daha güvenli bir yolunu bilip bilmediğimi ve sadece tembel olduğumu veya sadece cahil olup olmadığımı görmemi istediniz. lol.
MariusMatutiae

Özellikle ile kesilebilir programla ilgili sorulan poster olarak ctrl-c, denemek için muhtemelen daha iyidir kill -INTyerine kill -9(veya en azından denemek -9geçici dosyalar bırakırlar temiz çıkmak değil program şans verir - İlki suceed olmasaydı birkaç saniye sonra sadece vb))
Matija Nalis

5

pingÖrnekte bahsettiğinizden beri ; bu komut belirli bir süre sonra durması gereken birkaç seçeneğe sahiptir:

  • w tarihine önce saniye cinsinden bir zaman aşımı belirtin ping bakılmaksızın gönderilen veya alınan kaç paket içinde çıkar. Bu durumda, ping , sayılan paket gönderildikten sonra durmaz , son teslim tarihinin geçmesini veya sayım sondaları cevaplanıncaya veya ağdan gelen bazı hata bildirimlerini bekler .
  • W zaman aşımı Saniye cinsinden bir yanıt beklemek için gereken süre. Bu seçenek, yanıt yokluğunda sadece zaman aşımını etkiler, aksi takdirde ping iki RTT'yi bekler.

-man ping

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.