Thursday, October 10, 2013

Монтирование Nexus 7

С этой темой я корячился давно и долго, и вот после UP7 в LMDE всё заработало по-человечески.
Использовался вот этот чудесный гайд.

Для работы по протоколу MTP используется библиотека libmtp, и похоже, в последнем релизе Debian её таки починили.
Чтобы примонтировать устройство по протоколу MTP, можно пользоваться кучей способов: mtpfs, jmtpfs, gvfs-mtp, go-mtpfs.
Вот последний и интересен. Разрабатывался (и поддерживается в момент написания статьи) разработчиком Android, быстр и, в последних версиях, лишён багов с отваливанием устройства. Ну, будем думать, что из-за фикса непосредственно в libmtp.

Перво-наперво, нужно разрешить не-root пользователям доступ к файловым системам, смонтированным от лица root. Для этого открываем /etc/fuse.conf и раскомментируем опцию user_allow_other.

Дальше нужно поставить сам go-mtpfs.
Для этого понадобятся git и компилятор Go, а дальше дело занимает пару минут.
Итак:
sudo apt-get install libmtp-dev git golang # готовим build environment
mkdir /tmp/go # здесь будем собирать
export GOPATH=/tmp/go
go get github.com/hanwen/go-mtpfs # забираем проект go-mtpfs с гитхаба; при этом происходит сборка при помощи Go
sudo mv /tmp/go/bin/go-mtpfs ~/bin/go-mtpfs # готово, перемещаем бинарник туда, куда нам удобно
sudo chmod a+x ~/bin/go-mtpfs # не забываем выдать бинарнику права на запуск
Собрали. Можем монтировать:
go-mtpfs /media/mtp
и размонтировать:
fusermount -u /media/mtp
Кроме того, добавим правила udev, чтобы при подключении устройства через USB оно автоматически монтировалось. Создаём файлик /etc/udev/rules.d/99-android.rules с вот таким содержанием:
# /etc/udev/rules.d/

# Google Nexus 7
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e40", MODE="0666" # Bootloader
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="d001", MODE="0666" # Recovery
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e43", MODE="0666" # PTP media, USB debug off
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e44", MODE="0666" # PTP media, USB debug on
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e41", MODE="0666" # MTP media, USB debug off
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", MODE="0666" # MTP media, USB debug on

# Google Nexus 7 MTP mode under JB 4.1 : automatic mount & umount when plugged (USB debug on & off)
ENV{ID_MODEL}=="Nexus", ENV{ID_MODEL_ID}=="4e41", ACTION=="add", RUN+="/usr/bin/sudo -b -u dbz /home/dbz/bin/go-mtpfs -allow-other=true /media/mtp"
ENV{ID_MODEL}=="Nexus", ENV{ID_MODEL_ID}=="4e42", ACTION=="add", RUN+="/usr/bin/sudo -b -u dbz /home/dbz/bin/go-mtpfs -allow-other=true /media/mtp"
ENV{ID_MODEL}=="Nexus", ENV{ID_MODEL_ID}=="4e41", ACTION=="remove", RUN+="/bin/umount /media/mtp"
ENV{ID_MODEL}=="Nexus", ENV{ID_MODEL_ID}=="4e42", ACTION=="remove", RUN+="/bin/umount /media/mtp"

