Як неінвазивно перевірити доступ для запису до файлу?


20

Як у скрипті оболонки я легко і неінвазивно перевіряю доступ для запису до файлу, не намагаючись змінити файл?

Я міг би проаналізувати вихід stat, але це здається дійсно складним та, можливо, крихким, хоча я не впевнений, наскільки статичний вихід відрізняється в різних реалізаціях та за часом.

Я міг би додати в кінець файлу і побачити, чи вдалося це, але це потенційно небезпечно, з двох причин, про які я можу подумати:

  1. Тепер я маю видалити додавання, і якщо якийсь інший процес записує у файл, це одразу стає нетривіальним, оскільки мій рядок вже не останній.
  2. Будь-який процес, який читає файл, може мати довільні вимоги до вмісту цього файлу, і я, можливо, просто порушив цю програму.

Відповіді:


29

Просто використовуйте wпрапор testутиліти:

[ -w /path/to/file ] && echo "writeable" || echo "write permission denied"

Зауважте, що якщо ви збираєтеся написати файл у файл пізніше, все одно можливо, ви не зможете записати на нього. Файл, можливо, перемістився, дозволи можуть змінитися і т. Д. Також може траплятися -wвиявлення дозволів на запис, але якийсь інший фактор втручається, щоб зробити файл непридатним для запису .


1
Звичайно! Я повинен був подумати, щоб перевірити сторінку людини. Дякую.
user50849

1
@qweilun це вбудована оболонка, але ви можете відобразити сторінку man через man testабоman [
хаос

5
@chaos Це вбудована оболонка і зовнішній виконуваний файл - спробуйтеtype -a
Volker Siegel

1
На джерелоtest використовується, euidaccessяке просто перевіряє біти дозволу . Чи немає інших факторів (наприклад, SELinux), які можуть заборонити доступ до запису?
замнуть

2
@BroSlow &&і ||мають однаковий пріоритет. Вони оцінюються зліва направо.
Wildcard

11

Інший підхід:

if >> /path/to/file
then
    echo "writeable"
else
    echo "write permission denied"
fi

Це спробує відкрити файл для додавання, і, якщо це вдасться, не запускати жодної команди (тобто виконувати нульову команду ) з виведенням у файл. 

Будьте уважні, що при цьому створюється порожній файл, якщо його не існувало.

-wОператор testкоманди може просто зробити , stat а потім спробувати з'ясувати , чи виглядає це , як ви повинні мати доступ. Моя альтернатива (вище) є більш надійною, ніж testпідхід у деяких спеціальних умовах, оскільки вона змушує перевірку доступу робити ядро, а не оболонку. Наприклад,

  • якщо файл знаходиться у файловій системі, яка не є Unix - особливо якщо він віддалено встановлений з файлового сервера, який не є Unix - тому що statможе повернути значення режиму, яке вводить в оману.
  • якщо файл знаходиться у файловій системі, яка встановлена ​​лише для читання.
  • якщо файл має ACL, і режим робить його таким, як ви повинні мати доступ, але ACL це заперечує, або навпаки.
  • якщо якась система безпеки (AppArmor, SELinux, ...) забороняє доступ до файлу.

3
Я щойно тестував це (на Debian). Жоден час не був змінений, і саме так він повинен працювати на будь-якому Unix. Час доступу має бути оновлений лише у тому випадку, якщо ви читаєте з файлу, час модифікації повинен бути оновлений лише у тому випадку, якщо ви пишете у файл. Цей код не робить жодного. @Schwern: чи маєте ви посилання на свою заяву? Хтось із вас спробував це?
G-Man каже: "Відновіть Моніку"

2
PS @muru: Я просто спробував touchфайл, який я мав, але не мав доступу до запису, і це вдалося. Я думаю, що це chmodфайл і chmodповернути його назад. Отож, touchздається, абсолютно марно, як відповідь на запитання.
G-Man каже: «Відновіть Моніку»

2
@ G-Man ах, це цікаво. IIRC vimмає таку поведінку, щоб швидко змінювати дозволи, коли змушені писати на файли лише для читання. Я перевірив strace, touchз openпровалами EACCES, але наступний заклик utimensatуспіху, саме тому я думаю, що touchв цілому завершується успішно.
муру

2
@muru: Дякую за перевірку. utimensat(2)говорить: " Вимоги до дозволів: 1. Доступ до запису (або) 2. Ефективний ідентифікатор користувача абонента повинен відповідати власнику файлу, ..."
G-Man каже "Повторити Моніку"

3
Інші проблеми, як для Champignac's: >> fileне є портативними (наприклад, запускає NULLCMD в zsh), використовуйте true >> fileзамість цього. І якщо файл має назву "труби", він має неприємні побічні ефекти.
Stéphane Chazelas

3

G-man має рацію: [ -w ]не завжди скаже правду. Тут можна впоратися з неіснуючим файлом та дозволом, відхиленим від оболонки:

( [ -e /path/to/file ] && >> /path/to/file ) 2> /dev/null && 
  echo writable || 
  echo not writable

Оновлення : виглядає страшно, чи не так? Ну, так і є. Хм ... як це висловити ... НЕ ВИКОРИСТОВУЙТЕ це, якщо ви прекрасно не знаєте, що перебуваєте в умовах, коли він вимагає працювати так, як очікувалося. Дивіться коментар Стефана.

Що робити висновок? Навіть якщо [ -w ]не каже правди, це одна команда, яка призначена для виконання роботи. Якщо цього не буде, ну, ми будемо звинувачувати в цьому, писати звіти про помилки, і це спрацює в майбутньому. Краще перевірити умови, в яких він працює і використовувати [ -w ]; написати спеціальний код для особливих справ. Обхідні шляхи мають свої умови.

[ -w /path/to/file ]

найкращий апріорі .


3
Якщо файл має назву "труба", вона буде висіти, якщо не читати, і навіть якщо читач буде мати неприємні побічні ефекти. test -wу більшості застосувань таких застосувань access(2)повинно вистачити для тестування дозволів.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.