2010-08-27 20:02:40 +0000 2010-08-27 20:02:40 +0000
459
459
Advertisement

Как выполнить команду при каждом изменении файла?

Advertisement

Мне нужен быстрый и простой способ выполнить команду при каждом изменении файла. Я хочу что-то очень простое, что-то, что я оставлю запущенным на терминале и закрою его всякий раз, когда закончу работу с этим файлом.

В настоящее время я использую следующее:

while read; do ./myfile.py ; done

И затем мне нужно зайти на этот терминал и нажать Enter, всякий раз, когда я сохраняю этот файл в моем редакторе. Я хочу что-то вроде этого:

while sleep_until_file_has_changed myfile.py ; do ./myfile.py ; done

Или любое другое решение, такое же простое.

BTW: Я использую Vim, и я знаю, что могу добавить авто-команду, чтобы запустить что-то на BufWrite, но это не то решение, которое я хочу сейчас.

Обновление: Я хочу что-то простое, отбрасываемое, если это возможно. Более того, я хочу, чтобы что-то запускалось в терминале, потому что я хочу видеть вывод программы (я хочу видеть сообщения об ошибках).

Ответы: Спасибо за все ваши ответы! Все они очень хороши, и каждый из них отличается от других. Так как мне нужно принять только один, я принимаю тот, который я на самом деле использовал (он был простым, быстрым и легким для запоминания), хотя я знаю, что он не самый элегантный.

Advertisement

Ответы (37)

434
434
434
2010-08-27 20:54:55 +0000

Просто, используя inotifywait (установите пакет inotify-tools вашего дистрибутива):

или

Первый фрагмент проще, но у него есть существенный недостаток: он пропустит изменения, сделанные в то время, когда inotifywait не запущена (в частности, в то время, когда myfile запущена). Второй фрагмент не имеет этого недостатка. Однако, остерегайтесь, что он предполагает, что имя файла не содержит пробелов. Если это проблема, используйте опцию --format, чтобы изменить вывод, чтобы не включать имя файла:

while inotifywait -e close_write myfile.py; do ./myfile.py; done

В любом случае, есть ограничение: если какая-то программа заменит myfile.py другим файлом, вместо того, чтобы записывать на существующий myfile, inotifywait умрет. Многие редакторы работают таким образом.

Чтобы преодолеть это ограничение, используйте inotifywait в каталоге:

inotifywait -q -m -e close_write myfile.py |
while read -r filename event; do
  ./myfile.py # or "./$filename"
done

Альтернативно, используйте другой инструмент, который использует ту же самую базовую функциональность, например incron (позволяет регистрировать события при изменении файла) или fswatch (инструмент, который также работает на многих других Unix-вариантах, используя аналог уведомления каждого варианта в Linux).

179
179
179
2013-10-25 09:41:16 +0000

вход http://entrproject.org/ ) обеспечивает более дружественный интерфейс для оповещения (а также поддерживает *BSD и Mac OS X).

Это позволяет очень легко указать несколько файлов для просмотра (ограничивается только ulimit -n), избавляет от хлопот с файлами, которые заменяются, и требует меньшего баша синтаксиса:

$ find . -name '*.py' | entr ./myfile.py

Я использовал его на всем дереве исходных текстов моего проекта, чтобы запустить юнит-тесты для кода, который я в настоящее время модифицирую, и это было огромным толчком к моему рабочему процессу уже.

Флаги типа -c (очистить экран между запусками) и -d (выйти, когда новый файл добавляется в отслеживаемый каталог) добавляют ещё больше гибкости, например, вы можете сделать:

$ while sleep 1 ; do find . -name '*.py' | entr -d ./myfile.py ; done

С начала 2018 года он всё ещё находится в активной разработке и его можно найти в Debian & Ubuntu (apt install entr); сборка из авторского репо была безболезненной в любом случае.

112
Advertisement
112
112
2011-06-30 13:34:28 +0000

Я написал программу на Python, чтобы сделать именно это, называется когда изменился .

Использование просто:

when-changed FILE COMMAND...

Или для просмотра нескольких файлов:

when-changed FILE [FILE ...] -c COMMAND

