Что вы делаете, если не можете устранить ошибку?
У вас когда-нибудь была ошибка в вашем коде, которую вы не могли устранить? Я надеюсь, что я не единственный, кто сделал этот опыт...
Существует несколько классов ошибок, которые очень трудно отследить:
- ошибки, связанные с синхронизацией (например, возникающие во время межпроцессного взаимодействия)
- ошибки, связанные с памятью (я думаю, большинство из вас знает соответствующие примеры)
- связанные с событиями ошибки (трудно отлаживать, потому что каждая точка останова, с которой вы сталкиваетесь, делает вашу IDE целью для событий отпускания / фокусировки мыши...)
- ОС-зависимые ошибки
- аппаратно-зависимые ошибки (возникают на компьютере, на котором была выпущена версия, но не на компьютере разработчика)
- ...
Если честно, время от времени мне не удается самостоятельно исправить такую ошибку... После отладки в течение нескольких часов (а иногда даже дней) я чувствую себя очень деморализованным.
Что вы делаете в этой ситуации (не обращаясь к другим за помощью, что не всегда возможно)?
Вы
- используйте карандаш и бумагу вместо отладчика
- столкнуться с другой вещью и вернуться к этой ошибке позже
- ...
Пожалуйста, дайте мне знать!
32 ответа
Некоторые вещи, которые помогают:
1) Сделайте перерыв, подойдите к жуку под другим углом.
2) Становитесь более агрессивными с отслеживанием и регистрацией.
3) Посмотрите на него еще парой глаз.
4) Обычным последним средством является выяснение способа сделать ошибку несущественной, изменив основные условия, в которых она возникает.
5) Разбивать и ломать вещи. (Только для снятия стресса!)
Однажды я работал в компании, которая продала клиент-серверное приложение, которое было в основном средством передачи файлов и синхронизации. И клиент, и сервер были разработанными нами приложениями.
У нас была постоянная ошибка, которую было очень трудно воспроизвести в лаборатории. Наш сервер может обрабатывать только определенное количество входящих клиентских подключений на один блок, поэтому многие наши клиенты будут "кластеризовать" несколько серверов вместе для обработки большого количества пользователей. Внутренние данные для кластера находились на файловом сервере, которым они все поделились. В этой конфигурации кластера была ошибка, которая могла произойти под нагрузкой, когда мы получали низкоуровневый код ошибки файловой системы при вызове совместного доступа к файлу, включающему один из внутренних файлов. Никто не мог заставить это повторить достоверно в лаборатории, и даже когда они могли, они не могли сузить, что происходило.
(Забыл точную ошибку, наверное 59 ERROR_UNEXP_NET_ERR
или, может быть 65 ERROR_NETWORK_ACCESS_DENIED
, Насколько я помню, это был даже не один из документированных кодов ошибок, которые вы должны были получить из API, который мы вызывали (обычно это был вызов блокировки или разблокировки для раздела файла).
Так как это включало связь между сервером и внутренним хранилищем файлов, а я был "сетевым транспортным парнем", мне было поручено посмотреть на него. Многие другие смотрели на это безуспешно.
Единственное, что у меня было, было то, что я знал, где в коде обнаруживается ошибка, но не знал, что с этим делать. Поэтому мне нужно было найти основную причину. Поэтому я настроил подходящее аппаратное окружение для его дублирования и поместил пользовательскую сборку серверного программного обеспечения, которая инструментировала данный раздел кода.
Инструментарий был следующим: я добавил тест для проблемного кода ошибки и заставил его вызвать фрагмент кода для отправки пакета UDP по заранее определенному сетевому адресу при возникновении ошибки. Пакет UDP содержал уникальную строку для включения.
Затем я установил пакетный анализатор в сети. (В то время я использовал Microsoft Network Monitor). Я разместил его там, где он мог бы "видеть" этот пакет UDP, когда он был отправлен, а также всю связь между серверами кластера и файловым сервером.
У большинства хороших анализаторов есть режим, в котором вы можете захватить его, пока он не увидит определенный фрагмент трафика, а затем остановиться. Я включил этот режим и настроил его на поиск того UDP-пакета, который отправит мой код. Цель состояла в том, чтобы получить пакетный захват всего трафика файлового сервера непосредственно перед тем, как произошла ошибка. Самые последние сетевые пакеты в систему и из системы, в которой были созданы UDP-пакеты, вероятно, будут большим ключом к пониманию того, что происходит.
Я настроил конфигурацию "стресс-теста" и поехал домой на выходные.
Когда я вернулся в понедельник, вот, у меня были мои данные. Сниффер остановился, как и ожидалось, после многих часов бега и содержал захват. После изучения перехвата я обнаружил, что соединение между блоком сообщений сервера или SMB (он же CIFS или SAMBA) между нашим сервером и файловым сервером фактически истекло на уровне TCP из-за чрезмерной нагрузки на сервер. Поскольку весь материал Microsoft сильно наслоен, он будет перетекать обратно через стек обмена файлами как "неожиданную" ошибку, а не возвращать более понятный код ошибки, который говорит "эй, вы потеряли свое соединение на уровне TCP".
Я немного больше изучил настройки TCP для Windows, и вот, настройки по умолчанию для той версии Windows, которую мы использовали (вероятно, NT 4 в ту эпоху), не были слишком щедрыми. Это позволяло только очень небольшое количество сбоев в соединении TCP и бум, вы были мертвы. После того, как вы потеряли SMB-соединение с файловым сервером, все ваши файловые блокировки были полностью восстановлены, и восстановить их было невозможно.
Поэтому я закончил тем, что написал приложение к руководству пользователя, в котором объяснялось, как изменить настройки TCP в Windows, чтобы сделать кластерный сервер более терпимым к ситуациям с высокой нагрузкой. И это было все. Исправление ошибки - нулевое изменение в коде, просто дополнительная документация о том, как правильно настроить ОС для использования этим продуктом.
Что мы узнали?
- Будьте готовы запустить измененные версии вашего кода, чтобы исследовать проблему
- Подумайте об использовании нетрадиционных инструментов для решения проблемы (снифферы)
- Не все исправления ошибок требуют изменения кода
- Иногда вы можете диагностировать ошибку, находясь дома с пивом
Я делаю много разных вещей:
выкинь все мои предположения и начни с нуля. Помните, что ошибка существует, потому что что-то, что кажется правильным, на самом деле неправильно. Даже те строки, функции или классы, которые вы абсолютно уверены в правильности, могут быть неверными. Пока вы не сможете убедить себя в правильности, вы не можете предполагать, что все правильно.
продолжайте печатать заявления и утверждать заявления, чтобы устранить вещи и позволить мне изменить новые предположения.
пошаговое выполнение кода в отладчике, если проблема связана с потоком управления. Не переступайте через функции. Вступите в них и просмотрите все детали их исполнения, чтобы подтвердить, что они работают правильно. Подтвердите аргументы и верните значения.
Если строка, функция или класс являются подозрительными, но я не могу доказать это на месте, тогда напишите небольшой тестовый пример, который делает то, что, по вашему мнению, делает конструкция проблемы. Это может найти проблему или дать некоторое представление о том, где искать дальше.
остановись на день. Удивительно, какую автономную обработку ваш мозг сделает за одну ночь. Часто ответ или ключевое понимание появляются на следующий день, когда я делаю что-то бездумное, например, принятие душа или вождение.
Создать автоматизированный способ вызвать ошибку. Худшая ошибка, которую нужно исправить, - это та, которая воспроизводится часами.
Цитата взята из "Криптономикон":
"Интуиция, как вспышка молнии, длится только секунду. Обычно она возникает, когда человек мучается трудной расшифровкой, и когда кто-то вспоминает бесплодные эксперименты, которые он уже пытался предпринять. Внезапно свет прорывается, и после нескольких минут, что не могли показать предыдущие дни труда ".
Я обычно прошу кого-то еще взглянуть на код. Хотя я объясняю, что должен делать код, я иногда вижу ошибку, когда говорю.
Когда ошибка трудная, я сижу и работаю, пока не выясню и не решу проблему. Интересно, что бывают случаи, когда ловить таинственную ошибку приятнее, чем все, что происходит гладко. И облегчение и чувство, когда ошибка устранена, ну, не так много других может победить это (кроме очевидных).
Если ничего не помогает, не занимайтесь этим напрямую. Перепишите код проблемной зоны более реорганизованным способом.
У меня определенно были ошибки, над которыми я работал 4-5 дней непрерывно, прежде чем нашел решение. Другие ошибки сидели в баг-трекере месяцами, как я потратил на это несколько часов в течение длительного периода времени. Я думаю, что такого рода ошибка неизбежна в любом сложном программном проекте.
Некоторые вещи, которые хорошо работают для меня:
- бинарный поиск по потоку программ с регистрацией
- использование
Trace
заявления вместе с DbgView для поиска ошибок, которые появляются в режиме выпуска - найти альтернативный способ воспроизвести ошибку без изменения кода
- (работает против логики, но...) изменить код так, чтобы ошибка была более легко воспроизводимой (условие отказа легче достигается)
- спать на нем и попробуйте завтра со свежими глазами:)
На мой взгляд, худшая ошибка - это ошибка параллелизма, которая исчезает при вставке логирования.
Здесь много хороших ответов. Одна вещь, которая работала для меня в прошлом, это спросить: "Что я могу сделать, чтобы сделать это совершенно очевидным, когда эта проблема возникла?".
Например, если проблема заключается в поврежденном значении в структуре данных, попробуйте создать подпрограмму проверки согласованности, которую можно периодически запускать. Также рассмотрите возможность реализации всего доступа к общим данным через набор функций, которые регистрируют каждое изменение.
Или, если проблема заключается в "случайной" перезаписи памяти, используйте замену реализации malloc()/free(), которая перехватывает запись в "свободную" память (например, Electric fence или dmalloc).
Кто-то еще упомянул об автоматизации процесса запуска ошибки. Это здорово, если ты можешь это сделать. Даже рутина, которая выполняет программу случайным образом, может помочь в этих случаях.
У меня были ошибки, на которые ушли недели или месяцы, прежде чем было найдено решение, но в итоге все ошибки были исправлены. Помимо классических методов отслеживания ошибок без отладчика, таких как отключение частей системы, пока вы не получите минимальный тестовый пример, я использовал следующие методы:
В поисках лучших инструментов отладки. Новая перспектива имеет большое значение. Xdebug - это то, что я начал использовать в PHP только из-за ошибки производительности, о которой я не говорил заранее.
Изучение технологии, в которой находится ошибка. Это помогло отладить надстройку Outlook. У него были случайные ошибки, которые не имели никакого смысла, и поиски в Google обернулись. Изучив лучшие практики надстроек в Outlook, программирование COM и MAPI, мы получили более четкое представление о том, что может пойти не так, и подумали о новых вещах, чтобы попытаться исправить ошибки, которые в конечном итоге их и исправили.
Пытаюсь обострить проблему. Если есть проблема, которая возникает только изредка, я постараюсь найти способы, чтобы это происходило постоянно. Это помогло отследить ошибки в веб-приложениях под IE, а также сузить ошибку в плагинах Flash.
Когда ничего не помогло, я переписал подсистему, которая вызывала проблемы с нуля. Это может занять несколько дней или даже недель, но если вы застряли на ошибке и не можете ее устранить, а клиенты не ответят "нет", что еще вы можете сделать? Это не всегда исправляет ситуацию, но если это не так, вы обычно получаете более четкое представление о том, что происходит не так.
Я заметил несколько общих черт в этих ошибках, которые застряли на несколько недель:
Обращение к сторонним организациям за помощью редко помогает, и, как правило, не стоит ждать, пока кто-нибудь еще придет, чтобы спасти этот день.
Почти всегда ошибка заключается в какой-то сторонней технологии с закрытым исходным кодом, особенно при использовании неясных деталей. У IE были неприятные ошибки при попытке использовать клиентские сертификаты. Flash плохо справлялся со случайно сгенерированными инструкциями рисования (некоторые из которых были бессмысленными). Outlook не нравится, когда вы пытаетесь динамически изменить макет формы из кода. В эти дни я научился уважать "зоны комфорта" проприетарных технологий.
"Что вы делаете в этой ситуации (не обращаясь к другим за помощью, что не всегда возможно)?"
Когда невозможно обратиться за помощью?
Всегда есть другие люди, к которым вы можете обратиться за помощью - ваши коллеги, ваш начальник, друзья здесь, в Stack Overflow и т. Д.
Понимание того, когда обращаться за помощью, не должно быть деморализующим!
Здесь много хороших советов.
Я абсолютно не согласен с концепцией изменения кода в надежде, что он исчезнет. Во-первых, вы, вероятно, собираетесь представить новые ошибки. Секунды, вы можете легко изменить вещи настолько, чтобы скрыть ошибку, только чтобы она снова появилась в следующем патче.
Ошибки с повреждением памяти особенно вероятно исчезают так же волшебно, как и появляются. Тем не менее, ошибка повреждения памяти не исправлена, это только то, что нефатальные области памяти попадают в мусор.
1) Попробуйте другой отладчик. Например, я использую WinDbg все чаще и чаще. Когда вы загружаете программу в отладчике, структура памяти вашего приложения будет немного меняться. Возможно, другой отладчик приводит к тому, что ошибка проявляется немного по-другому.
2) Если вы прибегаете к изменению кода, не зная точно, в чем проблема, то, если ошибка исчезает, ВЫ ДОЛЖНЫ вернуться и понять, почему изменение исправило ошибку. В противном случае вы, вероятно, просто скрываете ошибку.
3) Поговорите с другими об ошибке, возможно, они видели разные версии одной и той же проблемы (то есть другие способы ее воссоздания).
4) Ведение журнала.
Я даю ему больше времени. Однажды у меня была ошибка (в личном проекте), которую я просто не мог понять. Я пробовал все методы отладки, в том числе и Google, но безуспешно. Через полгода я вернулся и обнаружил ошибку в течение часа или около того. Это не было чем-то простым (что-то явно недокументированное происходило глубоко внутри Swing), но я просто смотрел на это так, как раньше.
Шутки в сторону? Я делаю вещи в таком порядке.
- Пойти спать
- Спроси коллегу
- Перепишите, чтобы область не была затронута.
- Спросите ТАК
- Получите билет поддержки у вашего стороннего поставщика библиотеки.
Я тоже немного деморализован, когда не могу решить ошибку. Обычно, когда я врезаюсь в стену с ошибкой, я просто принимаю к сведению мои выводы и прекращаю работать над ней. Я бы вскочил на другую ошибку, которую легче решить, а затем вернулся к ошибке. Делая это, у меня был бы свежий ум и отношение к решению проблемы. Иногда вы можете иметь тенденцию слишком усложнять вещи, когда тратите слишком много времени на ошибку. Имея перерыв, помогает сломать стену.
Нет ошибки, которую нельзя исправить, так как нет ошибки, которая не может быть исправлена с помощью полной перезаписи.
Неисправимая ошибка - это просто ошибка, которую вы не хотите заменить.
Я, честно говоря, не могу вспомнить ошибку, которую не смог исправить. Это может вызвать много рефакторинга, или может занять некоторое время, но у меня никогда не было того, от чего я не могу избавиться. Если мне требуется больше часа, чтобы выследить это, то это почти всегда что-то действительно глупое и маленькое, как если бы я смотрел мимо :
это должно было быть ;
, так далее.
В Python, если я использую редактор, который не мой, или, возможно, это чужой код, я использую retab!
в vim или вставьте что-то вроде pastie, чтобы проверить отступ (если у меня нет vim).
Если это не крушение / нарушение условий сделки, тогда я продолжаю и возвращаюсь свежим взглядом.
О, и вы никогда не сможете получить слишком много записей.
Я рассмотрел вопрос о помощи на этом сайте под названием Stackru, который я часто посещал в последнее время...
Я добавляю как можно больше отладки (запись в файл журнала, окна сообщений и т. Д.) И тестирую.
Я не думаю, что это худшая ошибка, которую вы можете найти. Худшими являются те, которые вы не можете воспроизвести детерминистически или в среде тестирования.
У меня была эта проблема раньше, я думаю, что у всех есть, я отказался от нее раньше, ее было просто невозможно найти, но она продолжала падать, когда в коде была какая-то ошибка, я просто садился и концентрироваться на каждом кусочке кода понемногу, пока я его не найду, это сложно и требует терпения, но это все, что вы можете сделать в такой ситуации.
Надеюсь это поможет.
Я обычно стараюсь изо всех сил, решая это. Но, если это невозможно в течение разумного периода времени, я оставляю это на некоторое время мозговым органам, чтобы решить это, пока я сплю;) Иногда это работает...
Это то, что я сделал сегодня...
Я отлаживаю взаимодействие HW/SW, и часто его регистрация (изменение инструментов) изменяет или скрывает ошибку. Следовательно, тесты выполняются "на скорости". Я называю этих жуков "тараканами", потому что они убегают от любого света, который я могу им светить.
Так что я должен:
Найдите транзакцию, которая вызывает ошибку. Перечислите взаимодействие HW с помощью регистрации (этот тест проходит, но он иллюстрирует поток).
Инструмент до и после ошибки, чтобы напечатать изменения состояния.
Конечно, ошибка, которую я сейчас решаю, наихудшая, поскольку HW блокируется. HW включает в себя процессор, так что он как будто находится в хорошо освещенной комнате, после чего происходит сбой питания и его черная смола.
У меня есть особый бэкдор в память, но, конечно, это также заперто. Я попытался выключить и включить питание в надежде, что память останется энергонезависимой достаточно долго, чтобы снова включить черный ход. Нет такой удачи. Это возможно, хотя.
Я очень очень тщательно написал все шаги, которые я прошел, чтобы охарактеризовать эту ошибку (что работает, что не работает и т. Д.). Отправил это разработчикам с похожим HW, чтобы убедиться, что это был не я или мой HW.
Я взял несколько часов перерыва, чтобы дать этой информации понять и посмотреть, не зажгутся ли какие-либо лампочки в других местах.
Нет ответов, эта ошибка моя, чтобы решить...
Это взаимодействие HW SW представляет собой цикл, который выполняет некоторую настройку, затем входит в цикл опроса, который считывает, когда транзакция завершена. Много транзакций должно произойти. Какая транзакция не проходит? Это первый (указывает на то, что я могу отладить транзакцию, а не какой-то шум в HW). Это всегда N-ая транзакция? Чем N-й отличается от первого или (N-1) -ого. ПО является однопоточным и построено так, чтобы быть предсказуемым. Без прерывания, без прерываний.
Этот SW работал раньше, что нового? Все HW новое. В этом случае весь кремний является новым ASIC. Даже встроенный процессор является новым и настроенным, поэтому ISA является новым.
Так что я все подозреваю и я слепой. Мне придется подкрасться к этой плотве.
Я включил только журнал, который сообщает, сколько раз ПО опрашивает HW для завершения. Таким образом, первая транзакция выполняется с высокой скоростью, и я понимаю, как часто я касаюсь HW в узком цикле опроса. Тест проходит. Я знаю, что это N-я транзакция, и я записал пиковое количество опросов для всех транзакций (возможно, бессмысленные данные).
После внесения каких-либо изменений я должен вернуть его обратно, чтобы убедиться, что ошибка все еще существует. Ведь Земля вращается и солнечные ветры не так сильны;)
Посмотрел все проверки, увидел, как подрядчик изменил некоторые важные параметры настройки без объяснения причин. Эти (внешние) люди все еще находятся на стадии оценки. Это не поможет.
Обнаружено, что в цикле опроса не было спинвейта. Плохо для таймаута цикла, так как без него тайм-аут зависит от скорости процессора. Добавлен спинвейт, еще нет счастья.
Ограничено количество транзакций, чтобы увидеть, где он терпит неудачу, где-то до 1000.
Настройте HW на медленную работу, все еще зависает.
Ненавижу оставлять кого-нибудь, кто читает это повешение, но эту диатрибу придется подождать до завтра.
Во-первых, это воспроизводимо? Это ОГРОМНЫЙ плюс, если это так. Я хочу, чтобы ошибки всегда были / никогда не возникали... это прерывистые проблемы.
И это будет зависеть от проблемы, но в моем магазине мы, как правило, помечаем такую команду, считая, что 2 головы (или 3 или 4) лучше, чем 1.
Иногда ошибка даже не будет в МОЕМ коде, но обычно это так. Были проблемы, когда сторонняя библиотека была виновником или причиной была конкретная реализация на конкретной платформе - эти воняли.
Я буду использовать все и вся, чтобы хотя бы отследить это: отладчики, вывод трассировки, что угодно.
Как правило, если я могу изолировать его от класса или модуля, я напишу тестовый комплект для дублирования реального мира и попытаюсь скопировать его там. Обычно я сначала пишу свой тестовый код, но иногда существует устаревший код (или код другого разработчика), у которого уже нет тестов.
Я обычно буду обсуждать дизайн и проблемы, вслух с командой и доской все, что не ясно. Часто решение всплывает на поверхность, когда мы говорим об этом как о группе.
Это то, чем я занимаюсь.
Если ошибка настолько неуловима, что на ее обнаружение уходит более трех дней, то обычно я меняю дизайн, потому что основной смысл поставки программного обеспечения не вызывается три года спустя для его отладки, поэтому чем проще взаимодействие между компонентами, лучшее.
В дополнение к отладчику я также использовал журналирование и старомодную бумагу и карандаш. Иногда я обнаруживал действительно серьезные ошибки, например, код, который отлично работает в режиме отладки, но не работает в режиме выпуска. Я даже иногда переписывал совершенно хороший код, который по какой-то причине не работает надежно, полагая, что лучше быть надежным, чем элегантным.
Иногда я пытаюсь переопределить то, что другие называют ошибкой, в действительности являющейся функцией, но это редко работает!
Для ошибок, связанных с памятью, я обнаружил, что опции профилирования памяти Ants Profiler помогли мне найти ошибки.
У меня есть ошибка, которая появляется каждые несколько месяцев на сайте клиента. Обычно это происходит в 3 часа ночи и не обнаруживается до раннего следующего утра, когда клиент прибывает на сайт. И обычно, когда они обнаруживают это, они хотят, чтобы все сразу заработало, поэтому сотрудники нашей службы поддержки обычно просто перезагружают компьютер. Это сводило меня с ума в течение многих лет. Это никогда не происходит на моей тестовой машине или в лаборатории контроля качества, только на определенных сайтах клиентов. Со временем я
- переработал часть кода, который, как я думал, вызывал его
- добавлено больше отладочных распечаток, где, кажется, происходит сбой
- перенаправил стандартный вывод, чтобы в следующий раз я смог это увидеть
kill -3
" процесс - предоставлена поддержка некоторых новых инструментов для снятия текущего состояния блокировок базы данных и тому подобного.
- добавлена диагностика, чтобы сделать это более очевидным, когда это произойдет
Это не произошло в течение нескольких месяцев, и я скрестил пальцы, чтобы исправить это на этот раз, но я не рассчитываю на это.
Я считаю, что детальное ведение журналов имеет решающее значение для выявления ошибок такого рода, которые "периодически" на вашей рабочей машине, но которые вы не можете воспроизвести на своей машине разработчика из-за различий в среде и нагрузке на машину.
Поэтому, когда я нажимаю один из них и не могу воспроизвести / исправить его в разумные сроки, я насыщаю потенциальные области кода сообщениями журнала и позволяю ему работать в рабочей среде, пока это не произойдет снова - и, надеюсь, у меня будет достаточно информации в журналы, чтобы указать мне в правильном направлении.
Другие методы, которые могут или не могут быть доступны вам в вашей производственной среде, - это включить "удаленную отладку", чтобы вы могли фактически отлаживать код из процесса, запущенного в вашей производственной среде, - это очень удобно, если вы можете использовать его.
Использовать более креативные методы отслеживания ошибок.
используя удаленную отладку на машине, где его можно воспроизвести.
используя инструменты профилирования.
ввести больше регистрации в приложении.
Уходить на некоторое время, а затем возвращаться к проблеме - это один из распространенных подходов, которые я слышал.
Насколько легко воспроизвести ошибку, также может быть фактор, поскольку ошибка возникает только в одном из миллиардов запусков программы, что можно считать незначительным преимуществом для исправления ее путем поломки чего-то другого.
Существует также вопрос о том, где найти ошибку, в какой-то конфигурации, чтобы она возникала на сервере, а не на моей локальной машине XP Pro, на которой работает IIS 5.0. Некоторые другие ошибки могут включать необходимость изменить разрешение моей машины, что может раздражать, чтобы попытаться воспроизвести ошибку, о которой сообщали другие.
Вы исключили ошибку "встречается под другим O/S", так что веб-страница, хорошо работающая в IE и Firefox на ПК, может выглядеть как чушь в Safari на Mac. Могу ли я испачкать руки, пытаясь решить проблему с CSS, используя мою машину в качестве сервера и Mac, который находится над рядом или двумя рядами в полу, чтобы увидеть эту проблему, или это настолько низкий приоритет, который он получает? подмести? В качестве альтернативы, если в Linux была ошибка и рядом со мной нет машин Linux, что мне делать?
Извините, что ушел с некоторыми вопросами, но иногда они кажутся мне сложными.