# Google Nexus 7 MTP mode under JB 4.2+ : automatic mount & umount when plugged (USB debug on & off)
ENV{ID_MODEL}=="Nexus_7", ENV{ID_MODEL_ID}=="4e41", ACTION=="add", RUN+="/usr/bin/sudo -b -u dbz /home/dbz/bin/go-mtpfs -allow-other=true /media/mtp"
ENV{ID_MODEL}=="Nexus_7", ENV{ID_MODEL_ID}=="4e42", ACTION=="add", RUN+="/usr/bin/sudo -b -u dbz /home/dbz/bin/go-mtpfs -allow-other=true /media/mtp"
ENV{ID_MODEL}=="Nexus_7", ENV{ID_MODEL_ID}=="4e41", ACTION=="remove", RUN+="/bin/umount /media/mtp"
ENV{ID_MODEL}=="Nexus_7", ENV{ID_MODEL_ID}=="4e42", ACTION=="remove", RUN+="/bin/umount /media/mtp"
Здесь используется монтирование через sudo, т.к. почему-то без него монтировать не хочет. Копаться почему так мне не хотелось. Опция -b используется для запуска монтирования в бекграунде, т.к. udev очень нетерпим к долгим операциям. Пробовал вот такую команду:
ENV{ID_MODEL}=="Nexus_7", ENV{ID_MODEL_ID}=="4e42", ACTION=="add", RUN+="/home/dbz/bin/go-mtpfs -allow-other=true /media/mtp &"
т.е. монтировать без sudo и отправлять процесс в бекграунд при помощи & - не сработало...
В правилах udev нужно прописывать абсолютные пути.
Также видим, что наряду с fusermount -u можно размонтировать обычным umount.

Т.к. после UP7 система, наконец-то, научилась монтировать устройства при помощи gvfs-mtp, при подключении устройства увидим 2 точки монтирования: одна та, что мы только что задали; другая - будет называться Nexus_7 или как-нибудь похоже, и будет представлять собой путь вида mtp://...
Всё бы ничего, но раз уж нам две шары ни к чему (всё прекрасно работает через go-mtpfs), можем удалить правила для gvfs-mtp. Кроме того, они, похоже, мешают перемонтировать устройство вручную при помощи go-mtpfs, если кабель не отключали/включали, а перемонтировать по какой-то причине было нужно.
Идём в /lib/udev/rules.d/69-libmtp.rules и комментируем следующие строки:
# Google Inc (for Asus) Nexus 7 (MTP)
#ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e41", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
# Google Inc (for Asus) Nexus 7 (MTP+ADB)
#ATTR{idVendor}=="18d1", ATTR{idProduct}=="4e42", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1"
На этом всё. И чтобы наши правила вступили в силу:
sudo service udev restart
Выключаем/включаем кабель и вуаля - шара в /media/mtp. Разумеется, папку перед выполнением всех описанных операций надо создать :)
Закачка у меня происходит на скорости около 8 МБ/с.
Падений не наблюдается.

Есть ещё один нюанс. Если попытаться в файловом браузере отмонтировать шару, то получим сообщение, что мы не рут и сделать этого не можем.
Чтобы разрешить размонтирование, рекомендуют добавить правило в /etc/fstab:
DeviceFs(Nexus\0407)    /media/mtp   fuse.DeviceFs(Nexus\0407)    allow_other,rw,user,noauto    0    0
Я не смог заставить эту опцию заработать. Кроме того, архитектура MTP такова, что как только вы скопировали файл, можно вытаскивать кабель, не боясь что-либо потерять или испортить файловую систему устройства.
Зато я добавил два удобненьких алиаса в ~/.bashrc:
alias mtpmount='go-mtpfs /media/mtp'
alias mtpumount='fusermount -u /media/mtp'

Wednesday, October 2, 2013

Немного о картинках и бэкграундах


Задача №1: указать папку с картинками для слайдшоу в mate-screensaver.
Решение:
  • открываем /usr/share/applications/screensavers/personal-slideshow.desktop
  • ищем секцию Exec=/usr/lib/mate-screensaver/slideshow
  • дописываем в конец секции: --location=/path/to/your/images

Задача №2: поменять фон экрана блокировки.
Решение:
  • идём в /usr/share/backgrounds/linuxmint
  • видим символьную ссылку default_background.jpg
  • сохраняем её на всякий пожарный: cp default_background.jpg default_background.jpg.old
  • создаём новую символьную ссылку на то, что нам надо: sudo ln -s /path/to/image default_background.jpg
  • надо перелогиниться либо перезапустить mate-screensaver: killall mate-screensaver; mate-screensaver &