FILE может быть каталог. Смотреть рекурсивно с -r. Используйте %f для передачи имени файла команде.

53
53
53
2013-08-20 17:12:47 +0000

Как насчет этого сценария? Он использует команду stat для получения времени доступа к файлу и запускает команду всякий раз, когда происходит изменение времени доступа (всякий раз, когда доступ к файлу осуществляется).

#!/bin/bash

### Set initial time of file
LTIME=`stat -c %Z /path/to/the/file.txt`

while true    
do
   ATIME=`stat -c %Z /path/to/the/file.txt`

   if [["$ATIME" != "$LTIME"]]
   then    
       echo "RUN COMMAND"
       LTIME=$ATIME
   fi
   sleep 5
done
30
Advertisement
30
30
2010-08-27 20:12:25 +0000

Решение с использованием Vim:

:au BufWritePost myfile.py :silent !./myfile.py

Но мне не нужно это решение, потому что оно немного раздражает, немного трудно вспомнить, что именно нужно набирать, и немного трудно отменить его эффекты (нужно запустить :au! BufWritePost myfile.py). Кроме того, это решение блокирует Vim до тех пор, пока команда не завершит выполнение.

Я добавил это решение сюда просто для полноты, так как оно может помочь другим людям.

Чтобы отобразить вывод программы (и полностью прервать ваш поток редактирования, так как вывод будет писать над вашим редактором в течение нескольких секунд, пока вы не нажмете Enter), удалите команду :silent.

23
23
23
2012-06-09 23:51:16 +0000

Если у вас случайно установлена npm , то nodemon , наверное, самый простой способ начать работу, особенно в OS X, которая, очевидно, не имеет инструментов оповещения. Она поддерживает выполнение команды при изменении папки.

21
Advertisement
21
21
2016-03-22 14:57:03 +0000

Для тех, кто не может установить inotify-tools, как я, это должно быть полезно:

watch -d -t -g ls -lR

Эта команда выйдет при изменении результатов, ls -lR перечислит каждый файл и каталог с его размером и датами, так что если файл изменен, он должен выйти из команды, как говорит человек:

-g, --chgexit
          Exit when the output of command changes.

Я знаю, что этот ответ может быть не прочитан кем-либо, но я надеюсь, что кто-нибудь дотянется до него.

Пример командной строки:

~ $ cd /tmp
~ $ watch -d -t -g ls -lR && echo "1,2,3"

Открыть другой терминал:

Теперь первый терминал будет выводить 1,2,3

Пример простого скрипта:

&00001

17
17
17
2015-09-09 21:49:14 +0000

rerun2 на github ) - это 10-строчный Bash скрипт формы:

#!/usr/bin/env bash

function execute() {
    clear
    echo "$@"
    eval "$@"
}

execute "$@"

inotifywait --quiet --recursive --monitor --event modify --format "%w%f" . \
| while read change; do
    execute "$@"
done

Сохраните версию github как ‘rerun’ on your PATH, и вызывайте ее, используя:

rerun COMMAND

Она запускается КОМАНДА каждый раз, когда в вашей текущей директории возникает событие изменения файловой системы (рекурсивное. )

