Вопрос: Что касается команды Unix Move


Мне нужно написать Unix Shell Script tran.sh, который перемещает входные файлы csv из папки / exp / files в каталог / exp / ready.

Входные файлы csv записываются в /exp/files папку с FTP-сервером, поведение которого я не могу изменить тривиально. В tran.sh shell script Мне нужно убедиться, что перед перемещением этого входного файла csv из каталога / exp / files больше никакого другого процесса не записывается в файл.

Как мне это сделать.


4
2018-02-22 04:19


Источник


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


Ответы:


Не существует переносного способа сделать это. Можешь попробовать fuser, lsof, inotify, FAM, и другие.


3
2018-02-22 04:21



хороший ответ, режет прямо к делу. я думаю, вы можете добавить glib и gamin тоже - Matt Joiner


Попробуйте использовать fuser [FILE], Он будет возвращать ненулевое значение, если файл не используется.

Вот пример кода, который будет ждать, когда файл станет готовым к перемещению:

#!/bin/sh

FROMDIR='/exp/files'
DESTDIR='/exp/ready'

function move_file_if_ready () {
    if [ -f "$1" ]; then
        while fuser "$1" 2>/dev/null 1>&2 ; do
            sleep 1
        done

        mv "$1" "$DESTDIR"
    fi
}

for "$fn" in "$FROMDIR"/*.csv; do
    move_file_if_ready "$fn"
done

3
2018-02-22 04:22



Неплохо, но у него все еще есть состояние гонки. - dmckee
Большое спасибо. три процесса удаленного приложения - это ftp входной файл в этот каталог. Поэтому я могу узнать эту команду фьюзера, если они пишут в файл.
@dmckee - правда о состоянии гонки, но я предположил, что процесс записи на него только держит дескриптор файла открытым достаточно долго, чтобы писать на него, затем закрывает его, чтобы больше не открывать его. - amphetamachine
Большое спасибо. Я планирую проверить, получен ли последняя строка внутри файла csv и проверить файл


вы можете использовать lsof

r=$(lsof /exp/files )
if [ ! -z "$r" ] ;then
  mv /exp/files/*csv /exp/ready
fi

3
2018-02-22 04:31



Большое спасибо. три процесса удаленного приложения - это ftp входной файл в этот каталог. Поэтому я могу узнать эту команду lsof, если они пишут в файл.
Но с тремя (при условии, что независимые) процессы записываются в файлы каталога, то это не будет двигаться, если все три не закончены. Это более модульное использование фьюзера и тестирование по каждому файлу. - amphetamachine
Большое спасибо. Я планирую проверить, получен ли последняя строка внутри файла csv и проверить файл.


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

Некоторые конкретные примеры проблемных случаев:

  • Если процесс перемещения файлов выполняется как другой пользователь, чем lsof / fuser / etc, информация не гарантируется в полном объеме
  • Если процесс, выполняющий запись, является скриптом оболочки, он может порождать подпроцесс, который открывает файл, позволяет ему закрываться, порождать другой подпроцесс и т. Д. В этом сценарии lsof, фьюзер и подобные инструменты могут законно показывать файл как не доступный даже если дальнейший подпроцесс будет запущен для записи позже.

Другие, более тонкие условия гонки могут существовать также - и независимо, lsof, фьюзер и т. Д. Не являются инструментами POSIX и недоступны везде.

Требовать от протокола, чтобы процессы, записывающие файлы, переводили их в конечное местоположение по завершении; это единственный безопасный и портативный подход.

EDIT: выяснилось, что файлы записываются не произвольным процессом (который может закрывать и повторно открывать их), а FTP-сервером. В этом случае, incron может использоваться для запуска произвольного скрипта всякий раз, когда файл был закрыт в этом каталоге.


2
2018-02-22 04:43



Большое спасибо за информацию. Проблема состоит в том, что три процесса удаленного приложения - это ftp-файл в этом каталоге. Поэтому я не должен перемещать файл, когда пишу его в этом каталоге / exp / files
@arav - вы можете обойти это (то есть, я обходите это) с помощью настраиваемого сервера sftp. (Mine написан на Python, используя библиотеку Paramiko, а также ftpdlib для написания стандартных FTP-серверов на Python, хотя причин, чтобы избежать FTP, много).
@arav - ... сказал, что это звучит для меня как другое решение без гонки, которое будет работать для вас, будет использовать inotifywatch или incron для запуска скрипта по вашему выбору всякий раз, когда обновление будет завершено.


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


0
2018-02-22 04:52



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