Заменить файл, только если в bash нет доступа - PullRequest
0 голосов
/ 01 мая 2019

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

if [ -f file ]
then
    while true
    do
       if [ -n "$(fuser "file")" ]
       then
           echo "file is in use..."
       else
           echo "file is free..."
           break
       fi
   done
fi

{
   flock -x 3
   mv newfile file
} 3>file

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

Спасибо.

Ответы [ 2 ]

1 голос
/ 01 мая 2019

Мое требование - заменять file только тогда, когда к нему нет доступа.

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

Заменить file, не мешая при этом чтению / письму любых программ file.

Если этоВ этом случае вы можете использовать очень аккуратное поведение: в Unix-подобных системах файловые дескрипторы всегда указывают на файл (не путь), для которого они были открыты.Вы можете переместить или даже удалить соответствующий путь.См. Также Как команды UNIX mv и rm работают с открытыми файлами? .

Пример:

Откройте терминал и введите

i=1; while true; do echo $((i++)); sleep 1; done > file &
tail -f file

Первая команда записывает вывод в file и выполняется в фоновом режиме.Вторая команда читает файл и продолжает печатать его изменяющееся содержимое.

Откройте другой терминал и переместите или удалите file, например, с помощью

mv file file2
echo overwritten > otherFile
mv otherFile file2
rm file2
echo overwritten > file
echo overwritten > file2

Во время выполнения этих команд посмотритена выходе tail -f в первом терминале - ни на одну из этих команд это не повлияет.Вы никогда не увидите overwritten.

Решение для нового требования:

Из-за этого поведения вы можете заменить весь сценарий одной командой mv:

mv newfile file
0 голосов
/ 01 мая 2019

Рассмотрим lsof.

mvWhenClear() {
  while [[ -f "$1" ]] && lsof "$1"
  do sleep $delay
  done
  mv "$1" "$2" # still allows race condition
}
...