Автомонтирование разделов с NTFS


Вернуться к этой теме заставило недавнее обновление моего любимого LMDE до Update Pack 7 (UP7).

Итак, задача: после входа пользователя, разделы с файловой системой NTFS должны быть примонтированы.
Нашёл отличное решение вот здесь.
Заключается оно в следующем:
  • создаётся скрипт, который монтирует разделы по одному, скажем, по их UUID
  • скрипт помещается в автозагрузку
  • profit!

Продублирую это решение:
#!/usr/bin/env bash

# Redsandro 2013-03-01
# Mount (LUKS) drives and such

doMount() {
    # Devices change every now and then. UUID does not.
    DEV=`ls -l --color=never /dev/disk/by-uuid/ | grep $UUID | cut -d\>  -f2 | cut -d/ -f3`
    gvfs-mount -d /dev/$DEV
}

# LUKS-1TB
# /dev/sdb1
UUID='9dd6df52-c901-4b70-8151-27086ba7db16'
doMount

# Projects 1TB
# /dev/sdd1
UUID='6b01a30e-af6e-48b4-810a-f9824558f041'
doMount
Всё. Осталось только подставить сюда UUID своих разделов. В рамках одной системы решение долговечное, т.к. UUID разделов меняются чуть чаще чем никогда.

Ещё советуют запретить автоматически открываемые окна для каждого примонтированного девайса вот такой командой:
gsettings set org.gnome.desktop.media-handling automount-open false
Но у меня эти окна не появляются и без редактирования указанной опции.

Следующий шаг очевиден. После входа в систему мы увидим окошко с запросом пароля для монтирования разделов. Чтобы этого избежать, и монтировать без запроса пароля, рекомендуют сделать следующее:
  • открыть файл /usr/share/polkit-1/actions/org.freedesktop.udisks.policy
  • найти там следующую секцию: <action id="org.freedesktop.udisks.filesystem-mount-system-internal">
  • взглянуть ниже и найти там подсекцию <defaults>
  • для каждой из опций allow_* в этой секции поменять текущие значения на yes
В итоге должно получиться следующее:
    
      yes
      yes
      yes
    
НО.
После UP7 используется новая подсистема udisks2, и значит нужно менять другой конфиг и другие секции.
Конфиг теперь вот такой: /usr/share/polkit-1/actions/org.freedesktop.udisks2.policy
Секции теперь вот такие:
  • <action id="org.freedesktop.udisks2.filesystem-mount">
  • <action id="org.freedesktop.udisks2.filesystem-mount-system">
  • <action id="org.freedesktop.udisks2.filesystem-mount-other-seat">

Ну и напоследок - новая версия udisks преподнесла ещё один сюрприз.
Доселе разделы монтировались в /media, теперь же они стали монтироваться в /media/$USER.
К счастью, решение есть. Как видим, даже два :)
Используем самое простое и очевидное:
  • создаём файл /etc/udev/rules.d/99-udisks2.rules
  • пишем в нём: ENV{ID_FS_USAGE}=="filesystem", ENV{UDISKS_FILESYSTEM_SHARED}="1"
  • сохраняем
  • размонтируем примонтированные в корявое место разделы :)
  • sudo service udev restart
  • profit!

Tuesday, August 27, 2013

Флаги в индикаторе раскладок клавиатуры - Mate 1.6

Отображение флагов информативнее, чем уныло-чёрного us/ru.
Делаем:
1. Создаём (sudo) папку /usr/share/icons/flags, если ещё не создана (чтобы изменения не касались всех пользователей, можно использовать папку ~/.icons/flags)
2. Забрасываем в неё иконки нужных layout'ов (у меня это ru.png и us.png 48x48 каждый).
3. В консоли:
gsettings set org.mate.peripherals-keyboard-xkb.indicator show-flags true

Всё. Если эффекта нет, то:
killall mate-panel

