Короткий ответ: вам нужно выполнить обратный вызов следующим образом:
function callback(response) {
// Here you can do what ever you want with the response object.
console.log(response);
}
$.ajax({
url: "...",
success: callback
});
Вот еще один вариант.
Мне просто нужно было написать свой собственный, чтобы смотреть и запускать тесты в контейнере Docker. Решение Jan намного более изящно, но FileSystemWatcher в настоящее время разбит на контейнеры Docker. Мой подход похож на Василия, но гораздо более ленивый, доверяя времени записи файловой системы.
Вот функция, которая мне нужна, которая запускает командный блок каждый раз, когда файл изменяется.
function watch($command, $file) {
$this_time = (get-item $file).LastWriteTime
$last_time = $this_time
while($true) {
if ($last_time -ne $this_time) {
$last_time = $this_time
invoke-command $command
}
sleep 1
$this_time = (get-item $file).LastWriteTime
}
}
Вот один, который ждет, пока файл не изменится, запустит блок, а затем выйдет.
function waitfor($command, $file) {
$this_time = (get-item $file).LastWriteTime
$last_time = $this_time
while($last_time -eq $this_time) {
sleep 1
$this_time = (get-item $file).LastWriteTime
}
invoke-command $command
}
Вы можете использовать System.IO.FileSystemWatcher
для контроля файла.
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
См. также в этой статье
Вот решение, на котором я закончил, основываясь на нескольких предыдущих ответах здесь. Я специально хотел:
Сторона примечания: я оставил в деталях то, что я хотел запустить из-за иронии использования глобальной переменной для связи между потоками, чтобы я мог скомпилировать код Erlang.
Function RunMyStuff {
# this is the bit we want to happen when the file changes
Clear-Host # remove previous console output
& 'C:\Program Files\erl7.3\bin\erlc.exe' 'program.erl' # compile some erlang
erl -noshell -s program start -s init stop # run the compiled erlang program:start()
}
Function Watch {
$global:FileChanged = $false # dirty... any better suggestions?
$folder = "M:\dev\Erlang"
$filter = "*.erl"
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
Register-ObjectEvent $Watcher "Changed" -Action {$global:FileChanged = $true} > $null
while ($true){
while ($global:FileChanged -eq $false){
# We need this to block the IO thread until there is something to run
# so the script doesn't finish. If we call the action directly from
# the event it won't be able to write to the console
Start-Sleep -Milliseconds 100
}
# a file has changed, run our stuff on the I/O thread so we can see the output
RunMyStuff
# reset and go again
$global:FileChanged = $false
}
}
RunMyStuff # run the action at the start so I can see the current output
Watch
Вы могли бы передать папку / фильтр / действие в часы, если хотите что-то более общее. Надеюсь, это полезная отправная точка для кого-то еще.
Я добавлю еще один ответ, потому что мой предыдущий пропустил требования.
Требования
Уже есть ответ с использованием хэшей файлов. Я хочу выполнить свой предыдущий ответ и показать, как это можно выполнить с помощью FileSystemWatcher.
$File = "C:\temp\log.txt"
$Action = 'Write-Output "The watched file was changed"'
$global:FileChanged = $false
function Wait-FileChange {
param(
[string]$File,
[string]$Action
)
$FilePath = Split-Path $File -Parent
$FileName = Split-Path $File -Leaf
$ScriptBlock = [scriptblock]::Create($Action)
$Watcher = New-Object IO.FileSystemWatcher $FilePath, $FileName -Property @{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
$onChange = Register-ObjectEvent $Watcher Changed -Action {$global:FileChanged = $true}
while ($global:FileChanged -eq $false){
Start-Sleep -Milliseconds 100
}
& $ScriptBlock
Unregister-Event -SubscriptionId $onChange.Id
}
Wait-FileChange -File $File -Action $Action
Вот пример, который я нашел в своих отрывках. Надеюсь, что это немного более полно.
Сначала вам нужно создать наблюдателя файловой системы, а затем вы подписаться на событие, которое генерирует наблюдатель. Этот пример прослушивает события «Создать», но может быть легко изменен, чтобы следить за «Изменить».
$folder = "C:\Users\LOCAL_~1\AppData\Local\Temp\3"
$filter = "*.LOG"
$Watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
IncludeSubdirectories = $false
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $Watcher Created -SourceIdentifier FileCreated -Action {
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file '$name' was $changeType at $timeStamp"
Write-Host $path
#Move-Item $path -Destination $destination -Force -Verbose
}
Я попытаюсь сузить это до ваших требований.
Если вы запустите это как часть своего скрипта «profile.ps1», вы должны прочитать «Сила профилей» , в которой объясняются различные доступные скрипты профилей и многое другое.
Кроме того, вы должны понимать, что ожидание изменения папки не может быть запущено как функция в скрипте. Сценарий профиля должен быть завершен, чтобы начать сеанс PowerShell. Однако вы можете использовать функцию для регистрации события.
Что это значит, это зарегистрировать фрагмент кода, который будет выполняться каждый раз при срабатывании события. Этот код будет выполнен в контексте текущего хоста PowerShell (или оболочки), пока сеанс остается открытым. Он может взаимодействовать с хостом, но не знает исходного скрипта, который зарегистрировал код. Возможно, исходный скрипт уже завершен, к моменту запуска вашего кода.
Вот код:
Function Register-Watcher {
param ($folder)
$filter = "*.*" #all files
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
$changeAction = [scriptblock]::Create('
# This is the code which will be executed every time a file change is detected
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file $name was $changeType at $timeStamp"
')
Register-ObjectEvent $Watcher "Changed" -Action $changeAction
}
Register-Watcher "c:\temp"
После запуска этого кода измените любой файл в поле «C : \ temp "(или любой другой каталог, который вы указали). Вы увидите событие, запускающее выполнение вашего кода.
Кроме того, действительные события FileSystemWatcher, которые вы можете зарегистрировать, - «Изменены», «Созданы», «Удалены» и «Переименованы».
function watch($f, $command, $interval) {
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$hashfunction = '[System.BitConverter]::ToString($sha1.ComputeHash([System.IO.File]::ReadAllBytes($file)))'
$files = @{}
foreach ($file in $f) {
$hash = iex $hashfunction
$files[$file.Name] = $hash
echo "$hash`t$($file.FullName)"
}
while ($true) {
sleep $interval
foreach ($file in $f) {
$hash = iex $hashfunction
if ($files[$file.Name] -ne $hash) {
iex $command
}
}
}
}
Пример использования:
$c = 'send-mailmessage -to "admin@whatever.com" -from "watch@whatever.com" -subject "$($file.Name) has been altered!"'
$f = ls C:\MyFolder\aFile.jpg
watch $f $c 60
У меня была аналогичная проблема. Сначала я хотел использовать события Windows и зарегистрироваться, но это было бы менее отказоустойчиво, как решение под ним. Моим решением был сценарий опроса (интервалы в 3 секунды). Скрипт имеет минимальный след в системе и очень быстро замечает изменения. Во время цикла мой скрипт может делать больше вещей (на самом деле я проверяю 3 разных папки).
Мой сценарий опроса запускается через диспетчер задач. Расписание запускается каждые 5 минут с остановкой флага, когда он уже работает. Таким образом, он перезапустится после перезагрузки или после сбоя. Использование диспетчера задач для опроса каждые 3 секунды является слишком частым для диспетчера задач. Когда вы добавляете задачу в планировщик, убедитесь, что вы не используете сетевые диски (которые вызывают дополнительные настройки) и предоставляют свои пользовательские пакетные привилегии.
Я даю сценарию чистый старт, отключив его за несколько минут до полуночи. Менеджер задач запускает скрипт каждое утро (функция init моего скрипта выйдет 1 минуту около полуночи).