GNU/Linux >> Linux の 問題 >  >> Linux

過去X秒/分以内に実行されたコマンドをブロック/防止しますか?

(完成のために:ストーリー; 私がこの質問をしている理由を知りたくない場合は、これを読む必要はありません :カメラモーション検出機能を備えたWebカメラデーモンアプリケーション(「モーション」と呼ばれる)を入手しました。このデーモンは、カメラによってモーションが検出されたときにカスタムコマンドをトリガーできます。さらに、Androidモバイルにプッシュ通知を簡単に送信できる小さなコマンドラインプログラムをインストールしました。動きを検出したときにそのpush-message-commandを実行するようにcam-demonを構成しました。)

問題:悪魔は、モーションに必要なすべてのフレームでカスタムコマンドをトリガーし、5秒間の連続モーションがあると、大量のプッシュ通知が表示されます(カメラのフレームレートは10に設定されています)。写真/秒なので、モーションと見なされる毎秒10回のプッシュメッセージを取得します。

過去x秒/分ですでに実行されている場合は、そのpush-msgコマンドをブロックするスクリプトまたはプログラムが必要です。

私は次のようなものを想像することができます:

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

これを解決する簡単でエレガントな方法を見つけることができませんでした(タイムスタンプ付きのファイルを書き込んでから、そのファイルの内容を確認する必要があります)。どちらも同様の問題を抱えている人を見つけることができませんでした。

上記のような私の問題をできるだけ簡単に解決するようなコマンドプロキシや何かがありますか?

承認された回答:

最後の呼び出し時刻をファイルの最終変更時刻として保存する

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;

次のように使用します:

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

最後の実行時刻を/some/fileの最終変更時刻として記録します そのファイルの経過時間が指定された時間よりも短い場合、コマンドは実行されません。

シェル

BSDまたはGNUの場合find 、あなたはそれを行うことができます:

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

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

実行するには:

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

いずれの場合も、前回の実行に関する情報を、次の実行のために保持される場所に保存する必要があります。ファイルシステムはそのための明白な場所です。それはあなたがあなた自身のためにいくつかの領域を予約することができるものです。

特定の名前のスリーププロセス

別の名前空間は、たとえばプロセス名である可能性があります:

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

使用目的:

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

sleepを想定 argv[0]を気にしない実装 。

bashを使用しています shの代わりに exec -a arg0の場合 。 bashがない場合 、ksh93を含むサポートする他のシェル 、mkshyash およびzsh 。または、perlに戻すこともできます もう一度。

関連:コマンドラインからPowerShell用のActive Directoryモジュールを有効にしますか?

名前空間は予約されていないことに注意してください。 (~/.lastrunを使用するのとは対照的に、別のユーザーが同じ名前のプロセスを作成することを妨げるものは何もありません。 ただし、ここでは、これらのスクリプトはすべて同じmotionによって開始されます。 プロセスの場合、プロセスの検索を同じ親プロセスIDを持つプロセスに制限できます:

すべてのスクリプトが常に同じプロセスで開始される場合の改善

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

Linuxのみ:タイムアウト付きのカーネルキーを使用

Linuxでは、ユーザーのセッションキーリングでキーを使用することもできます。これは実際にはそのために設計されたものではありませんが、これらのキーは時間の経過とともに存続し、タイムアウトを与えることができるため、ここでは便利です:

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

さて、あなたがそのスクリプトの2つのインスタンスを同時に実行していないので、あなたのケースでは実際には問題ではありませんが、それらはすべて競合状態を持っているため、2つのインスタンスが実行されないことは保証されません。指定された時間内に実行します。 2つのインスタンスが同時に実行される場合、どちらかがリセットする前に、両方が条件に問題がないことを確認できます。

競合状態を回避するためにファイルをロックする

これを回避するアプローチは、sleepを使用することです。 プロセスはファイルのロックを保持します:

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

(さらに、ここでは、両方のsleep また、実行中のコマンドはロックを保持し、sleepよりも実行に時間がかかる場合でも、コマンドの2つのインスタンスが同時に実行されないようにします。 コマンド)。


Linux
  1. コメントされたコマンドの最後の引数にアクセスする方法は?

  2. シェルで最後に実行されたコマンドの実行時間を見つける方法はありますか?

  3. 過去 24 時間に変更されたファイルを見つける

  1. Linux の file コマンドがテキスト ファイルをバイナリ データとして報告する原因は何ですか?

  2. コマンドラインで gz 圧縮ファイルの最後の行を出力するには?

  3. ハード ドライブ アームをプラッター上の特定の位置に強制的に移動させるコマンド

  1. Linuxで最後に実行されたコマンドを再実行する2つの方法

  2. Bash Echoコマンドライン自体で実行されるコマンドライン(スクリプトではない)?

  3. dd コマンドの最適なバイト サイズを決定する方法