Запустите команду оболочки, когда файл добавлен

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

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

Ответ 1

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

Если протокол FTP, и у вас есть доступ к журналу FTP-сервера, я предлагаю настроить этот журнал для просмотра успешных загрузок. Такой подход, основанный на событиях, будет быстрее, надежнее и меньше нагрузки, чем опрос с традиционным cron, и более переносимым и более легким для отладки, чем с использованием inotify.

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

Fri May 25 07:36:02 2012 [pid 94378] [joe] OK LOGIN: Client "10.8.7.16"
Fri May 25 07:36:12 2012 [pid 94380] [joe] OK UPLOAD: Client "10.8.7.16", "/path/to/file.zip", 8395136 bytes, 845.75Kbyte/sec
Fri May 25 07:36:12 2012 [pid 94380] [joe] OK CHMOD: Client "10.8.7.16", "/path/to/file.zip 644"

Строка UPLOAD добавляется только тогда, когда vsftpd успешно сохранил файл. Вы можете разобрать это в оболочке script следующим образом:

#!/bin/sh

tail -F /var/log/vsftpd.log | while read line; do
  if echo "$line" | grep -q 'OK UPLOAD:'; then
    filename=$(echo "$line" | cut -d, -f2)
    if [ -s "$filename" ]; then
      # do something with $filename
    fi
  fi
done

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

Ответ 2

Как пояснил Джон, API-интерфейс inotify является отправной точкой, однако вам могут быть интересны некоторые инструменты, которые используют этот API для выполнения задач уведомления о файлах:

Например incron, который может использоваться для запуска cron-подобных задач при обнаружении изменений файла или каталога.

Или inotify-tools, который представляет собой набор инструментов командной строки, которые можно использовать для создания собственных оболочки уведомлений файла script.

Если вы посмотрите внизу патча Wiki для инструментов inotify, вы увидите ссылки на еще больше инструментов и поддержку языков более высокого уровня, таких как Python, Perl или Ruby (пример кода).

Ответ 3

Возможно, вы захотите посмотреть inotify

API-интерфейс inotify предоставляет механизм для мониторинга событий файловой системы. Inotify может использоваться для мониторинга отдельных файлов или для контроля каталогов. Когда каталог контролируется, inotify будет возвращать события для самого каталога и для файлов внутри каталога.

Ответ 4

Использование работы ghotis

Вот что я сделал, чтобы получить свободное пространство для пользователей:

#!/bin/bash

tail -F -n 1 /var/log/vsftpd.log | while read line; do
  if echo "$line" | grep -q 'OK LOGIN:'; then
    pid=$(sed 's/.*\[\([^]]*\)\].*/\1/g' <<< "$line")
    #the operator '<<<' doesnt exist in dash so use bash
    if [[ $pid != *"pid"* ]]; then
      echo -e "Disk 1: Contains Games:\n" > /home/vftp/"$pid"/FreeSpace.txt; df -h /media/Disk1/ >> /home/vftp/"$pid"/FreeSpace.txt
      echo -e "\r\n\r\nIn order to read this properly you need to use a text editor that can read *nix format files" >> /home/vftp/"$pid"/FreeSpace.txt
    fi
echo "checked"
#  awk '{ sub("\r$", ""); print }' /home/vftp/"$pid"/FreeSpace.txt > /home/vftp/"$pid"/FreeSpace.txt
  fi
done

Ответ 5

Если файл добавлен через HTTP-загрузку, и если ваш сервер является apache, вы можете проверить mod_security.

Он позволяет запускать script для каждой загрузки, сделанной через HTTP POST.

Ответ 6

#!/bin/bash

tail -F -n0 /var/log/vsftpd.log | while read line; do
  if echo "$line" | grep -q 'OK UPLOAD:'; then
    filename=$(echo $line | cut -d, -f2 |awk '{print $1}')
    filename="${filename%\"}"
    filename="${filename#\"}"
    #sleep 1s
    if [ -s $filename ]; then
      # do something with $filename
      echo $filename
    fi
  fi
done