Мы решили, что подобные случаи достойны серии небольших статей под общим названием «Работа с сообщениями об ошибках».
И сегодня у нас подарок от всеми любимой программы git.
В очередной раз, сделав git pull на тестовый сервер, клиент увидел вот такое сообщение:
fatal: write failure on 'stdout': No space left on device
И обратился к нам с просьбой разобраться, почему это он не может на stdout писать
Место на диске и свободных inode было достаточно. Клонирование того же репозитория на этот же сервер в другой каталог проходило без проблем.
Гугление по данной фразе ни к чему не привело.
То, что клонирование проходит настойчиво, подвигает нас к выводу, что поломалась локальная копия тестового сервера. Начали поиск инструментов для починки git-репозитория, но тут заметили странную вещь:
df -h
Filesystem Size Used Avail Use% Mounted on
/dev/simfs 535G 364G 144G 72% /
none 2.9G 2.9G 0 100% /dev
none 583M 1.1M 582M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 1.2G 0 1.2G 0% /run/shm
none 100M 0 100M 0% /run/user
На разделе /dev занято 100% места. Все 2.9G — странно.
Заходим в /dev и видим файл /dev/null размером как раз с эти 2.9 гигабайта.
Видимо, кто-то когда-то удалил устройство /dev/null, а сервисы так и продолжили писать в /dev/null, создав обычный файл и потихоньку забивая место.
Удалили файл, создали устройство, перестартовали сервисы, которые писали в /dev/null — освободилось место на /dev и git pull отработал без проблем и ошибок.
Комментарии (17)
ploop
17.04.2015 16:36+22Интересно, а при чём здесь git? :)
LuckySB Автор
17.04.2015 19:28-7Не при чем. При чем тут авторы git, которые поленились организовать более подробный вывод ошибок.
Вот одна из частых ошибок:
fatal: The remote end hung up unexpectedly
Сообщение от капитана Очевидность. А можно было бы хотя бы указывать в процессе какой операции удаленный конец оборвал соединениеploop
17.04.2015 20:03+2Полагаю, что 'No space left on device' уже системное сообщение, git его просто перебросил.
Да не суть — выскочить могла любая программа. При чём молча.LuckySB Автор
17.04.2015 20:31-2вот именно!
Вот к этому — «просто перебросил» — и есть основная претензия.
unix way — три-четыре утилиты перебросили системное сообщение — в итоге теряется контекст и оказывается, что вам показывают ошибку, которая слабо коррелирует с исходной командой.
И приходится писать вот такие мелкие постики, просто для того, чтобы сохранить информацию вида «а вы выключатель в шкафу поищите»
Чтобы в следующий раз проблему решило быстрое гугление, а не вдумчивое чтение исходников gitploop
17.04.2015 21:06+2unix way — три-четыре утилиты перебросили системное сообщение — в итоге теряется контекст и оказывается, что вам показывают ошибку, которая слабо коррелирует с исходной командой.
Так он же перед этим явно сказал, что ошибка возникла при записи в stdout. Ошибка такая-то, и выдал системную, что уже заставляет задуматься (что вы и сделали).
Ну как вот вы, на месте разработчиков гита, разрулили бы такую нестандартную ситуацию? Стали оборачивать обработчиками исключения каждое конкретное обращение к stdout, или всё-таки каким-нибудь базовым классом обошлись?LuckySB Автор
20.04.2015 14:31я не силен во внутренних алгоритмах гита, и читать исходники у меня времени нету.
но просто предположение:
git вызвал что-то типа patch file /dev/null
patch попытался записать в свой stdout, который на самом деле направлен в ФАЙЛ /dev/null
на разделе, занятом на 100%
а ошибка-то про запись в stdout. не надо обрабатывать исключения, достаточно вывести команду, которая вернула ошибку. Было бы намного информативнее.
ploop
20.04.2015 14:43+1Да я тоже не силён в них, просто предполагал. Понимаете, практически любой мало-мальски сложный код можно улучшить. Всегда. И заниматься этим можно до бесконечности. Думаю, у разработчиков гита есть более важные проблемы, которые надо решать, а не предусматривать все мыслимые и немыслимые варианты работы в хаотичном окружении.
grossws
18.04.2015 04:02+3А что
git fetch ... >/dev/null
, например, должен был бы вывести? Откудаgit fetch ...
может узнать куда перенаправили stdout?Power
18.04.2015 17:04Теоретически, он мог бы посмотреть на /proc/self/fd/1. Но это может быть не очень кросс-платформенно.
grossws
18.04.2015 19:56+1Оно, конечно, есть на linux. На freebsd, вроде, есть /proc/curproc. На mac os x procfs нет, на win — тоже.
Главный вопрос в том, зачем все эти сложности? Защититься от кого-то, который не смонтировал devfs? А если это было через неименованный pipe? Ошибка станет понятнее?
kahi4
17.04.2015 16:38+4«Клонирование того же репозитория на этот же сервер в другой каталог проходило без проблем.»
Эта цитата противоречит причине возникновения ошибки.LuckySB Автор
17.04.2015 19:14Вот именно. Противоречит.
Но так было.
Единственно, что могу предположить, ошибка происходила в момент изменения рабочего дерева.
А при клонировании с нуля файлы сразу создавались в последней версии.
maximw
17.04.2015 18:59+9Можно было придумать более «кричащий» заголовок.
Как забить под завязку /dev/null
Что если /dev/null «отправить в /dev/null»
Git! А теперь когда вы обратили внимание, /dev/null бывает не создано.LuckySB Автор
17.04.2015 19:31Извините. я в начале попытался объяснить суть названия.
Если переимновать ее в
«Работа с сообщениями об ошибках — git»
Будет не слишком кричаще?
А как насчет тяжеловестности и сложности для восприятия?maximw
17.04.2015 20:17+8Да не, это вы извините. Это был юмор, сарказм.
Я вообще не стал бы публиковать такой пост.
amarao
Вы устройство руками создавали? Ошибка.
Правильно:
mount|grep '/dev'
udev on /dev type devtmpfs (rw,relatime,size=1994644k,nr_inodes=206376,mode=755)
А /dev/null вам не «удалили», а «не создали» в процессе запуска контейнера/докера/mountnamespace'а/etc.