Система CentOS5 x86_64, полностью обновлена.
У меня есть папка, которую нельзя перечислить (ls просто зависает, жрет память, пока не убьется). Размер директории почти 500к:
root@server [/home/user/public_html/domain.com/wp-content/uploads/2010/03]# stat .
File: `.'
Size: 458752 Blocks: 904 IO Block: 4096 directory
Device: 812h/2066d Inode: 44499071 Links: 2
Access: (0755/drwxr-xr-x) Uid: ( 3292/ user) Gid: ( 3287/ user)
Access: 2012-06-29 17:31:47.000000000 -0400
Modify: 2012-10-23 14:41:58.000000000 -0400
Change: 2012-10-23 14:41:58.000000000 -0400
Я могу видеть имена файлов, если использую ls -1f
, но он просто повторяет те же 48 файлов до бесконечности, каждый из которых имеет символы, отличные от ascii, где-то в имени файла:
La-critic\363-al-servicio-la-privacidad-300x160.jpg
Когда я пытаюсь получить доступ к файлам (скажем, чтобы скопировать их или удалить), я получаю такие сообщения:
lstat("/home/user/public_html/domain.com/wp-content/uploads/2010/03/Sebast\355an-Pi\361era-el-balc\363n-150x120.jpg", 0x7fff364c52c0) = -1 ENOENT (No such file or directory)
Я попытался изменить код, найденный на эта страница руководства и изменил код для вызова unlink для каждого файла. Я получаю ту же ошибку ENOENT при вызове отмены связи:
unlink("/home/user/public_html/domain.com/wp-content/uploads/2010/03/Marca-naci\363n-Madrid-150x120.jpg") = -1 ENOENT (No such file or directory)
Я также натянул "прикосновение", схватил системные вызовы, которые он делает, и воспроизвел их, а затем попытался отсоединить получившийся файл по имени. Это нормально работает, но папка по-прежнему содержит запись с тем же именем после завершения операции и выполнения программы в течение сколь угодно долгого времени (через 5 минут вывод strace составил 20 ГБ, и я остановил процесс).
Я в тупике, я бы действительно предпочел не отключать эту производственную машину (сотни клиентов) для проверки файловой системы, но я склоняюсь к тому, чтобы это был единственный вариант на данный момент. Если кто-то добился успеха с использованием других методов удаления файлов (по номеру inode, я могу получить их с кодом getdent), я бы хотел их услышать.
(Да, я пробовал find . -inum <inode> -exec rm -fv {} \;
и у него все еще есть проблема с отменой ссылки, возвращающей ENOENT)
Для тех, кто заинтересован, вот разница между кодом этой страницы руководства и моим. Я не стал беспокоиться о проверке ошибок на маллоках и т. Д., Потому что я ленив, и это разовый вопрос:
root@server [~]# diff -u listdir-orig.c listdir.c
--- listdir-orig.c 2012-10-23 15:10:02.000000000 -0400
+++ listdir.c 2012-10-23 14:59:47.000000000 -0400
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
+#include <string.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
@@ -17,7 +18,7 @@
char d_name[];
};
-#define BUF_SIZE 1024
+#define BUF_SIZE 1024*1024*5
int main(int argc, char *argv[])
{
@@ -26,11 +27,16 @@
struct linux_dirent *d;
int bpos;
char d_type;
+ int deleted;
+ int file_descriptor;
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
+ char* full_path;
+ char* fd_path;
+
for ( ; ; ) {
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
@@ -55,7 +61,24 @@
printf("%4d %10lld %s\n", d->d_reclen,
(long long) d->d_off, (char *) d->d_name);
bpos += d->d_reclen;
+ if ( d_type == DT_REG )
+ {
+ full_path = malloc(strlen((char *) d->d_name) + strlen(argv[1]) + 2); //One for the /, one for the \0
+ strcpy(full_path, argv[1]);
+ strcat(full_path, (char *) d->d_name);
+
+ //We're going to try to "touch" the file.
+ //file_descriptor = open(full_path, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK, 0666);
+ //fd_path = malloc(32); //Lazy, only really needs 16
+ //sprintf(fd_path, "/proc/self/fd/%d", file_descriptor);
+ //utimes(fd_path, NULL);
+ //close(file_descriptor);
+ deleted = unlink(full_path);
+ if ( deleted == -1 ) printf("Error unlinking file\n");
+ break; //Break on first try
+ }
}
+ break; //Break on first try
}
exit(EXIT_SUCCESS);
Вот простой способ определить, нуждается ли файловая система в ремонте, или, по крайней мере, понять, насколько велик ущерб ...
Скачать (бесплатно) Утилита моментальных снимков R1Soft / Idera Hot Copy. Это модуль RPM и ядра, который обеспечивает копирование при записи моментальных снимков файловых систем Linux без необходимости наличия LVM и т.д.
Допустим, ваши файловые системы выглядят так:
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 12G 4.4G 7.0G 39% /
tmpfs 14G 0 14G 0% /dev/shm
/dev/sda1 291M 166M 110M 61% /boot
/dev/sda3 9.9G 2.5G 7.0G 26% /usr
/dev/sdb1 400G 265G 135G 67% /home
Вы можете использовать горячую копию для создания снимка /home
без монтирования полученной файловой системы ... Затем запустите fsck
чтобы узнать, есть ли проблемы.
hcp --skip-mount /dev/sdb1
fsck -a /dev/hcp1
Это может сэкономить время перезагрузки и помочь оценить серьезность перед планированием простоя клиента.
В долгосрочной перспективе я бы просто использовал XFS в качестве файловой системы ... Но это уже другая тема ...
Я предполагаю, что вы делаете это в АКТИВНОЙ файловой системе. Таким образом, возможно, что пока вы выполняете поиск и тому подобное, файл был удален до того, как его можно было обработать с помощью find. Это было бы нормально.
Чтобы получить список файлов, я мог бы НЕ использовать ls. ls пытается выполнить сортировку, и с каталогом такого размера потребовалось бы довольно много времени, чтобы получить список, а затем отсортировать его.
Что я делаю в таких случаях (как пользователь root):
find dirname -ls >outfile
Если вы хотите удалить что-то в зависимости от времени:
find dirname -type f -mtime +60 -print0 | xargs -0 rm -f
Кстати, -0 и -print0 - это параметры в Linux, поэтому имена файлов со «специальными» символами правильно передаются в xargs. Вышеупомянутое, конечно, удаляет файлы, которые были изменены БОЛЕЕ 60 дней до этого.
Не используйте "найти ... -exec rm -fv {} \;"использовать"найти ... - удалить"вместо