LINUX.ORG.RU
ФорумAdmin

Удаленный каталог: зависание при открытии каталога, зависание копирования. Как делать резервные копии?


0

1

Здравствуйте!

Разбираюсь сейчас с работой с удаленными каталогами - примонтированном SAMBA-ресурсе или каталогом на облачным хранилище.

Монтирую каталог через smbmount или хранилище через программу cloudfuse.

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

1.

Спустя какое-то время после монтирования (несколько часов), каталог удаленного ресурса перестает открываться. При этом ресурс примонтирован, команда mount показывает что монтирование есть. Вариант для облака:

$ mount
...
fuse on /mnt/storage type fuse (rw,nosuid,nodev,user=user)

Узнать, что каталог перестал открываться можно одним способом - попробовать войти в каталог (cd) и попробовать получить список файлов (ls). Если терминал повиснет, значит нужно перемонтироваться. Терминал виснет так, что даже Ctrl+C не помогает.

Отмонтирование с целью дальнейшего монтирования приходится делать с опциями -f -l, иначе не отмонтируется:

#umount -f -l /mnt/storage

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

2.

Проблема может возникнуть в середине копирования большого файла. То есть, на начало копирования каталог хранилища доступен. В середине копирования (не всегда, вероятность 50/50) все виснет напрочь, как и в п.1.

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

★★★★★

Ответ на: комментарий от zgen

Когда уже на лоре автору темы разрешат удалять чужие комментарии...

Xintrea ★★★★★ ()
Ответ на: комментарий от exception13

продолжайте кушать эти т.н. «облака»

Давайте тогда представим, что имеем дело с расшаренным SAMBA-ресурсом, расположенном на другом конце страны. Проблемы один-в-один те же самые.

Как решать?

Xintrea ★★★★★ ()

Каким способом можно в таких нестабильных условиях сделать проверку - копирование зависло, его надо прибить, и скопировать заново?

1. не юзать кривую самбу

2. не юзать кривое fuse

drBatty ★★ ()
Ответ на: комментарий от exception13

продолжайте кушать эти т.н. «облака»

облака разные бывают... «облако» != быдлокод. Хотя на практике..

drBatty ★★ ()
Ответ на: комментарий от Xintrea

Не надо использовать samba ресурс на другом конце страны через негарантированные линки.

Вы же не удивляетесь, когда вам сообщают, что вычерпывать воду ситом нельзя?

zgen ★★★★★ ()
Ответ на: комментарий от zgen

Не надо использовать дерьмо для производства пуль.

А кто говорил, что ТС'а используют для производства пуль? Его используют только для производстваметана и аммиака.

anonymous ()
Ответ на: комментарий от drBatty

ssh+rsync.
быстро, надёжно, и ещё и безопасно. И не качаешь одно и то же 10 раз.

Я бы так и сделал, но хранилище работает не по ssh. На хранилище ssh вообще нету.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

ssh+rsync. быстро, надёжно, и ещё и безопасно.

SSH? На моей практике монтирование по sshfs тоже работает нестабильно. Точно так же может подвиснуть в любой момент, проверено многократно на всяких комбинациях осей сервера и рабочей станции.

Xintrea ★★★★★ ()

Терминал (шелл) виснет на команде cd, так как она встроенная в него. Попробуйте из скрипта для проверки вызывать:

/bin/ls /mnt/ТОЧКА_монтирования >/dev/null 2>&1 </dev/zero &

потом делать sleep на 1-2 секунды и смотреть в списке процессов этот ls. Если он есть и у него состояние D, значит нужно перемонтировать. ls будет в списке процессов пока не будет сделано перемонтирование, поэтому чтобы скрипт не наплодил процессов, он должен сначала проверять ls в списке процессов.

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

mky ★★★★★ ()
Ответ на: комментарий от mky

Я наловчился делать путем само-убивание родительского процесса через время. Для этого обращение к проблемному ресурсу помещаю в подпроцесс (sh -c). Скрипт вот такой:

selfPid=$$ ; 
echo "Self PID: $selfPid" ; 

at now+1min 2>&1 <<<"kill -9 $selfPid" ; 

timeStart=`date` ; 
echo "Time start $timeStart" ; 

sh -c "cd /mnt/storage/energobase ; ls -l"

timeStop=`date` ; 
echo "Time stop $timeStop"

И это даже работает. Правда, остается висеть подпроцесс, но хотя бы у этого скрипта можно анализировать код возврата. Если он 0 - значит нормально завершился. Если 9 - был самоубит.

Но проблема теперь в другом. Этот код не работает при вызове из PHP через exec().

$cmd='весь вышеприведенный код в одну строку';
exec($cmd);

После самоубиения возврат в PHP не происходит. В процессах видим такое дерево:

