Назад | Перейти на главную страницу

Как обнаружить или зарегистрировать прерванные загрузки с помощью SFTP-сервера OpenSSH?

У меня есть эта проблема, когда наш клиент использует усеченные данные по SFTP. Я не уверен, на нашей или на его стороне проблема. Я включил ведение журнала SFTP, но это не позволяет мне определять, была ли прервана загрузка.

Например, если я запускаю клиент sftp и нажимаю ^C в середине загрузки сервер просто говорит что-то вроде close "/data/README.md" bytes read 0 written 5366, который неотличим от непрерывной загрузки.

Я думаю что-то вроде .part префикс будет работать, но, глядя на другие сообщения о сбоях сервера, я не думаю, что это возможно с сервером OpenSSH sftp.

Итак, есть ли способ определить, была ли загрузка файла прервана?

Я предполагаю, что под «клиентом sftp» вы имеете в виду клиент SFTP OpenSSH. "Проблема" в том, что при нажатии Ctrl + C, он останавливает загрузку и полностью закрывает удаленный файл, как если бы загрузка была полностью завершена (обратите внимание, что это правильное поведение, и многие другие клиенты SFTP ведут себя так же). Таким образом, сервер не может определить, что загрузка была прервана.


Ну, строго говоря, да, так как клиент OpenSSH отправляет серверу подсказку о размере при создании файла. Но сервер OpenSSH не использует и даже не регистрирует эту информацию. Хотя было бы довольно просто изменить его код для регистрации размера, если это для вас вариант.

Видеть process_open в sftp-server.c:

a = get_attrib();
flags = flags_from_portable(pflags);
mode = (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a->perm : 0666;
logit("open \"%s\" flags %s mode 0%o",
    name, string_from_portable(pflags), mode);

Изменить logit заявление на:

logit("open \"%s\" flags %s mode 0%o size %llu",
    name, string_from_portable(pflags), mode, (unsigned long long)a->size);

Обратите внимание, что отправка подсказки о размере необязательна. Некоторые клиенты SFTP отправляют его (например, OpenSSH или WinSCP), а некоторые - нет (например, PSFTP, FileZilla или LFTP). В таком случае вы получите 0 в a->size.


Если бы клиент действительно прервал загрузку (без полного закрытия удаленного файла, например, когда sftp убит), вы сможете определить это по префиксу "принудительный" для "закрытия" записи:

принудительное закрытие "/data/README.md" байт прочитано 0 записано 5366