Вещи, которые могут понравиться:

  • Он использует inotify, так что он более отзывчивый, чем опрос. Прекрасно подходит для выполнения субмиллисекундных юнит-тестов или рендеринга графических файлов с точками каждый раз, когда вы нажимаете ‘save’.
  • Так как это так быстро, вам не нужно говорить ему игнорировать большие субдиректории (например, node_modules) только из соображений производительности.
  • Это сверхчувствительный, потому что он звонит инотифицировать ждать только один раз, при запуске, вместо того, чтобы запускать его, и это приводит к дорогостоящему хиту установки часов, на каждой итерации.
  • Это всего лишь 12 строк Bash
  • Потому что это Bash, он интерпретирует команды, которые вы передаете его точно так же, как если бы вы напечатали их в Bash prompt. (Предположительно, это менее круто, если вы используете другую оболочку.)
  • Она не теряет события, которые происходят во время выполнения COMMAND, в отличие от большинства других решений по уведомлению на этой странице.
  • При первом событии она вводит “мертвый период” на 0.15 секунды, во время которого другие события игнорируются, перед тем как COMMAND будет запущен ровно один раз. Это сделано для того, чтобы шквал событий, вызванных танцем креатив-письменный танец, который делает Vi или Emacs при сохранении буфера, не вызвал многократных трудоемких запусков возможно медленно работающего тестового набора. Любые события, которые затем происходят во время выполнения COMMAND, не игнорируются - они вызовут второй мертвый период и последующее выполнение.

  • Он использует inotify, поэтому не будет работать за пределами Linuxland.

  • Из-за того, что он использует inotify, его будет тошнить при попытке посмотреть каталоги, содержащие больше файлов, чем максимальное количество пользовательских часов inotify. По умолчанию, кажется, что на разных машинах, которые я использую, установлено около 5,000 - 8,000, но их легко увеличить. Смотрите https://unix.stackexchange.com/questions/13751/kernel-inotify-watch-limit-reached

  • Он не выполняет команды, содержащие псевдонимы Bash. Я могу поклясться, что это работало. В принципе, поскольку это Bash, а не выполняющий COMMAND в подоболочке, я бы ожидал, что это сработает. Я бы с удовольствием послушал, если бы кто-нибудь знал, почему это не работает. Многие другие решения на этой странице также не могут выполнять такие команды.

  • Лично мне бы хотелось иметь возможность нажать на ключ в терминале, в котором он запущен, чтобы вручную вызвать дополнительное выполнение COMMAND. Могу ли я как-то просто это добавить? Одновременный запуск цикла ‘while read -n1’, который также вызывает execute?

  • На данный момент я закодировал его, чтобы очистить терминал и распечатывать выполняемый COMMAND на каждой итерации. Некоторые люди, возможно, захотят добавить флаги командной строки, чтобы выключить такие вещи, и т.п. Но это многократно увеличило бы размер и сложность.

  • Это уточнение ответа @cychoi.

12
Advertisement
12
12
2010-08-27 21:23:29 +0000

Вот простой скрипт оболочки Борна, который:

  1. Принимает два аргумента: файл для мониторинга и команду (с аргументами, если необходимо)
  2. Скопирует отслеживаемый файл в каталог /tmp
  3. Проверяет каждые две секунды, не является ли отслеживаемый файл более новым, чем копия
  4. Если он более новый, он перезаписывает копию более новым оригиналом и выполняет команду
  5. Очищает после себя, когда вы нажимаете Ctr-C

Это работает во FreeBSD. Единственная проблема переносимости, о которой я могу думать, это если в каком-нибудь другом Unix нет команды mktemp(1), но в этом случае вы можете просто жестко закодировать имя временного файла.

8
8
8
2014-08-08 22:20:09 +0000

если у вас установлен nodemon , то вы можете это сделать:

nodemon -w <watch directory> -x "<shell command>" -e ".html"

В моем случае я редактирую html локально и отправляю его на мой удаленный сервер, когда файл изменяется.

nodemon -w <watch directory> -x "scp filename jaym@jay-remote.com:/var/www" -e ".html"
8
Advertisement
8
8
2010-08-27 20:12:59 +0000

Посмотрите на incron . Он похож на Крона, но использует инотификацию событий вместо времени.

6
6
6
2014-07-09 13:16:10 +0000

Посмотрите в Guard, в частности, с этим плагином: https://github.com/hawx/guard-shell

Вы можете настроить его так, чтобы он смотрел на любое количество шаблонов в каталоге вашего проекта, и выполнять команды, когда происходят изменения. Хорошая вероятность даже того, что есть плагин, доступный для того, что вы пытаетесь сделать в первую очередь.

6
Advertisement
6
6
2014-01-22 14:55:46 +0000

