Apa cara sederhana untuk membiarkan perintah berjalan selama 5 menit? [duplikat]

66

Pertanyaan ini sudah ada jawabannya di sini:

Apakah ada cara mudah untuk membiarkan perintah tertentu (hanya bisa lewat melalui Ctrl-C) berjalan selama 5 menit secara otomatis?

Sebagai contoh:

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

atau perintah lain yang tidak menghentikan dirinya sendiri.

Saya ingin dapat menentukan batas waktu, tidak hanya 5 menit.

eckhart
sumber

Jawaban:

67

Ada (setidaknya) dua program yang menyediakan fungsi ini:

NAMA

timelimit - secara efektif membatasi waktu eksekusi absolut dari suatu proses

RINGKASAN

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

dan

NAMA

timeout - jalankan perintah dengan batas waktu

RINGKASAN

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

Mereka dikemas sebagai berikut:

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

Perbandingan:

/-----------------------------+------------+----------------\
|            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)       |
\-----------------------------+------------+----------------/

Catatan:

  1. timeoutselalu digunakan SIGKILLsebagai sinyal pilihan terakhir.
  2. timeout tidak memiliki fungsi apa pun untuk keluar dengan sinyal ketika program anak melakukannya.

Status keluar dari kedua program berbeda, tetapi itu sulit untuk diringkas dengan rapi, jadi saya sarankan Anda membaca sendiri halaman buku panduan untuk itu.

Seperti timeoutyang diinstal pada lebih banyak sistem secara default ( coreutilsadalah paket standar di banyak distribusi), saya sarankan Anda menggunakannya kecuali Anda memerlukan fungsionalitas tambahan yang disediakan oleh timelimit.

Toby Speight
sumber
10
Mengapa Anda menggunakan yang satu dan bukan yang lain?
Brice M. Dempsey
2
@ BriceM.Dempsey Pada mesin lokal saya, batas waktu ada, tetapi timelimit tidak (walaupun tersedia dari repo). Jadi, jika salah satunya datang pra-instal ... Selain itu, hanya dengan melihat tanda tangan metode saya dapat melihat bahwa mereka melakukan hal yang berbeda, dan memiliki kasus penggunaan yang berbeda.
Benubird
Perhatikan bahwa ada setidaknya dua implementasi dari timelimit. Lihat Bagaimana saya bisa mematikan proses dan pastikan PID belum digunakan kembali untuk info lebih lanjut tentang mereka dan batas waktu GNU.
sch
1
@ BriceM.Dempsey timeouttermasuk dalam GNU coreutils , timelimitbukan. Anda dapat menginstal tidak ada, satu atau keduanya. Untuk yang kedua dilaporkan timelimit mengeksekusi sebuah perintah dan mengakhiri proses spawned setelah waktu tertentu dengan sinyal yang diberikan. Sinyal "peringatan" dikirim terlebih dahulu , kemudian, setelah batas waktu, sinyal "bunuh", mirip dengan cara init (8) beroperasi pada shutdown. Begitu pun berbeda di tengah perilaku.
Hastur
Karena GNU coreutils sudah diinstal pada setiap GNU / Linux, timeoutadalah cara untuk pergi ke sana.
rexkogitans
87

Sebenarnya, ini timeoutuntuk:

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
Gombai Sándor
sumber
16

Murni bashdibangun, tanpa coreutils

Saya menemukan bahwa solusi ini bekerja secara bashmengandalkan built-in perintah tanpa memanggil executable eksternal. Ia bekerja pada sistem di mana akhirnya bahkan tidak diinstal coreutils [ 1 ]

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

Penjelasan : seperti biasa ketika Anda mengirim perintah di latar belakang dengan &, PID yang disimpan ke dalam variabel internal $!(hadir dalam versi modern dash, csh, bash, tcsh, zsh...).
Apa yang benar-benar membuat perbedaan di antara kerang adalah kehadiran built-in command read[ 2 ] dan opsi -t. Dalam versi 1 jika pengguna tidak akan menyelesaikan jalur input sebelum jumlah detik yang ditentukan instruksi akan dihentikan dan kode pengembalian kesalahan akan dihasilkan.

-T TIMEOUT Menyebabkan pembacaan waktu habis dan kegagalan kembali jika jalur input lengkap tidak terbaca dalam TIMEOUT detik.

Versi kedua berfungsi sebagai yang pertama tetapi Anda dapat membatalkan batas waktu pembunuhan hanya dengan menekan enter.
Memang operator atau ||menjalankan killpernyataan hanya jika readperintah keluar dengan kode kembali berbeda dari nol, seperti ketika batas waktu berakhir. Jika Anda menekan entersebelum saat itu, itu akan mengembalikan 0 dan itu tidak akan membunuh perintah Anda sebelumnya.


Solusi Coreutils [ 1 ]

Ketika coreutils hadir pada sistem Anda dan Anda tidak perlu menghemat waktu dan sumber daya untuk memanggil program eksternal, timeoutdan sleepkeduanya merupakan cara sempurna untuk mencapai tujuan Anda.

timeoutPenggunaannya timeoutsangat mudah.
Akhirnya Anda dapat mempertimbangkan untuk menggunakan juga -kopsi untuk mengirim sinyal kill tambahan jika yang pertama gagal.

timeout 5m YourCommand                                         # 3rd version 

sleep Dengan sleepAnda dapat menggunakan fantasi Anda atau mengambil beberapa inspirasi [ 3 ] . Perhatikan bahwa Anda dapat meninggalkan perintah di latar belakang atau di latar depan (misalnya topbiasanya harus di latar depan).

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

