Debian Buster, SecureBoot и Nvidia RTX 2070
Условия задачи
Дано:
- Ошибка Xorg в логах:
May 7 16:21:42 darktower kernel: [ 5.572986] Lockdown: ioperm is restricted; see https://wiki.debian.org/SecureBoot - Debian 10 Booster с подключенными репозиториями
non-freeиcontrib. - Права
root - Видеокарта NVidia RTX 2070
- Компьютер с включенной в настройках материнской платы опцией
SecureBoot (EFI)
Проблема в том, что в ряде случаев видеокарта может не запускаться, потому что драйверы не подписаны. Для подписания драйверов следует выполнить действия, описанные в Wiki Debian / SecureBoot.
В моём случае пришлось выполнить следующую последовательность действий:
Установка драйвера Nvidia, исходных кодов ядра и mokutil
apt-get update
apt-get install nvidia-driver nvidia-xconfig linux-headers-amd64 mokutil
| Пакет | Предназначение |
|---|---|
| nvidia-driver | Проприетарный драйвер Nvidia с поддержкой нужных моделей видеокарт. |
| nvidia-xconfig | Утилита конфигурирования параметров Xorg для поддержки им нужных драйверов. |
| linux-headers-amd64 | Исходные коды установленного ядра. |
| mokutil | Утилита для работы с ключами EFI |
Генерация ключа EFI, его установка и подписывание драйверов.
Теперь действуем ровно так, как написано в руководстве Debian'а:
# Генерация ключей и импорт в EFI
cd /root
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=NVidia RTX 2070 key/"
mokutil --import MOK.der
# Подписывание драйверов Nvidia
cd /lib/modules/4.19.0-8-amd64/updates/dkms/
/usr/lib/linux-kbuild-4.19/scripts/sign-file sha256 /root/MOK.priv /root/MOK.der nvidia-current-drm.ko
/usr/lib/linux-kbuild-4.19/scripts/sign-file sha256 /root/MOK.priv /root/MOK.der nvidia-current.ko
/usr/lib/linux-kbuild-4.19/scripts/sign-file sha256 /root/MOK.priv /root/MOK.der nvidia-current-modeset.ko
/usr/lib/linux-kbuild-4.19/scripts/sign-file sha256 /root/MOK.priv /root/MOK.der nvidia-current-uvm.ko
# Перенастройка Xorg под nvidia
cd /etc/X11
rm xorg.conf
nvidia-xconfig
Следует обратить внимание на путь, в котором расположены исходные модули ядра nvidia и скрипт для подписывания драйверов - они могут быть другими.
Перезагрузка
При перезагруке EFI выдаст сообщение, что появился запрос на установку собственного ключа цифровой подписи. Принимаем этот ключ и устанавливаем. После этого компьютер должен перезагрузиться и запустить установленный Linux, используя подписанные данным ключом драйверы. После этого запустится Xorg и всё будет нормально работать.
Автоматизация подписывания ключей.
Можно автоматизировать процесс по максимуму, если ручной выбор исходников ядра переключить на работу с результатами команды uname -r и поместить всё в файл скрипта:
#!/bin/sh
SIGN=/usr/lib/linux-kbuild-4.19/scripts/sign-file
MOK=/root/MOK.priv
DER=/root/MOK.der
cd /lib/modules/$(uname -r)/updates/dkms/
$SIGN sha256 $MOK $DER nvidia-current-drm.ko
$SIGN sha256 $MOK $DER nvidia-current.ko
$SIGN sha256 $MOK $DER nvidia-current-modeset.ko
$SIGN sha256 $MOK $DER nvidia-current-uvm.ko
Его нужно запускать всякий раз при обновлении драйвера Nvidia или ядра.
Ошибка "memmove does not exist on this platform"
Который раз вижу вот эту ошибку:
extensions/expat/lib/xmlparse.c:75:2: error: #error memmove does not exist on this platform, nor is a substitute available
Решение очень легко гуглится на StackOverflow, но для себя я решил сохранить, чтобы далеко не ходить. Проблема заключается в том, что в одном из заголовочных файлов Python 2.7 не определена константа HAVE_MEMMOVE
Решение
- Открыть файл /usr/include/python2.7/pyconfig.h
-
Добавить в его конец строку
#define HAVE_MEMMOVE 1
Послесловие: хватит уже пользоваться Python 2.7, Гвидо не для того старался с тройкой.
str object has no attribute _meta
Досадная ошибка, с которой пришлось столкнуться, вынесена в название статьи. Потратил два часа на поиски, просмотрел все файлы по нескольку раз - и ничего. Сегодня с утра (а утро вечера мудренее) обнаружил причину.
Было:class UserChangeForm(forms.ModelForm):
'''
Форма для обновления данных пользователей. Нужна только для того, чтобы не
видеть постоянных ошибок "Не заполнено поле password" при обновлении данных
пользователя.
'''
password = ReadOnlyPasswordHashField(
widget=forms.PasswordInput,
required=False
)
def clean_password(self):
return self.initial['password']
def save(self, commit=True):
user = super(UserChangeForm, self).save(commit=False)
password = self.cleaned_data["password"]
if password:
user.set_password(password)
if commit:
user.save()
return user
class Meta:
model = get_user_model()
fields = ('email')
Стало:
class UserChangeForm(forms.ModelForm):
'''
Форма для обновления данных пользователей. Нужна только для того, чтобы не
видеть постоянных ошибок "Не заполнено поле password" при обновлении данных
пользователя.
'''
password = ReadOnlyPasswordHashField(
widget=forms.PasswordInput,
required=False
)
def clean_password(self):
return self.initial['password']
def save(self, commit=True):
user = super(UserChangeForm, self).save(commit=False)
password = self.cleaned_data["password"]
if password:
user.set_password(password)
if commit:
user.save()
return user
class Meta:
model = get_user_model()
fields = ['email', ]
СУТЬ:
Если делаете перечисление полей в виде кортежа, после последнего элемента обязательно должна быть поставлена запятая. А лучше перечисляйте в квадратных скобках, как список - тогда точно не ошибётесь. Грабли, на которые наступают все новички, и я в том числе тоже.
Потенциальная возможность ошибки:class Meta:
model = get_user_model()
fields = ('email',)
Ошибки исключены
class Meta:
model = get_user_model()
fields = ['email']
Ошибка при запуске Eclipse Luna в Debian
Проблема
Я на работе окончательно переехал на Debian. После двух дней ненависти к Ubuntu понял, что лучше иметь старые проверенные пакеты, чем новые и постоянно глючащие. Как обычно, после установки системы поставил JRE:
apt-get update && apt-get install openjdk-7-jre -y
Скачал и распаковал последнюю стабильную версию Eclipse с официального сайта. Попробовал запустить:
./eclipse
Получил кучу ошибок, среди которых была такая: # C [libgdk-x11-2.0.so.0+0x5173f] gdk_display_open+0x3f.
Решение
Решение оказалось на редкость простым. Нужно импортировать в окружение переменную SWT_GTK3=0, тогда всё будет работать. Прописал в конце файла /etc/profile:
export SWT_GTK3=0
Чтобы не перезагружать систему, сделал то же самое для текущего пользователя, т.е. выполнил указанную выше команду. Всё работает!
Django и $resource
Суть проблемы
Решил использовать для реализации RESTful API своего приложения такой модуль Angular, как angular-resource. Проблем с установной и подключением, как обычно, не было. Создал свой сервис:
(function (A, U) { //U === undefined
"use strict";
A.module('DesktopApplication').factory('Category', function ($resource) {
var instance = {
selectedRow: U, //Используется в моём проекте для обмена данными между контроллерами,
//не является обязательным элементом
resource: $resource('/category/rows/:id', {id: '@id'})
};
return instance;
});
}(this.angular));
Казалось бы, всё должно работать. И ведь правда, вот такое работает (GET-запрос на получение данных):
//Где-то в коде, использующем сервис Category
Category.resource.query(function (items){
$scope.rows = items;
});
А вот такое уже нет:
//Чуть ниже
Category.save({'id': 4, 'name': 'Username'}, function (result) {
$scope.success = result.success;
});
Проблема оказалась в том, что даже явно указав слэш в конце строки ресурса, я получил POST-запросы, идущие к адресам без слэша, и Django такие запросы тут же банит. Начался поиск и чтение StackOverflow.
Решение
Решение оказалось довольно простым. Нужно указать в настройках приложения, что удалять концевой слэш для URL в AJAX-запросах не надо (а по-умолчанию включено). Кроме того, для корректной работы запросов методом PUT и DELETE нужно дополнительно конфигурировать $http. Иначе декоратор @csrf_protect из комплекта Django будет резать такие запросы. С учётом вышесказанного, скрипт настройки приложения стал выглядеть так (для сокращения размера выброшены прочие модули, которые я на самом деле использую в своём проекте):
(function(A) {
"use strict";
A.module('DesktopApplication', [ 'ngCookies', 'ngResource')
.config(function ($interpolateProvider, $resourceProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
$resourceProvider.defaults.stripTrailingSlashes = false;
})
.run(function ($http, $cookies) {
$http.defaults.headers.common['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
});
}(this.angular, this.jQuery));
Non Unicode character at position...
Введение
Как я уже писал ранее, моя компания использует множество проектов, написанных на Python. В качестве платформы для некоторых продуктов используется M3, построенная на основе популярного фреймворка Django. При первоначальной установке проектов на боевые сервера я столкнулся с тем, что при загрузке на сервер файлов, в имени которых встречается кириллица, система выдаёт невнятные сообщения. Оказалось, что проблема заключается в неправильной работе Python с кодировками, в которых хранятся имена файлов. В частности, от этого постоянно падали PIL и Pillow, а в некоторые разделы файлы не загружались вовсе.
В поисках решения
Первым делом я отправился в гугл, конечно же. Введя в поиск заголовок этой статьи, я наткнулся на кучу статей, в большинстве которых предлагались следующие варианты решения проблемы:
- Использовать в коде явное преобразование строк из одной кодировки в другую с помощью встроенных функций языка либо сторонних пакетов.
- Установить в систему нужные локали.
- Прописать настройки в конфигах Django.
- Перейти с этого вашего Python'а на PHP или Ruby On Rails.
Как выяснилось, ни один из этих путей не решает возникшую проблему, однако, второй пункт показался мне достаточно здравым.
Установка в систему нужных локалей.
При установке Debian 7 предлагается выбрать язык системы и кодировку по умолчанию. Если Вы указали свою национальную кодировку (уверен, меня читают не только жители России, но и других стран СНГ), можете этот пункт пропустить. Если же нет, то приступим к установке:
Первым делом следует войти в систему от имени root и выполнить команду по установке пакета управления локалями:
apt-get install locales
После установки этого пакета становится доступна следующая команда:
dpkg-reconfigure locales
Откроется окно, в котором нужно с помощью пробела отметить локали, которые следует держать в системе (можно выбрать вариант "Все локали", но я не рекомендую - чем меньше в системе лишнего, тем лучше). Я оставил там две локали: en_US.UTF-8 и ru_RU.UTF-8.
После нажатия кнопки OK будет предложено выбрать локаль по-умолчанию. Я использую ru_RU.UTF-8.
В самом конце система приступит к генерации недостающих локалей и их установке в систему.
Настройка окружения для работы Python
Как я писал в одной из статей, для запуска проектов на Python 2.x лучшим выбором является виртуальное окружение, созданное с помощью virtualenv, в которое установлен Gunicorn. При этом управление всем приложением осуществляется с помощью Supervisor'а. Здесь же сразу перейдём к делу.
Переходим в каталог настроек приложений Supervisor'а:
cd /etc/supervisor/conf.d/
Открываем файл настроек нашего приложения и приводим его к следующему виду:
[program:project]
environment=PROJECT_CONFIG_PATH="/var/www/project/conf/",DJANGO_SETTINGS_MODULE="project.settings",PYTHONIOENCODING="UTF-8",LANG="ru_RU.UTF-8",LC_ALL="ru_RU.UTF-8",LC_LANG="ru_RU.UTF-8"
command=/var/www/.virtualenvs/project/bin/gunicorn_django -c /var/www/project/conf/gunicorn.conf.py
user=www-data
group=www-data
daemon=false
debug=false
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/var/www/project/log/supervisor.log
Самая важная строка здесь - та, в которой задаётся значение параметра environment. Именно там указывается, какие локали использовать Python'у для работы с файлами, языком и т.д. Именно эта небольшая строка предотвращает ошибки вида "Non Unicode character at position..." и "Non-ASCII character at position...". Не забудьте удалить переменные окружения, которые на самом деле вам не нужны. При необходимости к окружению можно добавить новые переменные, однако, после запятых не должно быть пробелов, а все значения должны быть заключены в кавычки или апострофы.
После того, как файл настройки будет изменён, следует уведомить об этом Supervisor:
supervisorctl update
Если при этом Supervisor будет выдавать сообщения об ошибках, первым делом следует проверить правильность расстановки кавычек и запятых.