Другое решение с NodeJs, * (https://npmjs.org/package/fsmonitor)** :

  1. Инсталлируйте

  2. Из командной строки (например, журналы мониторинга и “розничная торговля” при изменении одного лог-файла).

5
5
5
2015-12-28 10:44:18 +0000
  • Watchdog ** - это проект Python, и может быть именно то, что вы ищете:

Поддерживаемые платформы

  • Linux 2. 6 (inotify)
  • Mac OS X (FSEvents, kqueue)
  • FreeBSD/BSD (kqueue)
  • Windows (ReadDirectoryChangesW с портами ввода/вывода; ReadDirectoryChangesW working threads)
  • OS-независимая (опрос диска на предмет снимков каталогов и их периодическое сравнение; медленная и не рекомендуется)

Просто записала обертку командной строки * watchdog_exec **:

Пример запуска

При событии fs, затрагивающем файлы и папки в текущем каталоге, выполните команду echo $src $dst, если только событие fs не было изменено, затем выполните команду python $src.

python -m watchdog_exec . --execute echo --modified python

Использование коротких аргументов и ограничение на выполнение только тогда, когда события включают “ main.py”:

python -m watchdog_exec . -e echo -a echo -s __main__.py
  • *

EDIT: Только что найден Watchdog имеет официальный CLI с именем watchmedo, так что проверьте, что и это тоже.

5
Advertisement
5
5
2012-07-02 16:36:51 +0000

Под Linux:

man watch

watch -n 2 your_command_to_run

Будет запускать команду каждые 2 секунды.

Если ваша команда занимает более 2 секунд, смотреть будет ждать, пока она будет сделана, прежде чем делать это снова.

4
4
4
2010-08-27 20:37:52 +0000

Если ваша программа генерирует какой-то лог/выход, вы можете создать Makefile с правилом для этого лога/выхода, которое зависит от вашего скрипта, и сделать что-то вроде

while true; do make -s my_target; sleep 1; done

Альтернативно, вы можете создать фальшивую мишень и иметь правило для нее, как вызывать ваш скрипт, так и касаться фальшивой мишени (в то же время, в зависимости от вашего скрипта).

4
Advertisement
4
4
2014-09-15 23:24:58 +0000
4
4
4
2015-06-17 18:03:51 +0000

Улучшен ответ Жиля ](https://superuser.com/revisions/181543/3).

Эта версия запускается inotifywait один раз и отслеживает события ( например: modify) после этого. Так что inotifywait does не нужно переисполнять при каждом встреченном событии.

Это быстро и быстро!(даже при рекурсивном мониторинге большого каталога)

inotifywait --quiet --monitor --event modify FILE | while read; do
    # trim the trailing space from inotifywait output
    REPLY=${REPLY% }
    filename=${REPLY%% *}
    # do whatever you want with the $filename
done
```.
3
Advertisement
3
3
2010-08-27 20:05:59 +0000

Немного больше на стороне программирования, но вы хотите что-то вроде inotify . Есть реализации на многих языках, такие как jnotify и pyinotify .

Эта библиотека позволяет отслеживать отдельные файлы или целые каталоги, и возвращает события при обнаружении действия. Возвращаемая информация включает в себя имя файла, действие (создать, изменить, переименовать, удалить) и путь к файлу, а также другую полезную информацию.

3
3
3
2012-11-11 21:48:31 +0000

Для тех из вас, кто ищет решение FreeBSD, вот порт:

/usr/ports/sysutils/wait_on
```.
3
Advertisement
3
3
2014-04-29 13:56:13 +0000

Мне нравится простота while inotifywait ...; do ...; done, но у него есть две проблемы:

  • Изменения файла, происходящие во время do ...; будет be missed
  • Slow при использовании в рекурсивном режиме

Therefor я сделал скрипт-помощник, который использует inotifywait без этих ограничений: inotifyexec

Я предлагаю поместить этот скрипт в ваш путь, как в ~/bin/. Использование описывается простым выполнением команды.

Пример: inotifyexec "echo test" -r .

3
3
3
2016-04-12 14:53:44 +0000

Улучшено решение Sebastian’s solution с командой watch:

watch_cmd.sh:

#!/bin/bash
WATCH_COMMAND=${1}
COMMAND=${2}

while true; do
  watch -d -g "${WATCH_COMMAND}"
  ${COMMAND}
  sleep 1 # to allow break script by Ctrl+c
done

Пример вызова:

watch_cmd.sh "ls -lR /etc/nginx | grep .conf$" "sudo service nginx reload"

Это работает, но будьте осторожны: команда watch имеет известные ошибки (смотрите man): она реагирует на изменения только в VISIBLE в терминальных частях вывода -g CMD.

2
Advertisement
2
2
2017-03-01 20:14:14 +0000

Можно попробовать рефлекс .

Рефлекс - это небольшой инструмент для просмотра каталога и повторного запуска команды при изменении определенных файлов. Он отлично подходит для автоматического запуска задач компиляции/линтования/тестирования и для перезагрузки приложения при изменении кода.

# Rerun make whenever a .c file changes
reflex -r '\.c$' make
1
1
1
2017-04-05 07:38:43 +0000

Для этого у меня есть GIST, и его использование довольно простое

watchfiles <cmd> <paths...>

https://gist.github.com/thiagoh/5d8f53bfb64985b94e5bc8b3844dba55

1
Advertisement
1
1
2017-06-03 12:10:57 +0000

Как и некоторые другие, я также написал легковесный инструмент командной строки, чтобы сделать это. Он полностью документирован, протестирован и модулен.

Watch-Do

Установка

Вы можете установить его (если у вас есть Python3 и pip), используя:

pip3 install git+https://github.com/vimist/watch-do

Использование

Используйте его сразу же, запустив:

watch-do -w my_file -d 'echo %f changed'

Обзор возможностей

  • Поддерживает глобирование файлов (используйте -w '*.py' или -w '**/*.py')
  • Выполняет несколько команд при изменении файла (просто укажите флаг -d еще раз)
  • Динамически поддерживает список файлов, которые нужно смотреть, если глобирование используется (-r, чтобы включить это)
  • Несколько способов “смотреть” файл:
  • Время модификации (по умолчанию)
  • Хэш-файл
  • Тривиальный для реализации собственных (это ModificationTime watcher)
  • Модульный дизайн. Если вы хотите, чтобы команды выполнялись, при обращении к файлу, тривиально записать свой собственный просмотрщик (механизм, который определяет, должны ли выполняться исполнители).
1
1
1
2016-02-26 19:10:05 +0000

Я использую этот сценарий. Я использую inotify в режиме монитора

#!/bin/bash
MONDIR=$(dirname $1)
ARQ=$(basename $1)

inotifywait -mr -e close_write $MONDIR | while read base event file 
do
  if (echo $file |grep -i "$ARQ") ; then
    $1
  fi
done

Сохраните это как runatwrite.sh

Usage: runatwrite.sh myfile.sh

он будет запускать myfile.sh при каждой записи.

1
Advertisement
1
1
2015-09-09 19:36:04 +0000

Для этого я написал программу на Python, которая называется rerun .

UPDATE: Этот ответ представляет собой Python скрипт, который опрашивает на предмет изменений, что полезно при некоторых обстоятельствах. Для скрипта на Linux-only Bash, который использует inotify, смотрите другой мой ответ, найдите на этой странице ‘rerun2’.

Install for Python2 или Python3 с:

pip install --user rerun

и использование очень простое:

rerun "COMMAND"

Команда ожидается как единственный аргумент, а не как последовательность аргументов, разделенных пробелами. Поэтому процитируйте ее, как показано на рисунке, что уменьшает любое дополнительное экранирование, которое вам придется добавить. Просто напечатайте команду так, как вы напечатали бы в командной строке, но в окружении кавычек.

По умолчанию она просматривает все файлы в текущем каталоге или под ним, пропуская такие вещи, как известные исходники, .git, .svn, и т.д.

Дополнительные флаги включают ‘-i NAME’, который игнорирует изменения в именованных файлах или каталогах. Это может быть задано несколько раз.

Поскольку это скрипт на Python, он должен запустить команду как подпроцесс, и мы используем новый экземпляр текущей оболочки пользователя для интерпретации ‘COMMAND’ и принятия решения о том, какой процесс на самом деле должен быть запущен. Однако, если ваша команда содержит псевдонимы оболочки и т.п., которые определены в .bashrc, они не будут загружены подоболочкой. Чтобы исправить это, вы можете дать флаг ‘-I’ для повторного запуска, чтобы использовать интерактивные (так же известные как ‘вход в систему’) подоболочки. Это медленнее и более подвержено ошибкам, чем запуск обычной оболочки, потому что она должна исходить из вашего .bashrc.

я использую ее с Python 3, но в последний раз я проверял, что перезапуск все еще работает с Python 2.

Double-edged sword - это то, что он использует опрос вместо inotify. С другой стороны, это означает, что он работает на каждой операционной системе. К тому же, это лучше, чем некоторые другие решения, показанные здесь, с точки зрения того, что он запускает данную команду только один раз для множества изменений файловой системы, а не один раз для каждого измененного файла, в то же время он запускает команду второй раз, если какие-либо файлы изменяются снова во время выполнения команды.

С другой стороны, опрос означает, что существует задержка от 0.0 до 1.0 секунды, и, конечно же, он медленно отслеживает очень большие каталоги. Сказав это, я никогда не встречал проекта достаточно большого, чтобы это было заметно до тех пор, пока вы используете ‘-i’, чтобы игнорировать такие большие вещи, как ваш virtualenv и node_modules.

Хммм. rerun была незаменима для меня в течение многих лет - в основном я использую ее по восемь часов каждый день для запуска тестов, восстановления точечных файлов во время их редактирования и т.д. Но теперь я пришел, чтобы напечатать это здесь, ясно, что мне нужно переключиться на решение, которое использует inotify (я больше не использую Windows и OSX.) и написано на Bash (так что оно работает с псевдонимами без лишних скрипок).

1
1
1
2015-09-01 04:53:52 +0000

Ответ oneliner, который я использую для отслеживания изменения файла:

$ while true ; do NX=`stat -c %Z file` ; [[$BF != $NX]] && date >> ~/tmp/fchg && BF=$NX || sleep 2 ; done

Вам не нужно инициализировать BF, если вы знаете, что первая дата - это время начала.

Это просто и портативно. Есть еще один ответ, основанный на той же стратегии с помощью скрипта здесь. Посмотрите также.

  • *

Использование: Я использую это, чтобы отладить и следить за ~/.kde/share/config/plasma-desktop-appletsrc, что по каким-то неизвестным причинам продолжает терять мою SwitchTabsOnHover=false.

1
Advertisement
1
1
2016-03-22 15:33:56 +0000

Для тех, кто использует OS X, вы можете использовать LaunchAgent для просмотра пути/файла на предмет изменений и сделать что-нибудь, когда это произойдет. FYI - LaunchControl - хорошее приложение для легкого создания/изменения/удаления демонов/агентов.

пример взят отсюда )

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>test</string>
    <key>ProgramArguments</key>
    <array>
        <string>say</string>
        <string>yy</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>~/Desktop/</string>
    </array>