23854 pts/10 Ss 0:00 \_ -bash
25140 pts/10 S+ 0:00    \_ /usr/bin/mc -P /tmp/mc-xi/mc.pwd.23854
25142 pts/16 Ss 0:00         \_ bash -rcfile .bashrc
25260 pts/16 S+ 0:00             \_ php process.php
25261 pts/16 Z+ 0:00                 \_ [sh] <defunct>

Вот этот вот <defunct> невозможно убить. Хотя он, как видно, не зомби (не D/D+). Чтобы завершить работу, нужно удалять именно сам процесс php.

Что делать дальше не знаю...

Xintrea ★★★★★ ()
Ответ на: комментарий от maxcom

Облачный диск - это не машина с Linux. Это только диск. Поэтому только fs.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Уточняю, как выглядит дерево до и после.

До самоубиения:

23854 pts/10 Ss 0:00 \_ -bash
25140 pts/10 S+ 0:00     \_ /usr/bin/mc -P /tmp/mc-xi/mc.pwd.23854
25142 pts/16 Ss 0:00         \_ bash -rcfile .bashrc
25454 pts/16 S+ 0:00             \_ php process.php
25455 pts/16 S+ 0:00                 \_ sh -c selfPid=$$ ; echo "Self PID: $selfPid" ...
25459 pts/16 D+ 0:00                     \_ sh -c cd /mnt/storage/energobase ; ls -l

Самоубивается процесс 25455, у него статус S+.

После самоубиения:

23854 pts/10 Ss 0:00 \_ -bash
25140 pts/10 S+ 0:00    \_ /usr/bin/mc -P /tmp/mc-xi/mc.pwd.23854
25142 pts/16 Ss 0:00         \_ bash -rcfile .bashrc
25454 pts/16 S+ 0:00             \_ php process.php
25455 pts/16 Z+ 0:00                 \_ [sh] <defunct>

Видно, что процесс, котрый был S+ стал Z+. А ведь по идее он должен был просто уничтожиться.

Xintrea ★★★★★ ()
Ответ на: комментарий от mky

Блин, ну это мистика какая-то.

Из-под баша самоубиение работает.

Из-под PHP нет.

Ветки процессов абсолютно одинаковые. Только одна запущена из баша, а другая из PHP.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Реально, не понимаю. Какая разница, откуда запущен скрипт?

Щас еще раз руками проверил. Скрипт, запущенный из-под PHP, после самоубиения зависает, получает статус Z+,

Скрипт, запущенный напрямую нормально самоубиваниется.

Почему так?

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Он как раз зомби. Это проблемы php по правильно обработке завершения потомка.

D — это uninterruptible sleep, когда процесс вызывает системный вызов (например, чтение каталога) он на время этого вызова преходит в uninterruptible sleep и в случае ошибке в драйвере (в ядре) его из этого состояние не вытащить.

Вы написали какой-то адовый скрипт, и зачем вам php не понятно. Делайте «ls /mnt/storage/energobase», зачем вам делать «cd» в этот каталог?

Если вы просто убиваете по таймауту и не анализируете в каком состоянии (S, R, D) находится ls, то есть команда «timeout» (входит в coreutils), не нужно городить такой огород с at. Или можно убивать процесс из php.

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

mky ★★★★★ ()
Ответ на: комментарий от Xintrea

Погуглите, должны быть примеры по правильному запуску процессов из php. Именно родитель процесса долже заботиться о том, чтобы прочитать его exit status, только после этого такой потомок (зомби-процесс) исчезнет из таблицы процессов.

mky ★★★★★ ()
Ответ на: комментарий от mky

Вы написали какой-то адовый скрипт, и зачем вам php не понятно.

На PHP явсегда пишу логику, это очень удобно. Из него вызываю bash-команды, которые проще выполнить в шелле, чем городить в PHP. Каждой задаче - своя среда исполнения.

Если вы просто убиваете по таймауту и не анализируете в каком состоянии (S, R, D) находится ls, то есть команда «timeout» (входит в coreutils), не нужно городить такой огород с at.

В CentOs 5.8 программа timeout не входит в coreutils. Ее вообще нет.

# yum search timeout
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos-mirror.rbc.ru
 * epel: mirror.xfes.ru
 * extras: centos-mirror.rbc.ru
 * updates: centos-mirror.rbc.ru
========================================= Matched: timeout ==========================================
apcupsd.i386 : APC UPS Power Control Daemon for Linux
libevent.i386 : Abstract asynchronous event notification library
pam_pkcs11.i386 : PKCS #11/NSS PAM login module
python-mtTkinter.noarch : A thread-safe version of Tkinter
sudo.i386 : Позволяет предоставить определенным пользователям ограниченные права суперпользователя.

# yum provides "*/timeout"
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos-mirror.rbc.ru
 * epel: mirror.xfes.ru
 * extras: centos-mirror.rbc.ru
 * updates: centos-mirror.rbc.ru
