web-dev-qa-db-ja.com

Bashスクリプト、監視フォルダー、コマンドの実行

ディレクトリとコマンドの2つのパラメーターを取るbashスクリプトを作成しようとしています。このディレクトリの変更を監視する必要があり、何かが変更されたらコマンドを実行する必要があります。私はbashスクリプトを書くのは初めてで、何をしているのかよくわかりません。また、LinuxではなくMacを使用しています。任意のポインター、または外部リソースが大いに役立ちます。多くの人がインターネットでこれを試しており、誰もそれを正しくできないように見えることを知っています。私は本当にSASSの時計機能を真似しようとしています。

#!/bin/bash

#./watch.sh $PATH $COMMAND

DIR=$1  

ls -l $DIR > $DIR/.begin
#this does not work
DIFFERENCE=$(diff .begin .end)

if [ $DIFFERENCE = '\n']; then
    #files are same
else
    $2
fi 

ls -l $DIR > $DIR/.end
35
ThomasReggi

フォルダーの変更を監視し、更新時にlessコンパイラーを実行する例を次に示します。前提条件として、 npm およびこれらのモジュール onchange が必要です。ノードコミュニティには、さまざまな監視コマンド(onchangeなど)が大量にあります。コンパイル済みの自己完結型のバイナリは知りません。

npm install less onchange -g

次に、次のようなものを使用できます。

onchange "./stylesheets/*.less" -- lessc main.less > main.css

Grunt answer よりもBASHコマンドを好む。

10
ThomasReggi

フォルダー(md5)を継続的に再帰的に監視し、変更時にコマンドを実行するには:

daemon() {
    chsum1=""

    while [[ true ]]
    do
        chsum2=`find src/ -type f -exec md5 {} \;`
        if [[ $chsum1 != $chsum2 ]] ; then           
            compile
            chsum1=$chsum2
        fi
        sleep 2
    done
}

digestがないため、OS Xで動作します。

Linuxでは、md5sumコマンドの代わりにmd5を使用できます。

37
Radek

メソッド1:

_#!/bin/sh

check() {
    dir="$1"
    chsum1=`digest -a md5 $dir | awk '{print $1}'`
    chsum2=$chsum1

    while [ $chsum1 -eq $chsum2 ]
    do
        sleep 10
        chsum2=`digest -a md5 $dir | awk '{print $1}'`
    done

    eval $2
}

check $*
_

このスクリプトは、2つのパラメーター[ディレクトリ、コマンド]を取ります。 10秒ごとにスクリプトはcheck()を実行して、フォルダーが変更されたことを確認します。そうでない場合はスリープし、サイクルが繰り返されます。

フォルダーが変更された場合は、evalsコマンドになります。

メソッド2:
cronを使用してフォルダーを監視します。

Incronをインストールする必要があります。

_ Sudo apt-get install incron
_

そして、スクリプトは次のようになります。

_#!/bin/bash
eval $1
_

(指定されたディレクトリを監視するのはcronの仕事になるため、フォルダを指定する必要はありません)

完全で実用的な例はここにあります:

http://www.errr-online.com/index.php/2011/02/25/monitor-a-directory-or-file-for-changes-on-linux-using-inotify/ =

10
Swift

まだ誰も投稿していないとは信じられません。

最初に確認してくださいinotify-toolsがインストールされます。

次に、これらを次のように使用します。

logOfChanges="/tmp/changes.log.csv" # Set your file name here.

# Lock and load
inotifywait -mrcq $DIR > "$logOfChanges" &
IN_PID=$$

# Do your stuff here
...

# Kill and analyze
kill $IN_PID
cat "$logOfChanges" | while read entry; do
   # Split your CSV, but beware that file names may contain spaces too.
   # Just look up how to parse CSV with bash. :)
   path=... 
   event=...
   ...  # Other stuff like time stamps?
   # Depending on the event…
   case "$event" in
     SOME_EVENT) myHandlingCode path ;;
     ...
     *) myDefaultHandlingCode path ;;
done

または、--format の代わりに -c on inotifywaitはアイデアです。

ただman inotifywaitおよびman inotifywatch詳細については。

10
Evi1M4chine

おそらくそれを行う最速の方法..(1G gitリポジトリでは、1秒未満で戻ります。)

#!/bin/bash

watch() {

    echo watching folder $1/ every $2 secs.

while [[ true ]]
do
    files=`find $1 -type f -mtime -$2s`
    if [[ $files == "" ]] ; then
        echo "nothing changed"
    else
            echo changed, $files
    fi
    sleep $2
done
}

watch folder 3
5
Devrim

Mac OS Xでは、フォルダーをControlキーを押しながらクリックし、[フォルダーアクションのセットアップ]をクリックするだけです。これにより、アクションをフォルダーに添付できるようになります。つまり、実行するスクリプトです。

OS Xには多数のスクリプトがあらかじめ組み込まれていますが、独自のスクリプトを作成することもできます。

