OS X 및 Ubuntu에서 실시간으로 파일 시스템 감시

OS X 및 Ubuntu에서 실시간으로 파일 시스템 감시

디렉터리를 감시하고 실시간으로 변경되는 파일 이름을 뱉어내는 CLI 도구를 찾고 있습니다.

some_watch_command /path/to/some/folder | xargs some_callback

나는 inotify( inotify-tools?) 것을 알고 있고 그것이 나에게 필요한 것 같지만 Linux(내 경우에는 Ubuntu)와 OSX 호환이 모두 필요한 것이 필요합니다.

매우 빠를 필요는 없지만 변경 시 트리거되어야 합니다(1초 이내가 합리적임). 또한 위에서 언급한 정확한 CLI 프로그램이 반드시 필요한 것은 아닙니다. 기본 기술이 존재하고 두 플랫폼 모두에서 쉽게 스크립팅할 수 있다면 그것도 좋을 것입니다.

답변1

OS X는 일반적으로폴더 작업또는출시됨이 작업을 위해.

내가 아는 유일한 크로스 플랫폼 도구는감시 APIPython용(따라서 OS X 및 Linux에서 사용 가능). pip(또는 easy_install) 을 통해 설치하세요 .

pip install watchdog

watchmedo시스템 이벤트에 대해 쉘 명령을 실행할 수 있는 명령줄 도구 가 함께 제공됩니다 . 다음을 사용하여 일반 구문을 확인하세요.watchmedo --help

다음은 명령과 굵게 강조 표시된 경로를 쉽게 수정할 수 있는 간단한 예입니다.

watchmedo 쉘 명령 \
    --재귀적 \
    --명령='echo "${watch_src_path}"' \
    /일부/폴더

이렇게 하면 변경된 모든 파일이나 폴더에 대한 경로가 간단히 표시되므로 watchmedo의 출력을 다른 셸 명령으로 파이프할 수 있습니다.

답변2

나는 여러분이 찾고 있는 것을 정확히 수행하기 위해 제가 본 일부 Ruby 스크립트를 수정했습니다. Ruby 코드는 다음과 같습니다.

#!/usr/bin/ruby
# Inspired by http://vikhyat.net/code/snippets/#watchfile

# How to use:
# This script takes two paramaters:  a folder and a shell command
# The script watches for when files in the folder are changed.  When they are, the shell command executes
# Here are some shortcuts you can put in the shell script:
# %F = filename (with extension)
# %B = base filename (without extension)


unless ARGV.length == 2
  puts "\e[32m    Usage: \e[0mruby OnSaveFolder.rb 'folder' 'command'"
  exit
end

require 'digest/md5'
require 'ftools'

$md5 = ''
$directory = File.expand_path(ARGV[0])
$contents = `ls #{$directory}`
$contentsList = $contents.split("\n")
$fileList = []


Dir.chdir($directory)

for i in $contentsList
  if ( File.file?(File.expand_path(i)) == true)
    $fileList.push(i)
  end
end

$processes = []

def watch(file, timeout, &cb)
  $md5 = Digest::MD5.hexdigest(File.read(file))
  loop do
    sleep timeout
    if ( temp = Digest::MD5.hexdigest(File.read(file)) ) != $md5
      $md5 = temp
      cb.call(file)
    end
  end
end

puts "\e[31m Watching files in folder \e[34m #{$directory}"
puts "\e[32m    Press Control+C to stop \e[0m"

for i in $fileList
  pid = fork do
    $num = 0
    $filePath = File.expand_path(i)

    watch i, 1 do |file|
      puts "\n     #{i} saved"

      $command = ARGV[1].dup
      if ( ARGV[1].include?('%F') )
        $command = $command.gsub!('%F', i)
      end
      if ( ARGV[1].include?('%B') )
        $command = $command.gsub!('%B', File.basename(i, '.*'))
      end

      $output = `#{$command}`
      if ( $output != '')
        puts "\e[34m     #{$command}\e[31m output: \e[0m"
        puts $output
      end
      puts "\e[34m     #{$command}\e[31m finished \e[0m (#{$num}, #{Time.now})\n"
      $num += 1

    end
  end
  $processes.push(pid)
end

Process.wait(pid)

for i in $processes
  `kill #{i}`
end

이 스크립트의 이름을 "OnSaveFolder.rb"로 지정했습니다. 변경 사항을 감시하려는 폴더와 변경 사항이 있을 때 실행하려는 bash 코드라는 두 가지 매개 변수가 필요합니다. 예를 들어,

ruby OnSaveFolder.rb '/home/Movies' 'echo "A movie has been changed!"'

이게 도움이 되길 바란다! 나는 Ruby가 이러한 유형의 작업에 매우 적합하다는 것을 알았으며 OS X에는 기본적으로 설치되어 있습니다.

답변3

lsof명령 을 입력 watch하고 매초마다 업데이트되도록 할 수 있습니다 <s>.

watch -n <s> lsof

pid1, pid2, pid3을 관찰하고 pid4를 무시하는 등 어떤 필터로든 실행합니다.

lsof -p "pid1,pid2,pid3,^pid4"

충분하지 않다면 언제든지 grep을 사용하여 자신만의 필터를 작성할 수 있습니다.

OS X의 경우 다음을 참조하세요.질문님의 답변입니다.

답변4

입장좋다. 이렇게 보고 싶은 정확한 파일을 필터링할 수 있습니다.

find . -name '*.py' | entr python runTests.py

디렉터리 내의 특정 파일만 모니터링하도록 하려면 find보고 싶은 파일만 반환하도록 명령을 작성할 수 있습니다.

에 비해 구성하기가 더 쉽다고 생각합니다 fswatch.

관련 정보