Saturday, August 17, 2013

URL Encoding в bash используя perl

Понадобилось для curl делать URL Encoding параметров, вводимых из консоли.
Спасло простое решение, требующеее наличие perl.
Решение здесь: http://andy.wordpress.com/2008/09/17/urlencode-in-bash-with-perl/

Продублирую:
ENCODED=$(echo -n "value to encode" | \
perl -pe's/([^-_.~A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg');
echo $ENCODED

Sunday, August 4, 2013

Регулировка яркости монитора

Захотелось менять яркость монитора, не тыкая кнопки на самом мониторе. Для этого понадобятся как минимум два пакета: ddccontrol и i2c-dev. Для GUI понадобится ещё и gddccontrol. Первым делом необходимо добавить текущего пользователя (который будет менять яркость) в группу i2c, т.к. по умолчанию запуск этой команды требует прав суперпользователя. Для этого выполняем:
sudo adduser $USER i2c
Далее необходимо, чтобы был загружен модуль ядра i2c-dev. Разумеется, каждый раз переходить в режим суперпользователя для этого неудобно да и незачем, поэтому обеспечим его автоподгрузку при старте системы, выполнив:
sudo /bin/sh -c 'echo i2c-dev >> /etc/modules'
Теперь у нас есть всё, чтобы начать настраивать саму ddccontrol/gddccontrol. Вначале запускаем ddccontrol с параметром -p
ddccontrol -p
и ждём, пока программа найдёт имеющиеся в системе мониторы и определит их параметры. У меня в системе найдены два устройства: dev:/dev/i2c-4 и dev:/dev/i2c-3. Первый определился как PHLC05D [Philips standard LCD] и далее проследовали его параметры, в частности:
> Brightness and Contrast
  > id=brightness, name=Brightness, address=0x10, delay=-1ms, type=0
    supported, value=90, maximum=100
Нас интересует яркость (Brightness), и нам нужен параметр address для установки значений. Теперь, когда у нас есть всё необходимое, можем запускать, например:
ddccontrol -r 0x10 -w 90 dev:/dev/i2c-4
для установки значения яркости 90. Вывод команды будет такой:
ddccontrol version 0.4.2
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.

Reading EDID and initializing DDC/CI at bus dev:/dev/i2c-4...
I/O warning : failed to load external entity "/usr/share/ddccontrol-db/monitor/PHLC05D.xml"
Document not parsed successfully.

EDID readings:
 Plug and Play ID: PHLC05D [Philips standard LCD]
 Input type: Analog
=============================== WARNING ===============================
There is no support for your monitor in the database, but ddccontrol is
using a generic profile for your monitor's manufacturer. Some controls
may not be supported, or may not work as expected.
Please update ddccontrol-db, or, if you are already using the latest
version, please send the output of the following command to
ddccontrol-users@lists.sourceforge.net:

LANG= LC_ALL= ddccontrol -p -c -d

Thank you.
=============================== WARNING ===============================

Writing 0x10, 0x5a(90)...
Control 0x10: +/90/100 C [Brightness]
Программа сказала, что наш монитор ей неизвестен, включив в вывод warning. Далее это же предупреждение будет появляться в gddccontrol, поэтому пойдём в директорию с настройками известных мониторов:
cd /usr/share/ddccontrol-db/monitor/
и скопируем файл VESA.xml, дав имя новому файлу в соответствии с опознанной моделью:
sudo cp VESA.xml PHLC05D.xml
Всё. Теперь наш монитор будет определяться как VESA-совместимый, а назойливый warning исчезнет. Пробуем:
ddccontrol -r 0x10 -w 90 dev:/dev/i2c-4
И получаем вывод:
ddccontrol version 0.4.2
Copyright 2004-2005 Oleg I. Vdovikin (oleg@cs.msu.su)
Copyright 2004-2006 Nicolas Boichat (nicolas@boichat.ch)
This program comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of this program under the terms of the GNU General Public License.

