Принудительное извлечение дисков во время сна Мака: продолжение истории

Недавно мы подняли волнующую многих пользователей Mac OS X тему — проблемы с режимом сна, вызванные внешними USB-устройствами (особенно внешними HDD). С сожалением пришлось констатировать, что Mac OS X сама по себе ничего с этим сделать не может — в системе даже нет возможности разрешить или запретить вывод компьютера из режима сна для отдельных устройств, существующие опции касаются только пробуждения по сети и с помощью Bluetooth-периферии.

Один читатель обратил внимание на утилиту Jettison, которая, по идее, решает все сложности. Перед засыпанием компьютера она принудительно отключает все диски, а при пробуждении монтирует обратно. Но у Jettison нашлось три недостатка:

  • утилита стоит два доллара
  • она бывает крайне неповоротливой, иногда тормозя пробуждения компьютера на 5-10 секунд
  • она срабатывает далеко не всегда

Последние два недостатка вынудили автора этого материала поискать более разумные решения. О том, что нашлось в итоге, я хотел бы рассказать вам в этой статье.

Я несколько лет пользовался хакинтошем, отложив покупку домашнего десктопного Мака на будущее. Недавно это будущее настало — казалось бы, переход на настоящий Мак с его кустарного подобия должен доставлять исключительно положительные эмоции, но не тут-то было. Как ни странно, но с настоящим Маком проблем оказалось больше, чем с хакинтошем! :) Наиболее назойливыми оказались две — подбор ИБП (но об этом лучше поговорить отдельно) и проблемы с режимом сна.

Внешний HDD от Seagate, подключённый к Маку, стабильно портил режим сна. Через 90 секунд после засыпания iMac просыпался, а на рабочем столе красовалось сообщение о том, что диск был извлечён ненадлежащим способом:

Установка дополнительных драйверов от Seagate ситуацию не улучшила, напротив, проблемы со сном никуда не делись, зато при включении и перезагрузки Мак стал по 40 секунд отображать белый экран (к слову, на саму загрузку системы он тратит 8 секунд :). В общем, стало ясно, что проблема связана с самой Mac OS X и особенностями её работы с USB 3.0.

Упомянутая выше утилита Jettison лестных отзывов тоже не заслуживает. С ней бессонница Мака прекратилась, однако после пробуждения по-прежнему регулярно появлялась ошибка некорректного извлечения диска.

Альтернативный способ решения вопроса нашёлся достаточно быстро. Им оказалась утилита sleepwatcher — мощное средство, которого крайне не хватает в OS X. Это утилита для командной строки, которая позволяет запускать любые скрипты в момент засыпания и пробуждения Мака. Ставится она следующим образом:

  • качаете архив отсюда и распаковываете его на рабочий стол
  • запускаете Терминал и последовательно вводите команды, после каждой нажимая Enter (после первой надо будет ввести пароль вслепую):

sudo -s
mkdir -p /usr/local/sbin /usr/local/share/man/man8
cp ~/Desktop/sleepwatcher_2.2/sleepwatcher /usr/local/sbin
cp ~/Desktop/sleepwatcher_2.2/sleepwatcher.8 /usr/local/share/man/man8
cp ~/Desktop/sleepwatcher_2.2/config/de.bernhard-baehr.sleepwatcher.plist /Library/LaunchDaemons

  • теперь система получит поддержку скриптов rc.sleep и rc.wakeup, которые надо будет положить в папку /etc/. Первый скрипт будет выполняться при каждом засыпании, второй — при каждом пробуждении
  • давайте заставим Mac OS X принудительно извлекать нужный нам диск перед засыпанием. Если на извлекаемом диске только один раздел, создайте текстовый файл и скопируйте туда следующий шаблон:

#!/bin/sh
diskutil unmount -f /dev/disk3s2

  • /dev/disk3s2 надо заменить на идентификатор раздела на извлекаемом диске. Узнать его можно, если вы введёте команду diskutil list в Терминале — вы увидите полный список всех дисков и разделов с их идентификаторами
  • отдельной ремарки заслуживает параметр -f в команде выше. Он отвечает за принудительное извлечение. Оно происходит быстро, но оно опаснее, чем традиционное извлечение (без этого параметра) — если с диском в момент извлечения велась какая-то работа, сохраняемые файлы могут быть повреждены
  • сохраните файл на рабочем столе под именем rc.sleep (без расширения, это важно!)
  • затем создайте ещё один текстовый файл, скопируйте туда:

#!/bin/sh
diskutil mount /dev/disk3s2

  • здесь так же замените идентификатор диска на ваш. Сохраните файл на рабочем столе под именем rc.wakeup
  • если же на извлекаемом диске у вас несколько разделов, понадобятся другие команды: diskutil unmountDisk force /dev/disk3 и diskutil mountDisk /dev/disk3 соответственно. Обратите внимание, что вместо идентификатора раздела (disk3s2) в данном случае вводится идентификатор самого диска (disk3). Они разом извлекут все разделы на вашем внешнем диске, а потом примонтируют их обратно
  • после того, как ваши скрипты готовы, остаётся залить их в папку /etc:

mv ~/Desktop/rc.sleep /etc
mv ~/Desktop/rc.wakeup /etc

Вот и всё, остаётся проверить работоспособность созданных вами скриптов, перезагрузившись и отправив Мак в режим сна.

Допускаем, что на вашем внешнем HDD этот трюк может не сработать. На этот случай есть куда более радикальное решение — выгружать перед режимом сна драйвер, отвечающий за скоростную шину USB. Это делает команда:

kextunload -q /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBXHCI.kext

Её вы можете добавить в rc.sleep ПОСЛЕ строки с diskutil. Обратной по назначению будет команда:

kextload -q /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns/AppleUSBXHCI.kext

Её надо будет добавить в rc.wakeup ДО строки с diskutil.

Опять-таки, не можем гарантировать, что это сработает с любым внешним диском.

Чтобы отредактировать созданные скрипты rc.wakeup и rc.sleep, используйте команду sudo nano /etc/rc.wakeup (либо sudo nano /etc/rc.sleep). После того, как вы отредактируете скрипт, нажмите на клавиатуре Ctrl+X, затем Y, наконец — Enter.

P.S. Кстати, на форумах Apple есть немало критики в адрес OS X Mountain Lion и USB 3.0. Проблемы действительно распространены, и они не решены ни в OS X 10.8.1, ни в OS X 10.8.2. Можете попробовать обновиться на бета-версию OS X 10.8.3, где USB-драйверы были обновлены — возможно, ситуация улучшится.