Чи застосовує перенаправлення виводу до файлу блокування на файл?


30

Якщо я маю команду

$ ./script >> file.log

що дзвонить двічі, причому другий дзвінок відбувається до закінчення першого, що відбувається?

Чи отримує перший виклик ексклюзивний замок на вихідному файлі? Якщо так, чи не працює другий скрипт при спробі запису, чи оболонка приймає вихід (дозволяє сценарію закінчуватися) і видає помилку?

Або файл журналу записується двічі?


1
Я не знаю жодної системи, яка заблокувала б файл за замовчуванням. Більш імовірно, що дві програми закінчуються переплетенням своїх записів, оскільки обидві будуть у режимі додавання. Результати були б досить непередбачуваними. Замість "привіт світу" ви могли б отримати "hweolrllod".
jw013

Відповіді:


18

Оскільки ви використовуєте >>, що означає додавання, кожен рядок виводу з кожного примірника буде доданий у порядку, в якому він відбувся.

Якщо ваш скрипт висновок друкує 1\nчерез 5\nз одного секундною затримкою між кожним і , наприклад , два запуском 2,5 секунди пізніше ви отримаєте це:

1
2
1
3
2
4
3
5
4
5

Отже, щоб відповісти на ваше запитання: Ні.


23

Системи Unix за великим рахунком уникають обов'язкових блокувань. Є кілька випадків, коли ядро ​​заблокує файл проти модифікацій програм користувача, але це не так, якщо це просто записується іншою програмою. Жодна система Unix не заблокує файл, тому що програма пише на нього.

Якщо ви хочете, щоб одночасні екземпляри вашого сценарію не наступали на пальці ніг один одного, вам потрібно використовувати явний механізм блокування, наприклад .flock lockfile

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

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

Процес ефективно записує у файл, коли він викликає writeсистемний виклик. Заклик до writeатомарний: кожен виклик writeзаписує послідовність байтів, які не будуть перервані іншими програмами. Часто існує обмеження кількості даних, writeякі ефективно записуватиме один дзвінок : для більших розмірів записується лише початок даних, і програма повинна дзвонити writeзнову. Крім того, багато програм виконують буферизацію: вони накопичують дані в області пам’яті, потім записують ці дані в один шматок. Деякі програми промивають вихідний буфер після завершення рядка або іншого змістовного розділення. З такими програмами ви можете очікувати, що цілі лінії будуть безперебійними, якщо вони не надто довгі (до кількох кілобайт; це залежить від ОС). Якщо програма не розмивається на значущих місцях, а лише на основі розміру буфера, ви можете побачити щось на зразок 4 кБ від одного екземпляра, потім 4 кБ від іншого екземпляра, потім знову 4 кБ від першого екземпляра тощо.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.