GNU/Linux >> Belajar Linux >  >> Linux

Blokir/Cegah Perintah Jika Telah Dieksekusi Dalam X Detik/Menit Terakhir?

(Hanya untuk melengkapi:cerita; Anda tidak perlu membaca ini jika Anda tidak ingin tahu mengapa saya menanyakan pertanyaan ini :Saya mendapat aplikasi setan webcam (disebut "gerakan") dengan deteksi gerakan kamera. Setan ini mampu memicu perintah khusus ketika ada gerakan yang terdeteksi oleh kamera. Saya selanjutnya menginstal program commandline kecil yang dengan mudah dapat mengirim pemberitahuan push ke ponsel android saya. Saya mengonfigurasi cam-demon untuk menjalankan perintah push-message saat dia mendeteksi gerakan.)

Masalahnya:Setan memicu perintah khusus itu dengan setiap frame yang dia ambil untuk sebuah gerakan, membawa saya ke sejumlah besar pemberitahuan push ketika ada gerakan terus menerus hanya – katakanlah – 5 detik (framerate kamera disetel ke 10 pics/second jadi saya mendapatkan 10 push-msgs setiap detik yang dianggap sebagai gerakan).

Saya memerlukan skrip atau program yang memblokir perintah push-msg tersebut jika sudah dijalankan dalam x detik/menit terakhir.

Saya bisa membayangkan sesuatu seperti:

$ proxy_command.sh --block_time=10s --command==androidpush -msg "There was a motion in your flat!"

Saya tidak dapat menemukan cara mudah/namun elegan untuk menyelesaikan ini (tanpa menulis file dengan cap waktu dan kemudian memeriksa konten file itu). Saya juga tidak dapat menemukan seseorang yang memiliki masalah serupa.

Apakah ada semacam proksi perintah atau sesuatu yang akan menyelesaikan masalah saya seperti yang dijelaskan di atas semudah mungkin?

Jawaban yang Diterima:

Menyimpan waktu pemanggilan terakhir sebagai waktu modifikasi terakhir dari sebuah file

perl

#! /usr/bin/perl
# usage: cmd file seconds cmd args
$file = shift @ARGV;
$time = shift @ARGV;
$age = -M $file;
exit 3 if defined($age) && 86400 * $age < $time;
open $fh, ">>", $file ||
  die "Can't open $file: $!\n";
utime undef, undef, $fh;
exec @ARGV;

Untuk digunakan seperti:

that-script /some/file 10 androidpush -msg 'There was a motion in your flat!'

Ini mencatat waktu terakhir dijalankan sebagai waktu modifikasi terakhir /some/file dan tidak menjalankan perintah jika usia file tersebut kurang dari waktu yang ditentukan.

kulit

Dengan BSD atau GNU find , Anda dapat melakukannya dengan:

#! /bin/sh -
file=${1?} time=${2?}
shift 2

[ "$(find -- "$file" -prune -newermt "$time ago")" ] && exit 3
touch -- "$file"
exec "[email protected]"

Untuk dijalankan sebagai:

that-script /some/file 10sec androidpush -msg 'There was a motion in your flat!'

Bagaimanapun, Anda harus menyimpan informasi tentang run terakhir di beberapa tempat yang bertahan untuk run berikutnya. Sistem file adalah tempat yang jelas untuk itu. Itu adalah tempat di mana Anda dapat memesan beberapa area untuk diri sendiri.

proses tidur dengan nama tertentu

Namespace lain bisa jadi misalnya nama proses:

#! /bin/bash -
label=$0-$(logname)@${1?} time=${2?}
shift 2
pgrep -f "^$label" > /dev/null 2>&1 && exit 3
(exec -a "$label" sleep "$time") &
exec "[email protected]"

Untuk digunakan sebagai:

that-script motion 10 androidpush -msg 'There was a motion in your flat!'

(dengan asumsi sleep implementasi yang tidak peduli dengan argv[0] its ).

Kami menggunakan bash bukannya sh untuk exec -a arg0 . Jika Anda tidak memiliki bash , shell lain yang mendukung yang menyertakan ksh93 , mksh , yash dan zsh . Atau Anda dapat kembali ke perl lagi.

Terkait:Mengaktifkan Modul Direktori Aktif untuk PowerShell melalui baris perintah?

Perhatikan bahwa namespace tidak dicadangkan. Tidak ada yang mencegah pengguna lain untuk membuat proses dengan nama yang sama (sebagai lawan menggunakan ~/.lastrun file dalam pendekatan berbasis file), namun mengingat bahwa di sini skrip tersebut semuanya dimulai dengan motion yang sama proses, Anda dapat membatasi proses pencarian untuk proses yang memiliki id proses induk yang sama:

Peningkatan ketika semua skrip selalu dimulai dengan proses yang sama

#! /bin/bash -
label=$0-${1?} time=${2?}
shift 2
pgrep -P "$PPID" -f "^$label" > /dev/null 2>&1 && exit 3
(exec -a "$label" sleep "$time") &
exec "[email protected]"

Khusus Linux:gunakan kunci kernel dengan batas waktu

Di Linux, Anda juga dapat menggunakan kunci pada keyring sesi pengguna. Itu tidak benar-benar dirancang untuk itu, tetapi ini berguna karena kunci-kunci itu bertahan sepanjang waktu dan dapat diberikan batas waktu:

#! /bin/sh -
key=$0-${1?} time=${2?}
shift 2
keyctl search @us user "$key" > /dev/null 2>&1 && exit 3
key=$(keyctl add user "$key" x @us) || exit
keyctl timeout "$key" "$time" || exit
exec "[email protected]"

Sekarang, itu tidak terlalu penting dalam kasus Anda karena Anda tidak menjalankan dua instance skrip itu secara bersamaan, tetapi semuanya memiliki kondisi balapan yang membuatnya tidak menjamin bahwa dua instance tidak akan berjalan dalam waktu yang ditentukan. Jika dua instance dijalankan pada saat yang sama, keduanya dapat memverifikasi bahwa kondisinya baik-baik saja sebelum salah satu dari mereka menyetel ulang.

Mengunci file untuk menghindari kondisi balapan

Pendekatan yang akan mengatasinya adalah dengan memiliki sleep proses menahan kunci pada file:

#! /bin/sh -
file=${1?} time=${2?}
shift 2
{
  flock -n 3 || exit 3
  sleep "$time" 3>&3 &
  exec "[email protected]"
} 3<> "$file"

(sebagai tambahan di sini, keduanya sleep dan perintah yang dijalankan akan menahan kunci yang akan memastikan tidak ada dua contoh perintah yang dijalankan pada saat yang sama bahkan jika mereka membutuhkan waktu lebih lama untuk dijalankan daripada sleep perintah).


Linux
  1. Trik terminal Linux:Retas perintah cd untuk mengingat di mana Anda pernah berada

  2. Linux – Bagaimana Cara Melihat Commandline Proses yang Dieksekusi Dalam 10 Detik Terakhir?

  3. $_ Vs !$. Argumen Terakhir Dari Perintah Sebelumnya Dan Pengalihan Output?

  1. Bagaimana Cara Mengakses Argumen Terakhir Dari Perintah yang Dikomentari?

  2. Perintah "java" tidak menjalankan JVM yang telah diinstal

  3. Temukan file yang telah diubah dalam 24 jam terakhir

  1. Apa yang menyebabkan perintah file di Linux melaporkan file teks sebagai data biner?

  2. Bagaimana cara mencetak baris terakhir dari file terkompresi gz di baris perintah?

  3. Perintah untuk memaksa lengan hard drive bergerak ke posisi tertentu pada piringan