Reading EDID and initializing DDC/CI at bus dev:/dev/i2c-4...

EDID readings:
 Plug and Play ID: PHLC05D [VESA standard monitor]
 Input type: Analog

Writing 0x10, 0x5a(90)...
Control 0x10: +/90/100 C [Brightness]
Команда длинная, сделаем для неё alias. А точнее, создадим функцию bright (т.к. alias'ы не поддерживают передачу параметров) и сохраним её в файле ~/.bashrc:
function brigth() { ddccontrol -r 0x10 -w "$@" dev:/dev/i2c-4; }
Теперь, завершив сессию пользователя для перечитывания файла ~/.bashrc, мы сможем менять яркость, выполнив простую команду:
bright 70
Вот и всё. Также можно пользоваться удобным GUI, вызывая gddccontrol. Для этого поместим на панель новый апплет (среда Mate/Gnome-2), выберем тип Custom application launcher и впишем туда одно слово:
gddccontrol

Жить стало удобнее :)


Использованы материалы:
http://www.techytalk.info/debian-ubuntu-gddccontrol-non-root/
http://www.cyberciti.biz/faq/linux-unix-pass-argument-to-alias-command/

Sunday, April 28, 2013

Читаем SMS из модема Huawei E153u-1

Итак, есть указанный модем. Необходимо под LMDE x64 каким-то образом читать SMS.
Все возможные версии MobilePartner, найденные на просторах интернетиков, зафейлились либо на этапе установки, либо на этапе запуска.
Больше в их сторону не смотрим.
Нам понадобится gammu + wammu (последний для GUI). Но об этом чуть ниже.

Прежде всего, обнаружилась проблема. Модем не хотел определяться после того, как был вынут из USB-порта. Поиски привели к решению проблемы:

1. Проверяем атрибуты USB, на котором висит модем:
lsusb

в моём случае вывод был следующий:
Bus 004 Device 018: ID 12d1:1446 Huawei Technologies Co., Ltd.

2. Редактируем udev rules:
sudo nano /lib/udev/rules.d/40-usb_modeswitch.rules

Ищем устройство с idVendor 12d1 (из предыдущего вывода) и idProduct 1446 (опять же из предыдущего вывода). Такового нет, поэтому добавляем его ручками по аналогии с имеющимися записями для прочих хуавеев:

# Huawei E153u-1
ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1446", RUN+="usb_modeswitch '%b/%k'"
3. Достаём модем, втыкаем назад. Через некоторое время появляется запрос PIN'а. Не верим своим глазам, проверяем:
dmesg | grep tty
И действительно, устройство было опознано:
[ 3222.977099] usb 4-1.2.4: GSM modem (1-port) converter now attached to ttyUSB0
[ 3222.980352] usb 4-1.2.4: GSM modem (1-port) converter now attached to ttyUSB1
[ 3222.980438] usb 4-1.2.4: GSM modem (1-port) converter now attached to ttyUSB2

Итак, проблему решили.

Здесь важно сделать ещё один пункт, иначе возможны проблемы.
На апплете network-manager'а правой кнопкой и снимаем галку напротив Enable Mobile Broadband. Интернетики уверяют, что в противном случае возможны дедлоки и wammu не сможет ничего прочесть.

Всё готово. Теперь осталось настроить gammu + wammu для выполнения непосредственно поставленной цели.

Перво-наперво запускаем
gammu-config
и выбираем порт /dev/ttyUSB0 (первый из тех, что нам выдал dmesg).
Connection оставляем как есть - at19200.
Всё остальное, в принципе, тоже оставляем как есть, сохраняем конфиг (сохраняется в ~/.gammurc).

Можем попробовать прочитать SMS-ки в памяти телефона из консоли:
gammu getallsms
Получаем список SMS, ликуем.

Дальше открываем wammu и видим чудненький GUI.
Делаем по порядку:
- Phone -> Connect, ожидаем соединения с устройством
- Retrieve -> Messages.
Получили список SMS в гуях. Чётко, красиво, аккуратно.