</dict>
</plist>
0
0
0
2019-11-26 15:53:22 +0000

Если вы не хотите устанавливать что-то новое для этого, вот небольшой shell-скрипт, который вы можете вставить в свой путь (например, под $HOME/bin). Он запускает команду при изменении одного или нескольких предоставленных файлов. Например:

$ onchange './build' *.txt

Он tars, а затем хэширует содержимое файлов и/или каталогов, так что он не будет запускаться каждый раз, когда вы навязчиво нажимаете CTRL-S (или набираете :w), а только один раз, когда что-то действительно меняется. Обратите внимание, что он будет проверять каждую секунду, так что не включайте много, иначе ваша машина может работать медленно. Если вы хотите, чтобы она запускалась при каждом сохранении, используйте stat вместо него (см. комментарий). Также, для mac md5sum называется md5, если я правильно помню.

Хитрый маленький трюк: В тот момент, когда вы захотите использовать его, вы, вероятно, захотите повторить последнюю только что выполненную команду, но снова и снова. Вы можете использовать ярлык !!, чтобы ‘вставить’ последнюю команду:

#!/bin/sh
cmd="$1"; shift
files="$@"
changed() { tar -c $files | md5sum; } # for on every save use: `stat -c %Z $files`
while true; do
  if ["$(changed)" != "$last"]; then
    last="$(changed)"
    $cmd
  fi
  sleep 1
