Чи bash відкриває файли в O_APPEND під час використання “>>” в Linux?


38

Якщо ми використовуємо, echo 1234 >> some-fileтоді Документація говорить, що результат додається.

Я здогадуюсь, що якщо деякий файл не існує, O_CREAT створить новий файл. Якщо >він використовувався, O_TRUNC буде усікати існуючий файл.

У разі >>: Чи буде файл відкрито як O_WRONLY (або O_RDWR) і буде зроблено прагнення закінчити і записати операцію, імітуючи O_APPEND? Або файл буде відкрито як O_APPEND, залишивши його в ядрі, щоб переконатися, що додавання відбувається?

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


12
Проблема в NFS не в тому, що O_APPENDвона не підтримується; проблема в тому, що вона наслідується. У локальній файловій системі декілька процесів запису в один і той же файл, відкритий з O_APPEND ніколи, не перезаписують дані один одного; на NFS, O_APPENDімітується шляхом пошуку до кінця перед написанням, що залишає можливість перегонових умов. На NFS це не обійти; кожному паралельному письменнику потрібно написати свій файл. Єдиний спосіб подолати це - налаштувати серверний процес на сервері NFS, надати журнали реєстраторів |nc server portі сервер додавати в журнал вхідні дані.
Гунтрам Блом підтримує Моніку

@GuntramBlohm, +1, дякую за підтвердження. В основному, ваша пропозиція полягає у використанні до файлу лише одного процесу запису, а всі інші записи письменника пройдуть цей процес.
Прем

Стільки хороших відповідей, Не впевнений, яку відповідь я повинен прийняти. Перший Брюс Едігер показав, що використовується O_APPEND. Далі Random832 показав, що це наведено в стандартах. Нарешті, Ерік Реноф показав вихідний код з тією ж відповіддю. Всі три перспективи додають до остаточної повної картини.
Прем

6
Коротше кажучи, NFS - це набір помилок, і його не слід використовувати.
Р ..

2
Так, але ми вже дізналися про це назад, коли був винайдений O_EXCL.
Кевін

Відповіді:


60

Я побіг так: strace -o spork.out bash -c "echo 1234 >> some-file"щоб з'ясувати ваше запитання. Ось що я знайшов:

open("some-file", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

Жодного файлу з назвою "деякий файл" не було в каталозі, в якому я запустив echoкоманду.


50

Це робиться не тільки в Bash, це вимагається стандартом.

З єдиної специфікації Unix :

Додане перенаправлення виводу повинно спричинити відкриття файлу, ім'я якого в результаті розширення слова, для виведення на призначений дескриптор файлу. Файл відкривається так, ніби функція open () , визначена в томі системних інтерфейсів POSIX.1-2008, викликалася прапором O_APPEND. Якщо файл не існує, він повинен бути створений.

Тому будь-яка оболонка, сумісна з POSIX, повинна це робити. У деяких системах Unix /bin/shможе бути оболонка Bourne, що не є POSIX (оболонка Bourne спочатку була написана раніше, коли O_APPENDбула винайдена), і наявна оболонка POSIX, як правило ksh, буде доступна як shв іншому місці шляху, наприклад у Solaris /usr/xpg4/bin.


2
Цікаво, що одна оболонка, яка цього не робить, - це оболонка Борна. Оболонка Bourne відкривається без O_TRUNC та lseek () s до кінця. Це було б тому, що воно було написане до додавання прапора O_APPEND open(). >>сама була представлена ​​його попередником панциром Thomson.
Стефан Шазелас

1
@ StéphaneChazelas Крім того, я шукав джерело оболонки C для різних версій, і прапор O_APPEND не був введений до 4.3BSD-Reno.
Випадково832

У ньому написано "як би", так чи не можна було його реалізувати інакше (але створюючи той же ефект, що спостерігається)? Не здається, що стандарт вимагає використання O_APPEND, просто щось, що поводиться "як би".
Томас

1
@Thomas Це означає, що ви збираєтеся отримати всю поведінку, задокументовану для O_APPEND, що означає перестановку в кінці для кожного запису. "Ніби" - це лише стандартна багатослівність, яка має на увазі, наприклад, її відкриття якимось способом, ніж виклик функції open () на нетрадиційних платформах Unix.
Випадково832

+1, за показ того, що така поведінка відповідає стандартам.
Прем

32

Дивлячись на джерело, він використовує O_APPEND. Для баш 4.3.30 у make_cmd.cрядку 710-713 читайте:

case r_appending_to:                /* >>foo */
case r_append_err_and_out:          /* &>> filename */
  temp->flags = O_APPEND | O_WRONLY | O_CREAT;
  break;

+1, для відображення відповіді з точки зору вихідного коду.
Прем

19

Давайте дослідимо, що за straceдопомогою локальної файлової системи (не-NFS):

$ strace -eopen -- bash -c "echo foo >> /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3

$ strace -eopen -- bash -c "echo foo > /tmp/testfile000" 2>&1 | grep /tmp/testfile000
open("/tmp/testfile000", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3

Інші оболонки, а саме dash, dash, shз BusyBox »і mkshповодяться точно так же.

Цей параметр -e openозначає -e trace=openвідстежувати лише open()системний виклик.

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