Применяет ли перенаправление вывода в файл блокировку файла?

30

Если у меня есть команда

$ ./script >> file.log

что вызывается дважды, а второй вызов происходит до того, как закончится первый, что происходит?

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

Или файл журнала записывается дважды?


источник
1
Я не знаю ни одной системы, которая блокировала бы файл по умолчанию. Что более вероятно, так это то, что две программы в конечном итоге будут чередовать свои записи, поскольку обе будут в режиме добавления. Результаты были бы довольно непредсказуемыми. Вместо «Привет, мир» вы можете получить «hweolrllod».
jw013

Ответы:

18

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

Если ваш скрипт вывод печатает 1\nчерез 5\nс одной секундной задержкой между каждым и , например , два запуском 2,5 секунды позже вы получите это:

1
2
1
3
2
4
3
5
4
5

Итак, чтобы ответить на ваш вопрос: Нет.

bahamat
источник
23

Системы Unix в целом избегают обязательных блокировок. Есть несколько случаев, когда ядро ​​блокирует файл от изменений пользовательскими программами, но не в том случае, если он просто записывается другой программой. Ни одна система unix не заблокирует файл, потому что программа пишет в него.

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

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

Плохая вещь, которая может случиться, если один из экземпляров записывает несколько блоков вывода и ожидает, что они выйдут вместе. Между последовательными записями одного экземпляра другие экземпляры могут выполнять свои собственные записи. Например, если экземпляр 1 записывает foo, затем экземпляр 2 записывает, helloи только тогда экземпляр 2 записывает bar, файл будет содержать foohellobar.

Процесс эффективно записывает в файл при writeвызове системного вызова. Вызов writeатомарен: каждый вызов writeзаписывает последовательность байтов, которая не будет прервана другими программами. Часто существует ограничение на то, сколько данных writeбудет эффективно записывать один вызов : для больших размеров записывается только начало данных, и приложение должно вызывать writeснова. Кроме того, многие программы выполняют буферизацию: они накапливают данные в области памяти, а затем записывают эти данные в один блок. Некоторые программы очищают выходной буфер после полной строки или другого значимого разделения. С такими программами можно ожидать, что целые строки будут непрерывными, если они не слишком длинные (до нескольких килобайт; это зависит от ОС). Если программа не очищается в значимых местах, а только в зависимости от размера буфера, вы можете увидеть что-то вроде 4 КБ из одного экземпляра, затем 4 КБ из другого экземпляра, затем снова 4 КБ из первого экземпляра и так далее.

Жиль "ТАК - прекрати быть злым"
источник