done
```.
0
Advertisement
0
0
2018-04-12 18:32:28 +0000

Описание

Посмотрит файл на изменения и выполнит любую команду (включая дальнейшие аргументы) данную как второе утверждение. Он также очистит экран и распечатает время последнего выполнения. Примечание: вы можете сделать функцию более (или менее) реактивной, изменяя количество секунд, которое функция должна спать после каждого цикла цикла.

Пример использования

watch_file my_file.php php my_file.php

Эта строка будет смотреть php файл my_file.php и запускать через php интерпретатор всякий раз, когда он меняется.

Описание функции

function watch_file (){

### Set initial time of file
LTIME=`stat -c %Z $1`
printf "&00133c"
echo -e "watching: $1 ---- $(date '+%Y-%m-%d %H:%M:%S')\n-------------------------------------------\n"
${@:2}

while true
do
   ATIME=`stat -c %Z $1`

   if [["$ATIME" != "$LTIME"]]
   then
    printf "&00133c"
    echo -e "watching: $1 ---- $(date '+%Y-%m-%d %H:%M:%S')\n-------------------------------------------\n"
    ${@:2}
    LTIME=$ATIME
   fi
   sleep 1
done
}

Кредит

Это, в основном, более общая версия ответа VDR.

0
0
0
2018-03-19 20:30:21 +0000
0
Advertisement
0
0
2019-01-28 16:51:42 +0000

find может сделать трюк.

while true; do
    find /path/to/watched/file -ctime 1s | xargs do-what-you-will
done

find -ctime 1s печатает имя файла, если оно было изменено в последней 1s.

0
0
0
2015-05-13 15:21:33 +0000

Для людей, которые находят это в Googling для изменений в particular файле, ответ гораздо проще (вдохновленный Gilles’s answer ).

Если вы хотите сделать что-то after определенный файл был записан, вот как:

while true; do
  inotifywait -e modify /path/to/file
  # Do something *after* a write occurs, e.g. copy the file
  /bin/cp /path/to/file /new/path
done

Сохраните это как, например, copy_myfile.sh и поместите файл .sh в папку /etc/init.d/, чтобы он запустился при старте.

0
Advertisement
0
0
2019-03-21 11:33:37 +0000

У меня была немного другая ситуация. Но я чувствую, что это может быть полезно для кого-то, кто читает этот вопрос.

Мне нужно было получать уведомления о том, что лог файл изменил размер, но в этом не было необходимости сразу же. И это могут быть дни или недели в будущем, поэтому я не мог использовать inotify (которая все равно не была установлена/активирована на этом сервере) в командной строке (я не хотел использовать nohup или что-то подобное). Поэтому я решил запустить скрипт bash на cron для проверки

Скрипт записывает размер просматриваемого файла в текстовый файл и на каждой cron запускает и проверяет, изменилось ли это значение, и отправляет мне последнюю строку, если изменилось

#!/bin/bash
FILE_TO_WATCH="/path/to/log_file.log"
FILESIZE_FILE="/path_to/record.txt"
SUBJECT="Log file 'log_file.log' has changed"
MAILTO="info@example.com"
BODY="Last line of log file:\n"
LAST_LINES=1

# get old recorded file size from file
OLD_FILESIZE=$(cat "${FILESIZE_FILE}")
# write current file size into file
stat --printf="%s" "${FILE_TO_WATCH}" > "${FILESIZE_FILE}"
# get new recorded file size from file
NEW_FILESIZE=$(cat "${FILESIZE_FILE}")

if ["${OLD_FILESIZE}" != "${NEW_FILESIZE}"]; then
    echo -e "${BODY}"$(tail -${LAST_LINES} ${FILE_TO_WATCH}) | mail -s "${SUBJECT}" "${MAILTO}"
fi
```.
0
0
0
2019-11-23 23:41:53 +0000

Проверьте https://github.com/watchexec/watchexec .

watchexec является простым, автономным инструментом, который следит за пути и запускает команду всякий раз, когда он обнаруживает изменения.

Example

Следите за всеми JavaScript, CSS и HTML файлами в текущем каталоге и во всех подкаталогах за изменениями, запуская make при обнаружении изменений:

$ watchexec --exts js,css,html make

0
Advertisement
0
0
2017-03-20 13:52:53 +0000

Инструмент ‘fido’ может быть еще одним вариантом для этой необходимости. Смотрите https://www.joedog.org/fido-home/ .

Похожие вопросы

6
10
11
8
5
Advertisement