Penjelasan

  • Pada versi ke-4 Anda mengeksekusi di latar belakang YourCommandmaka shell Anda sleepuntuk 5 minuites. Ketika akan selesai proses latar belakang terakhir ( $!) akan dibunuh. Anda menghentikan shell Anda.
  • Di versi ke-5 alih-alih Anda mengeksekusi di latar belakang YourCommanddan Anda segera menyimpan PID dalam variabel $pid. Kemudian Anda menjalankan di latar belakang tidur siang 5 menit dan perintah konsekuensinya yang akan membunuh PID yang disimpan. Karena Anda mengirim grup perintah ini di latar Anda tidak menghentikan shell Anda. Anda perlu menyimpan PID dalam variabel karena nilai $!dapat diperbarui dengan eksekusi program lain di latar belakang. Dengan kata-kata sederhana Anda menghindari risiko untuk membunuh proses yang salah atau tidak ada proses sama sekali.
  • Dalam versi ke-6 itu disebut bash shell baru yang akan bunuh diri dalam 5 menit $$, kemudian dieksekusi perintah Anda yang tetap di latar depan.
  • Dalam versi ke-7 itu dipanggil subkulit ()yang menyimpan PID-nya dalam variabel ( cmdpid) dan bunuh diri dengan subkulit lain yang dikirim dalam eksekusi latar belakang, kemudian jalankan YourCommand di latar depan.

Tentu saja di setiap versi Anda dapat mengirim sinyal bunuh yang Anda butuhkan, dari yang standar ke yang ekstrem kill -9 , hanya untuk digunakan ketika benar-benar diperlukan.

Referensi

  • [ 1 ] The Coreutils
  • [ 2 ] Panduan Pemula Bash
  • [ 3 ] BashFAQ
Cepat
sumber
2
"Dengan tidur Anda dapat menggunakan fantasi Anda atau mengambil beberapa inspirasi [tautan ke Bash FAQ]" +1 #thatsenoughinternetfortoday
joeytwiddle
11

Untuk kasus khusus Anda, sebagian besar implementasi pingdukungan -catau --countuntuk mengakhiri setelah sejumlah ping:

ping -c 300 host.example.com

Untuk solusi yang lebih umum, lihat jawaban lainnya.

Toby Speight
sumber
7
Saya mendapatkan kesan OP hanya memberikan pingcontoh konkret. Dia tidak menginginkan solusi kasus per kasus untuk setiap program yang berbeda.
user1717828
8

Anda dapat melakukannya dengan skrip sederhana seperti ini:

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

(sinyal SIGINT = 2 digunakan sesuai saran Matija Nalis dalam komentar di bawah).

Penjelasan tentang ekspresi bash (tidak umum?) $@:...: Parameter posisi, ( $*, $@, "$*", "$@") mengakui spesifikasi tambahan berikut, misalnya:

"${@:START:COUNT}"

yang berarti: dari semua parameter, ambil COUNT dari mereka, yang pertama diambil adalah bahwa pada posisi MULAI; jika COUNT dihilangkan, ambil semuanya sampai akhir, dimulai dengan posisi MULAI. Ingat itu $0adalah nama programnya. Jika MULAI negatif, mulailah menghitung dari akhir, dan ingat bahwa COUNT tidak boleh negatif, maka argumen terakhir adalah "${@:-1}". Juga, hampir selalu menyertakan parameter posisi di dalam tanda kutip ganda.

MariusMatutiae
sumber
1
Saya mungkin akan merancang skrip untuk mengambil waktu sebagai argumen pertama atau terakhir, dan menjalankan semua argumen lainnya sebagai perintah. Membiarkan bash-split $1sangat kotor. Anda juga bisa memasukkan sleep "$1"sesuatu countdown.
Peter Cordes
1
@PeterCordes Selesai, sesuai keinginan Anda.
MariusMatutiae
Waktu dalam arg pertama memungkinkan Anda melakukannya time=$1; shift, dan kemudian Anda tidak perlu sintaks array-slicing untuk parameter posisi. Tapi ya, itu jauh lebih sederhana.
Peter Cordes
1
@PeterCordes Setuju, tetapi Anda meminta saya untuk melihat apakah saya tahu cara yang lebih aman untuk melakukan ini dan saya baru saja malas, atau apakah saya benar-benar bodoh. lol.
MariusMatutiae
sebagai poster yang secara khusus ditanyakan tentang program yang dapat diganggu ctrl-c, mungkin lebih baik untuk mencoba kill -INTdaripada kill -9(atau setidaknya mencoba -9hanya setelah beberapa detik jika yang pertama tidak berhasil - itu memberi peluang program untuk keluar dengan bersih dan tidak meninggalkan file sementara dll sekitar)
Matija Nalis
5

Karena Anda menyebutkan pingdalam contoh Anda; perintah ini memiliki beberapa opsi untuk berhenti setelah waktu tertentu:

  • w tenggat waktu Tentukan batas waktu, dalam detik, sebelum ping keluar terlepas dari berapa banyak paket yang telah dikirim atau diterima. Dalam hal ini ping tidak berhenti setelah paket hitungan dikirim, ia menunggu batas waktu berakhir atau sampai probe jumlah dijawab atau untuk beberapa pemberitahuan kesalahan dari jaringan.
  • W timeout Waktu untuk menunggu respons, dalam detik. Opsi ini hanya memengaruhi batas waktu jika tidak ada tanggapan, jika tidak ping tunggu dua RTT.

-man ping

pengguna2428118
sumber