2014-11-26 2 views
2

Есть ли программный способ узнать, почему я не могу написать файл в сценарии оболочки (файл существует, доступ запрещен, полная файловая система и т. Д.)?Могу ли я узнать, почему я не могу написать файл в сценарии оболочки?

Например, в C одном использует переменную errno для этого:

FILE *fp = fopen("/etc/passwd", "w"); 
if (!fp) { 
    if (errno == EACCES) { 
     // ... 
    } 
    else if (errno == EEXISTS) { 
     // ... 
    } 
} 

Могу ли я сделать что-то подобное с помощью сценариев оболочки?

Мой тестовый сценарий:

#!/bin/sh 

err=$(echo 'x' 2>&1 > /etc/passwd) 
if [ $? -ne 0 ]; then 
    echo "An error occured: $err" 
    exit 1 
fi 

Запуск этого, как не суперпользователя, даст вам:

An error occured: 'test.sh: line 3: /etc/passwd: Permission denied' 

Проверка содержимого $err является не очень хорошее ИМХО решение ; сообщение об ошибке может измениться в будущем и зависит от настроек пользователя locale.

Я также знаю, что я могу сделать stat & некоторые другие проверки перед созданием файла или после того, как код выхода отличен от нуля; но это быстро выходит из-под контроля, если вы хотите проверить все возможные ошибки. В некоторых случаях он также подвержен условиям гонки (например, файл создается между вашим test -f и фактически записывает его).

Я использую оболочку POSIX и предпочитаю делать это с помощью POSIX-совместимого способа, но также допускается расширение или zsh.

+4

'' $ является кодом выхода/ошибки. это все, что вы получите, кроме фактического вывода строки, который вы захватываете. –

ответ

0

Большинство программ, которые ваша команда собирается вызывать, улавливают ошибку, интерпретируют errno и печатают описательное (но не машиночитаемое) сообщение об ошибке. Таким образом, формальная информация errno обычно теряется; все, что вы можете сделать, это интерпретировать сообщение с возможностью чтения человеком.

С другой стороны, причина причины для отказа произвольной команды зависит от интеллекта, и если вы не хотите запрограммировать искусственный для этого, вам это не удастся. Если сбой записи в файле /a/b/c/d, это может быть связано с тем, что d не имеет битов разрешения на запись, либо потому, что у любого из a, b, нет разрешений на выполнение или из-за ошибки ввода-вывода во время записи или из-за того, что файловая система устанавливается как доступная только для чтения. И я уверен, что просто забыл еще больше возможностей. И это было просто для простой записи в файле. Если вы попытаетесь вытащить это прямо для произвольных команд, это будет слишком много.

Для простых тем доступа к файлам (на основе разрешений) вы можете получить где-нибудь, используя faccessat(2) (но я не знаю об этом shell-интерфейсе).

0

Там в несколько ОС встроенных функций, чтобы проверить особенности файла:

она существует, но вы не можете писать/читать ему - это 0 байт - это каталог (!) - это символическая ссылка - и некоторые более

Проверить через

man test 

или иметь быструю проверку через: http://unixhelp.ed.ac.uk/CGI/man-cgi?test

Кроме того, вы можете, например, проверить, если каталог сам файл существует. Это может быть причиной того, что файл не существует. Вы можете использовать DIRNAME для этого:

http://linux.die.net/man/1/dirname

+0

Thanks; как я упоминал в своем вопросе, это не то, что я хотел бы сделать: * Я также знаю, что могу сделать stat и некоторые другие проверки перед созданием файла или после того, как код выхода не равен нулю; но это быстро выходит из-под контроля, если вы хотите проверить все возможные ошибки. В некоторых случаях это также подвержено условиям гонки (например, файл, создаваемый между вашим тестом -f и фактически его написанием). * – Carpetsmoker

+0

Да, все эти условия могут измениться в любое время, что также может быть что-то, что нужно помнить , Файл также может быть открыт (используется процессом) или нет. То, что вы также можете сделать, это сделать контрольную сумму (crc/cksum) для отслеживания изменений в файле. – tvCa

Смежные вопросы