Всё. Задача решена.

Из возможных проблем - wammu не всегда работает корректно. Например у меня иногда виснет в процессе сбора SMS. Тогда:
sudo killall wamu
и запускаем по новой :)

Ещё одна интересная особенность. После прописывания устройства в udev rules файлик, модем стал определяться под другим ID:
Bus 004 Device 020: ID 12d1:14ac Huawei Technologies Co., Ltd.
Т.е. Vendor ID остался прежним (12d1), а Product ID сменился (14ac вместо 1446). Но, как ни странно, теперь всё работает как часы, несмотря на то, что в udev rules устройство с Product ID 14ac не прописано.
Магия, мать её за ногу...

Wednesday, March 27, 2013

Установка системы на SSD: тонкости и тюнинг

В конфигурации два HDD:
  • sda: SSD Crucial M4 128 GB
  • sdb: HDD Seagate SATA-III 3Tb ST33000651AS
На SSD стоит Windows 7.
Схема разбиения для линуксовых разделов была принята следующая:
  • sda3 - /boot (200M)
  • sda4 - extended partition
  • sda5 - / (30G)
  • sda6 - swap (8G)
и
  • sdb4 - /tmp (10G)
  • sdb5 - /var/log (4G)
  • sdb6 - /home (сколько останется :)

В процессе установки выяснилось, что инсталлятор LMDE не умеет создавать разделы на разных устройствах. Пришлось выделить временно разделы на sda для /tmp, /var/log и /home (выделял по 2G).
После установки создал при помощи обожаемого GParted Live нужные разделы на sdb и скопировал разделы поштучно при помощи
$ cp -ax /old_content /new_content
The -a option preserves the original system as much as possible. The -x option limits cp to a single file system... (c) Источник
Т.е. опция -x нужна для предотвращения копирования подмонтированных файловых систем. В моём случае один раздел нужно просто скопировать в другой, так что опция -x теряет смысл (оставляю её здесь на память для себя).
После копирования старые разделы можно удалить, а для новых обновить /etc/fstab:
# /dev/sdb4
UUID=7aaf7a78-...   /tmp   ext4   rw,errors=remount-ro   0 0
# /dev/sdb5
UUID=aeacecfd-...   /var/log   ext4   rw,errors=remount-ro   0 0
# /dev/sdb6
UUID=0dff36fd-...   /home   ext4   rw,errors=remount-ro   0 0

После этого первым делом добавил опцию discard для раздела /, который находится на SSD:
# /dev/sda5
UUID=c97278c1-...   /   ext4   rw,discard,errors=remount-ro   0 1
И изменил кое-какие дополнительные настройки:
  • в /etc/sysctl.conf дописал:
vm.dirty_writeback_centisecs = 6000
vm.swappiness = 0
что заставляет свопить только при заполнении всей физической памяти, а также устанавливает лимит отложенной записи в 60 секунд (100 centisecs = 1 sec);
  • заменил I/O планировщик (по умолчанию CFQ) на DEADLINE, для этого:
    • а) в /etc/default/grub изменил строку GRUB_CMDLINE_LINUX_DEFAULT и добавил в конец elevator=deadline
    • б) для обновления Grub выполнил:
sudo update-grub

Источники информации: раз и два.

Вводная

Серия заметок про GNU/Linux.

Создана как хранилище полезных знаний, которые позже не лишним будет перечитать самому.

Стартовый дистрибутив - Linux Mint Debian Edition (LMDE), т.к. ноги растут из Debian, и помимо этого имеет человеческое лицо и шикарную рабочую среду Mate.

О подсветке синтаксиса в блоге читать здесь.
Пример для bash на сайте автора.

Плюс фикс стилей от NathanAldenSr, взят здесь: http://stackoverflow.com/questions/11804789/extra-lines-using-syntaxhighlighter-for-chrome-only

Поехали!