Сбой чтения файлов в папке scriptfiles
#1

Нужны советы. Внезапно произошёл какой-то сбой с файлами. В один миг перестались читаться все файлы (.txt, .bans, .ini, .db), которые находятся в папке scriptfiles.
Клиентский лог server_log.txt продолжил работу после сбоя, сервер не упал, продолжать работать, от игроков жалоб не было, анализ журнала фтп от хостера тоже ничего не дал.

Анализ server_log.txt:

перед сбоем
[17:32:28] [chat] [Nickname]: быстро там приступник был
[17:32:35] [chat] [Nickname]: где
[17:32:35] [chat] [Nickname]: спецназ я теперь не в лодке
[17:32:36] [chat] [Nickname]: на крышу
[17:32:41] Incoming connection: *.*.*.*:49640
[17:32:41] [join] Nickname has joined the server (8:*.*.*.*)
и вот началось отсюда
[17:32:41] Не удалось открыть файл 'bans/bans.ini'
[17:32:41] Не удалось создать файл лога 'log/2016/05/log_05.05.16.txt'
...
[00:25:46] Не удалось открыть конфиг 'config/news.ini'
[00:25:46] Не удалось открыть конфиг 'config/cmds.ini'
[00:25:46] Не удалось открыть конфиг 'config/rules.ini'
[00:25:46] Не удалось открыть конфиг 'config/faq.ini'
[00:25:46] Не удалось открыть конфиг 'config/phrases.ini'
[00:25:46] Не удалось открыть конфиг 'config/spawn.ini'
[00:25:47] Не удалось создать файл лога 'log/2016/05/log_07.05.16.txt'

Код. Практически все файлы мода создаются/читаются в созданной мною ф-ии ниже:
PHP Code:
ExampleFunc()
{
    if (!
fexist("config/news.ini"))
    {
        
printf("Конфиг '%s' не найден", "config/news.ini");
        return;
    }
    new 
File: handle = fopen("config/news.ini", io_read);
    if (
handle)
    {
        
// Код...
        
fclose(handle);
    }
    else
    {
        
// Срабатывает именно вот эта часть кода
        
printf("Не удалось открыть конфиг '%s'", "config/news.ini");
    }
} 
За пол года работы сервера - такой сбой с файлами произошёл впервые. После выключения сервера (/rcon exit) все файлы вновь стали нормально читаться, что это за уязвимость в моде пока не ясно
Reply
#2

Серв на лине? Во время работы меняются права на файлы в системе?
Reply
#3

На лине да. На счёт прав если честно не знаю что там, я лично их не менял, и в изменение прав никогда не лезу.
Reply
#4

Просто из практики бывало, что юзеры сначала под рутом запускали серв, а потом через юзера и получали подобную ситуацию с файлами.

А ещё стоит проверить на то, что эти же файлы до момента вызова твоей функции уже закрылись (поискать не забыл ли где fclose()
Reply
#5

Спс, буду разбираться. Если есть ещё варианты, пишите. Файлы снова стали читаться после перезагрузки, но это же не выход, потому что есть вероятность - что сбой снова повторится не завтра, так через месяц)
Самое интересное, что всё перестало читаться из папки scriptfiles, даже базы .db, в которые я вообще не лез.
Reply
#6

Явно проблема с правами доступа.
Reply
#7

pawn Code:
return;
1 или 0 - сделай выбор)
Reply
#8

Quote:

1 или 0 - сделай выбор)

ахаах, мой выбор - вернуть ничего)
Quote:

Явно проблема с правами доступа.

Что мне нужно делать в этом случае?
Вот скрин с фтп FileZilla Client, все файлы в scriptfiles имеют числовое значение 644
Reply
#9

Quote:
Originally Posted by Diman777
View Post
ахаах, мой выбор - вернуть ничего)

Что мне нужно делать в этом случае?
Вот скрин с фтп FileZilla Client, все файлы в scriptfiles имеют числовое значение 644
Покажи вывод ls -l scriptfiles/
Reply
#10

Доступ к файлам мода, которые на Лине - я получаю только через фтп-клиент. Где ж я ввиду команду ls? Не особо шарю в таких тонкостях, поэтому хз
Reply
#11

Quote:
Originally Posted by Diman777
View Post
Доступ к файлам мода, которые на Лине - я получаю только через фтп-клиент. Где ж я ввиду команду ls? Не особо шарю в таких тонкостях, поэтому хз
Тогда покажи владельца этих файлов (можно посмотреть в FileZilla).
Reply
#12

