(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.
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).