epel/filelists_db                                                             | 4.8 MB     00:00     
bash-3.2-32.el5.i386 : The GNU Bourne Again shell (bash) version 3.2
Repo        : base
Matched from:
Filename    : /usr/share/doc/bash-3.2/scripts/timeout

bash-3.2-32.el5.i386 : Оболочка GNU Bourne Again shell (bash), версия 3.1.
Repo        : installed
Matched from:
Filename    : /usr/share/doc/bash-3.2/scripts/timeout

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

Если я из PHP вызову «sh -c» (PID1), потом из него еще раз «sh -c» (PID2), и из него опять же через «sh -c» зависающую команду (PID3), то убивание PID2 должно пройти независимо от того, откуда PID2 запущен? Он должен убиться, ведь родитель у него не PHP? Ничего не должно припятствовать его завершению по kill -9?

Xintrea ★★★★★ ()
Ответ на: комментарий от mky

Погуглите, должны быть примеры по правильному запуску процессов из php. Именно родитель процесса долже заботиться о том, чтобы прочитать его exit status, только после этого такой потомок (зомби-процесс) исчезнет из таблицы процессов.

Ваша теория неправильная. Сделал эксперимент:

Запуск:

31350 S+ 0:00 \_ php process.php
31351 S+ 0:00     \_ /bin/sh ./checkReadWriteProxy.sh
31352 S+ 0:00         \_ /bin/sh ./checkReadWrite.sh <- Этот процесс убивается
31355 D+ 0:00             \_ sh -c cd /mnt/storage/energobase ; ls -l

Убиение:

31350 S+ 0:00 \_ php process.php
31351 Z+ 0:00     \_ [checkReadWriteP] <defunct>

Обратите внимание: убивается процесс, у которого родитель не PHP, а просто оболочка. По идее, уж она-то должна правильно обрабатывать удаление подпроцесса.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

SSH? На моей практике монтирование по sshfs тоже работает нестабильно.

ты ощущаешь разницу между sshfs и rsync(внимание!) по ssh? Это кагбе немного разные вещи

По теме - хз что сказать. Я с такой проблемой не сталкивался - CIFS точки монтирования(поверх обычной IP-сети) отваливаются сами по таймауту если с сетью проблемы

Pinkbyte ★★★★★ ()
Последнее исправление: Pinkbyte (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Я бы так и сделал, но хранилище работает не по ssh. На хранилище ssh вообще нету.

вот поднимите. А то это не хранилище, а помойка. Извините, если что не так.

drBatty ★★ ()
Ответ на: комментарий от Xintrea

На моей практике монтирование по sshfs тоже работает нестабильно.

это тоже fuse.

drBatty ★★ ()
Ответ на: комментарий от Xintrea

Если не затруднит, дайте минимальные код на php и bash, который воспроизводит данную ситуацию. Только без fusefs, на sleep или ещё чём.

И я не понял, что значит «убивается процесс, у которого родитель не PHP, а просто оболочка»? Ведь у вас остаётся процесс с PID 31351, его родителем был и остался PID 31350 (php process.php). А если вы убиваете bash-скрипт, то он, ЕМНИП, сам убивает своих потомков. Поэтому его потомок PID 31352 умирает, а потомок 31355 должен доставатся процессу init. Посмотрите при следующем эксперименте полный список процессов, нет ли в нём ls.

P.S. Да, в centos 5.8 timeout не входит, слишком старый он. Но, если у вас php, то он умеет сам посылать kill процессам. По мне, «at now+1min» это в чистом виде логика, и она должна быть в php.

mky ★★★★★ ()
Ответ на: комментарий от mky

Если не затруднит, дайте минимальные код на php и bash, который воспроизводит данную ситуацию. Только без fusefs, на sleep или ещё чём.

Блин, код на работе. Я уже его так уделал что аж на питон переписывать начал.

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

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

Xintrea ★★★★★ ()
Ответ на: комментарий от mky

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

Xintrea ★★★★★ ()

А удалось как-то решить проблемы?
Сейчас пытаюсь юзать cloudfuse для хранилища от selectel...

madcore ★★★★★ ()
Ответ на: комментарий от madcore

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

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

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

Скрипт supload на Bash. Возвращает ли он код ошибки?

В обсуждение даже написал сам автор скрипта из Селектела, который ради этого на ЛОРе зарегистрировался.

Xintrea ★★★★★ ()
Ответ на: комментарий от Xintrea

Т.е., использовать это хранилище как нормальную смонтированную ФС никак не выйдет? Нам, при этом, нужен одновременный доступ с нескольких машин.

madcore ★★★★★ ()
Ответ на: комментарий от madcore

Это не от селектела зависит, а от уродливого дискового ввода-вывода в Linux. Как никогда в Linux небыло нормальной работы с дискетами, так никогда не будет нормальной работы с примонтированными сетевыми дисками. Это касается и cloudfuse, и sshfs, и ftpfs.

Xintrea ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.