У всех файлов ftp владелец
Reply
#13

Quote:
Originally Posted by Diman777
View Post
У всех файлов ftp владелец
Поменяй владельца на того, от которого пытаешься запустить сервер. Или добавь своего пользователя в группу ftp. Если не знаешь как это сделать, обратись к своему хостинг провайдеру.
Reply
#14

Собственно получил ответ от тех. поддержки:
Quote:

Работа по FTP производится под тем же пользователем, под которым работает игровой сервер.
Никаких изменений прав не нужно - это ничего не исправит, однако может вызвать проблемы при их неправильной установке.
В Вашем сообщении на форуме указано "Файлы снова стали читаться после перезагрузки" - это однозначно указывает на проблемы в моде, которые были убраны перезагрузкой. Очевидно, в случае сбоя ОС и/или файловой системы перезапуск программы никак бы не исправил ситуацию.

Также пояснили, что проблема скорей всего в моде (указали на fclose) и посоветовали провести подробный дебаг.
Reply
#15

Я бы проверил, сколько/какие файлы открыты, когда начинаются проблемы
Reply
#16

Quote:

сколько/какие файлы открыты

Приведи пример такого способа, или в чём принцип
Reply
#17

Quote:
Originally Posted by Diman777
View Post
Приведи пример такого способа, или в чём принцип
Надо полагать, что как-то так

PHP Code:
#define MAX_OPENED_FILES     (508) //на виндовс получилось открыть 507
#define MAX_PATH_LEN        (64) //это от балды: я не знаю, что тут должно быть
enum of_enum
{
    
filepath[MAX_PATH_LEN],
    
File: filehandle
}
new 
opened_files[MAX_OPENED_FILES][of_enum];
new 
opened_files_count;
stock File: temp_fopen(path[], filemode:mode = io_readwrite)
{
    new 
File: handle = fopen(path, mode);
    if(
handle)
    {
        if(
opened_files_count < MAX_OPENED_FILES)
        {
            
strmid(opened_files[opened_files_count][filepath], path, 0, MAX_PATH_LEN - 2, MAX_PATH_LEN);
            
opened_files[opened_files_count][filehandle] = handle;
            
opened_files_count ++;
        }
        else
        {
            
printf("temp_fopen: слишком много открытых файлов (%s)", path);
        }
    }
    return 
handle;
}
#define fopen temp_fopen
stock temp_fclose(File: handle)
{
    new 
ret = fclose(handle);
    if(
ret == 1)
    {
        for(new 
i; i < opened_files_count; i++)
        {
            if(
opened_files[i][filehandle] == handle)
            {
                
opened_files_count--;
                
                if(
i != opened_files_count)
                {
                    
strmid(opened_files[i][filepath], opened_files[opened_files_count][filepath], 0, MAX_PATH_LEN - 2, MAX_PATH_LEN);
                    
opened_files[i][filehandle] = opened_files[opened_files_count][filehandle];
                }
            
                break;
            }
        }
    }
    
    return 
ret;
}
#define fclose temp_fclose
COMMAND:openedfiles(playerid)
{
    
printf("На данный момент открыто файлов: %d", opened_files_count);
    
    for(new 
i; i < opened_files_count; i++)
    {
        
printf("%d) %s", i, opened_files[i][filepath]);
    }
    
    return 
1;
} 
Это надо добавить в самый верх. Команда /openedfiles выводит в лог список открытых файлов.

И да, следует заметить, что это не сработает, если файлы открываются еще где-либо кроме основного мода.
Reply
#18

Ого, буду тестить, спс)
Reply
#19

Вообщем наблюдал за модом, и эта фигня с файлами повторялась уже раз 5, причём есть небольшая особенность - файлы перестают работать ~ через 5-6 дней работы мода (если мод не перезагружать конечно же).
Попробывал сделать следующее - отключал файлы по одному, что выявить где проблема, и теперь на 95% уверен, что проблема в моём логе. После его добавления началась эта проблема скорей всего.

Код
PHP Code:
// Макс. длина одной строки в логе (время + группа + текст)
const MAXLEN_STR_LOG = 300;
new 
str_log[STRING_256];
#define Log(%1,%2,%3);\
    