3
John Vargo

ほぼ3年後、このうなり声ベースのソリューションをお勧めします。

ここで実際の例を作成しました https://github.com/reggi/watch-execute

これがGruntfile.js

module.exports = function (grunt) {
  grunt.initConfig({
    Shell: {
      run_file:{
        command: 'sh ./bash.sh',
        options: {
            stdout: true
        }
      }
    },
    watch: {
      run_file: {
        files: ["./watchme/*"],
        tasks: ["Shell:run_file"]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-Shell');
};
1
ThomasReggi

watchfile と呼ばれるこれらの種類の操作を簡素化する一般的なユーティリティを作成しました。

inotifywatchよりも強力ではありませんが、よりシンプルで冗長なユーティリティを好みます。

目的のタスクについて、現在のディレクトリ内のファイルが変更されたかどうかを監視します。現在のディレクトリ内のすべてのファイルを再帰的にリストするには:

find . -type f

これらの各ファイルのタイムスタンプ情報を出力するには:

find . -type f -print0 | xargs -0 stat

これで、watchfileユーティリティを使用してこの出力を監視し、この情報が変更されたときにコマンドCMDを実行できます。

watchfile -s "find . -type f -print0 | xargs -0 stat" -e CMD
1
swalog
#!/bin/bash

# Author: Devonte
# NGINX WATCH DAEMON
# Place file in root of nginx folder /etc/nginx
# This will test your nginx config on any change and
# if there are no problems it will reload your configuration
# USAGE: sh nginx-watch.sh

dir=`dirname $0`

checksum_initial=`tar -cf - $dir | md5sum | awk '{print $1}'`
checksum_now=$checksum_initial

# Start nginx
nginx

while true
do
    sleep 3
    checksum_now=`tar -cf - $dir | md5sum | awk '{print $1}'`

    if [ $checksum_initial != $checksum_now ]; then
        echo "[ NGINX ] A configuration file changed. Reloading..."
        nginx -t && nginx -s reload;
    fi

    checksum_initial=$checksum_now
done
1
Devonte

AppleScriptを使用しない理由

http://www.tuaw.com/2009/03/26/applescript-exploring-the-power-of-folder-actions-part-iii/

on adding folder items to this_folder after receiving added_items
tell application "Finder"
...
0
Eric Fortis

使用するテンプレートは次のとおりです。渡されたディレクトリの変更を120秒ごとにチェックし、ディレクトリ、ファイル、または名前パイプの作成時に通知します。何かが削除されたときにコマンドも実行したい場合は、追加のループの例について stackoverflow の他の答えを確認してください。

#!/usr/bin/env bash
Var_dir="${1:-/tmp}"
Var_diff_sleep="${2:-120}"
Var_diff_opts="--suppress-common-lines"
Func_parse_diff(){
    _added="$(grep -E '>' <<<"${@}")"
    if [ "${#_added}" != "0" ]; then
        mapfile -t _added_list <<<"${_added//> /}"
        _let _index=0
        until [ "${#_added_list[@]}" = "${_index}" ]; do
            _path_to_check="${Var_dir}/${_added_list[${_index}]}"
            if [ -f "${_path_to_check}" ]; then
                echo "# File: ${_path_to_check}"
            Elif [ -d "${_path_to_check}" ]; then
                echo "# Directory: ${_path_to_check}"
            if [ -p "${_path_to_check}" ]; then
                echo "# Pipe: ${_path_to_check}"
            fi
            let _index++
        done
        unset _index
    fi
}
Func_watch_bulk_dir(){
    _current_listing=""
    while [ -d "${Var_dir}" ]; do
        _new_listing="$(ls "${Var_dir}")"
        _diff_listing="$(diff ${Var_dec_diff_opts} <(${Var_echo} "${_current_listing}") <(${Var_echo} "${_new_listing}"))"
        if [ "${_diff_listing}" != "0" ]; then
            Func_parse_diff "${_diff_listing}"
        fi
        _current_listing="${_new_listing}"
        sleep ${Var_diff_sleep}
    done
}

監視対象の各タイプのアクションについて、上記のecho行をeval <some command>に置き換える場合は、アクションの自動化により近くなります。また、スクリプト内で使用した場合に上記のように見えることを確認したい場合は、gpgおよびtarによる暗号化と復号化の自動化に取り組んでいるプロジェクトの最新の script version を確認してください。

0
S0AndS0

最上位で作成/削除されているファイルのみをチェックする必要がある場合(サブフォルダーはチェックしない)、次を使用できます。

少ないリソースを使用するため、迅速に対応できます。変更されたファイルを確認するために使用します。

#!/bin/bash

file="$1"
shift

tmp=$(mktemp)
trap 'rm "$tmp"' EXIT

while true; do
    while [ ! "$tmp" -ot "$file" ]; do
        sleep 0.5
    done
    eval "$@ &"
    echo $! > "$tmp"
    wait
done
0
exic