{format(str_log, STRING_256, %2, %3);\
    
_Log(%1, str_log);}
_Log(group[], text[])
{
    new 
day, month, year, hour, minute, second;
    
getdate(year, month, day);
    
gettime(hour, minute, second);
    new 
name_log[STRING_64];
    
format
    
(
        
name_log, STRING_64,
        
"log/%d/%02d/log_%02d.%02d.%02d.txt",
        
year, month, day, month, year-2000
    
);
    new 
File:handle;
    if (!
fexist(name_log))
    {
        
handle = fopen(name_log, io_write);
        if (
handle)
        {
            
fclose(handle);
        }
    }
    
handle = fopen(name_log, io_append);
    if (
handle)
    {
        new 
str_fmt_log[MAXLEN_STR_LOG];
        
format
        
(
            
str_fmt_log, MAXLEN_STR_LOG, "%02d.%02d.%02d %02d:%02d:%02d <%s> %s\r\n",
            
day, month, year-2000, hour, minute, second, group, text
        
);
        for (new 
i = 0; i < strlen(str_fmt_log); i++)
        {
            
fputchar(handle, str_fmt_log[i], false);
        }
        
fclose(handle);
    }
    else
    {
        
printf
        
(
            
"Не удалось создать файл лога '%s'\n\
            Возможные причины:\n\
            1) отсутствует папка с именем 'log';\n\
            2) отсутствует папка с текущим годом;\n\
            3) отсутствует папка с текущим месяцем."
,
            
name_log
        
);
    }
} 
Использование
PHP Code:
Log("деньги", "%s (%d) передал игроку %s (%d) $%d", GetPlayerNameEx(from_id), from_id, GetPlayerNameEx(him_id), him_id, money);
Log("жалобы", "%s (%d) отправил ЖБ на %s (%d): %s", GetPlayerNameEx(senderid), senderid, GetPlayerNameEx(intruderid), intruderid, cmd_dest); 
Записи
02.07.16 00:00:08 <пикап> Nickname (3) купил 'Гранаты' цена $3500 патроны 1
02.07.16 00:11:08 <чат/общий> Nickname (1): ок спасибо

Казалось бы - лог записывает всё на ура, 1 день = 1 файл. Но в чём может быть тут проблема? Срабатывает printf, который приведён в коде.

stabker через твой код попробывал сделать дебаг (таймер поставил в OnGameModeInit вместо команды, ибо вводить постоянно команду - это лольство). В клиентский лог постоянно выводит, что открыто 0 файлов, хотя ясен перец, что при входе в игру какие-то файлы открывались для чтения/записи. Код поключил разумеется сразу после a_samp.inc, в самый верх.
Reply
#20

Хз, в коде все нормально, насколько я разбираюсь. Только вот это не обязательно:

PHP Code:
if (!fexist(name_log)) 
{ 
    
handle = fopen(name_log, io_write); 
    if (
handle) 
    { 
        
fclose(handle); 
    } 
} 
io_append же все равно создаст файл, если его не существует.

---

Попробуй добавить

PHP Code:
printf("На данный момент открыто файлов: %d", opened_files_count); 
     
for(new 
i; i < opened_files_count; i++) 
{ 
    
printf("%d) %s", i, opened_files[i][filepath]); 
} 
сюда

PHP Code:
else 
{ 
    
printf 
    
( 
        
"Не удалось создать файл лога '%s'\n\ 
        Возможные причины:\n\ 
        1) отсутствует папка с именем 'log';\n\ 
        2) отсутствует папка с текущим годом;\n\ 
        3) отсутствует папка с текущим месяцем."
, 
        
name_log 
    
); 
} 
По крайней мере будет известно, сколько файлов открыто на момент возникновения проблемы. Даже если 0, то это тоже важный результат.

Quote:
Originally Posted by Diman777
View Post
stabker через твой код попробывал сделать дебаг (таймер поставил в OnGameModeInit вместо команды, ибо вводить постоянно команду - это лольство). В клиентский лог постоянно выводит, что открыто 0 файлов, хотя ясен перец, что при входе в игру какие-то файлы открывались для чтения/записи. Код поключил разумеется сразу после a_samp.inc, в самый верх.
Ну так они же сразу закрываются, поэтому и 0. Либо проблема в чем-то другом, либо она еще не проявилась, когда ты тестил через мой код. Надо подождать достаточно долго или воспользоваться советом, который я написал выше.

---

Как создаются папки под логи?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)