Многие пользователи ПК знают, что от того как оформлен их Рабочий стол, от стиля иконок и папок, от всевозможных гаджетов и датчиков, зависит их комфортная и продуктивная работа за компьютером.
Continue Reading

Футуристические фильмы, говорящие дома... А почему бы не сделать шаг в будущее и не научить Linux разговаривать? Имея Debian Squeeze в качестве домашнего сервера, научим его проверять почту на gmail и сообщать число непрочитанных сообщений с помощью голоса на русском языке.

В этом нелегком деле нам помогут пакеты festival, speech-tools и festvox-ru:

root@localhost:~$ apt-get install festival speech-tools festival-voice festvox-ru

Проверим как оно звучит:

root@localhost:~$ echo "Привет мир" | festival --language russian --tts

Если вместо того, чтобы услышать голос, вы увидели сообщение об ошибке: «ESD: error writing — Bad file descriptor», у вас не стоит PulseAudio, который festival пытается использовать по-умолчанию. Для того, чтобы переключить его на использование alsa и избавится от этой ошибки нужно создать файл ~/.festivalrc с таким содержанием:

(Parameter.set 'Audio_Command "aplay -q -c 1 -t raw -f s16 -r $SR $FILE")
(Parameter.set 'Audio_Method 'Audio_Command)

Теперь перейдем к части с почтой. Gmail представляет удобную atom-ленту для непрочитанных сообщений, используя ее можно написать небольшой скрипт который получает число сообщений аккаунта gmail и информирует об этом с помощью голоса. У меня получился вот такой:

~/bin/check_mail.sh

#!/bin/bash
 
USER="yourname@gmail.com"
PASS="secret"
 
plural () {
    if (( $1 > 10 ))
    then
        N=$(($1 % 10))
    else
        N=$1
    fi
 
    if (( $N > 10 && $N < 20 ))
    then
        FORM="сообщений"
    else if (( $N > 1 && $N < 5 ))
    then
        FORM="сообщения"
    else if (( $N == 1 ))
    then
        FORM="сообщение"
    else
        FORM="сообщений"
    fi
    fi
    fi
 
    echo $FORM
}
 
NEW=`/usr/bin/curl -u ${USER}:${PASS} --silent "https://mail.google.com/mail/feed/atom" |
grep -c "<entry>"`
 
if (( $NEW > 0 ))
then
    if (( $NEW == 1 ))
    then
           echo "У вас одно непрочитанное сообщение электронной почты." | /usr/bin/festival
--language russian --tts
    else
           echo "У вас $NEW непрочитанных `plural $NEW` электронной почты." | /usr/bin/festival
--language russian --tts
    fi
fi
 
exit 0

Этот скрипт можно добавить в крон, он нем как рыба если непрочитанных сообщений нет, когда же они появятся, он сообщит вам об этом.

В последнее время особую популярность обретают различные «облачные» сервисы, в том числе резервное копирование. В интернете можно найти десяток сайтов представляющих подобные услуги, в том числе на платной основе.

Рассмотрим настройку автоматического бекапа веб-сервера с помощью архиватора 7z и сервиса Dropbox в Debian/Ubuntu Linux.

Создадим непривилегированного пользователя из-под которого будет запущен клиент Dropbox.

root@localhost:~$ useradd backupus

Далее в соответсвии с официальной вики устанавливаем консольного клиента, для созданного ранее пользователя

backupus@localhost:~$ cd ~/
backupus@localhost:~$ wget -O dropbox.tar.gz http://www.dropbox.com/download/?plat=lnx.x86
backupus@localhost:~$ tar -zxof dropbox.tar.gz

Запускаем клиента

backupus@localhost:~$ ~/.dropbox-dist/dropboxd

Через несколько секунд в консоле появится ссылка для привязки данного компьютера к вашему аккаунту.

Изменяем каталог за которым следит демон Dropbox на «/backup»:

backupus@localhost:~$ cp ~/.dropbox/dropbox.db dropbox.db.backup
backupus@localhost:~$ wget http://dl.dropbox.com/u/119154/permalink/dropboxdir.py
backupus@localhost:~$ chmod +x dropboxdir.py
backupus@localhost:~$ mv ~/Dropbox /backup
backupus@localhost:~$ ./dropboxdir.py --setfolder=/backup

Добавим скрипт автозапуска /etc/init.d/dropbox

# dropbox service
DROPBOX_USERS="backupus"
 
DAEMON=.dropbox-dist/dropbox
 
start() {
    echo "Starting dropbox..."
    for dbuser in $DROPBOX_USERS; do
        HOMEDIR=`getent passwd $dbuser | cut -d: -f6`
        if [ -x $HOMEDIR/$DAEMON ]; then
            HOME="$HOMEDIR" start-stop-daemon -b -o -c $dbuser -S -u $dbuser -x $HOMEDIR/$DAEMON
        fi
    done
}
 
stop() {
    echo "Stopping dropbox..."
    for dbuser in $DROPBOX_USERS; do
        HOMEDIR=`getent passwd $dbuser | cut -d: -f6`
        if [ -x $HOMEDIR/$DAEMON ]; then
            start-stop-daemon -o -c $dbuser -K -u $dbuser -x $HOMEDIR/$DAEMON
        fi
    done
}
 
status() {
    for dbuser in $DROPBOX_USERS; do
        dbpid=`pgrep -u $dbuser dropbox`
        if [ -z $dbpid ] ; then
            echo "dropboxd for USER $dbuser: not running."
        else
            echo "dropboxd for USER $dbuser: running (pid $dbpid)"
        fi
    done
}
 
 
case "$1" in
  start)
    start
    ;;
 
  stop)
    stop
    ;;
 
  restart|reload|force-reload)
    stop
    start
    ;;
 
  status)
    status
    ;;
 
  *)
    echo "Usage: /etc/init.d/dropbox {start|stop|reload|force-reload|restart|status}"
    exit 1
 
esac
 
exit 0

Делаем исполняемым, разрешаем запуск при загрузке и запускаем:

root@localhost:~$ chmod +x /etc/init.d/dropbox
root@localhost:~$ update-rc.d dropbox defaults
root@localhost:~$ /etc/init.d/dropbox start

Синхронизация файлов с онлайн-хранилищем работает, перейдем непосредственно к бекапу:

#!/bin/sh
 
DATE=`/bin/date +%Y%m%d`
BACKUP_DIR="/backup/${DATE}"
 
SZ_CMD="/usr/bin/7za"
SZ_PSW="secret"
SZ_OPT="a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on -p${SZ_PSW}"
 
SITES="example.org site.com blog.me"
 
MYSQL_USR="backup"
MYSQL_PSW="secret"
MYSQL_DBS="mysql example_org site_com blog_me"
 
# Create Dirs
/bin/mkdir ${BACKUP_DIR}
/bin/mkdir ${BACKUP_DIR}/db
/bin/mkdir ${BACKUP_DIR}/www
 
# Installed packages
/usr/bin/dpkg --list | $SZ_CMD $SZ_OPT -si ${BACKUP_DIR}/dpkg.list.7z
 
# Configs
$SZ_CMD $SZ_OPT ${BACKUP_DIR}/etc.7z /etc/
 
# Crontabs
$SZ_CMD $SZ_OPT ${BACKUP_DIR}/crontabs.7z /var/spool/cron/crontabs/
 
# Sites
for SITE in $SITES; do
    $SZ_CMD $SZ_OPT ${BACKUP_DIR}/www/${SITE}.7z /srv/www/${SITE}/
done
 
# MySQL
for DB in $MYSQL_DBS; do
    /usr/bin/mysqldump --opt -u $MYSQL_USR -p${MYSQL_PSW} $DB | $SZ_CMD
    $SZ_OPT -si ${BACKUP_DIR}/db/${DB}.sql.7z
done

Итак, что делает это скрипт:

  • Слепок установленных пакетов
  • Резервную копию конфигов и кронтабов
  • Резервную копию сайтов example.org, site.com и blog.me
  • Резервную копию mysql баз mysql, example_org, site_com и blog_me

Архивы в данном скрипте шифруются с помощью пароля $SZ_PSW, так как доверять никому не стоит

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

В этом может помочь пакет weather-util:

root@localhost:~$ apt-get install weather-util

После устновки нужно проследовать по адресу weather.noaa.gov и найти METAR (METeorological Aerodrome Report) для своего города. После этого можно узнать погоду из командной строки, например для Самары:

root@localhost:~$ weather --city=Samara --id=UWWW
Current conditions at Samara, Russia (UWWW) 53-12N 050-09E (UWWW)
Last updated Oct 26, 2010 - 12:00 PM EDT / 2010.10.26 1600 UTC
   Temperature: 39 F (4 C)
   Relative Humidity: 86%
   Wind: from the SE (130 degrees) at 4 MPH (4 KT)
   Weather: mist

Осталось написать обработчик который пропарсит вывод команды weather и передаст его на озвучку festival. Я использовал для этого простой shell-скрипт:

#!/bin/bash
 
plural () {
    if (( $1 > 10 ))
    then
        N=$(($1 % 10))
    else
        N=$1
    fi
 
    if (( $N > 10 && $N < 20 ))
    then
        FORM=$2
    else if (( $N > 1 && $N < 5 ))
    then
        FORM=$3
    else if (( $N == 1 ))
    then
        FORM=$4
    else
        FORM=$2
    fi
    fi
    fi
 
    echo $FORM
}
 
 
TMP="/tmp/weather_`/bin/date +%s`"
 
/usr/bin/weather --city=Samara --id=UWWW > $TMP
 
temperature=`cat $TMP |grep Temperature |awk '{print $4}' |sed -e 's/(//g'`
humidity=`cat $TMP |grep Humidity |awk '{print $3}' |sed -e 's/%//g'`
 
echo "Температура воздуха $temperature `plural $temperature градусов градуса градус`
Цельсия. Относительная влажность воздуха $humidity
`plural $humidity процентов процента процент`" | /usr/bin/festival --language russian --tts
 
rm -f $TMP
 
exit 0

Твердотельные накопители становятся все доступнее и занимают все большую часть рынка. Вот и я решил заменить hdd c windows seven своего нетбука Lenovo IdeaPad S10-2 на SSD c Ubuntu Netbook.

В этой записи я собрал нагугленные заметки по оптимизации работы Linux на SSD для рабочей станции.

Разметка диска и файловая система

В первую очередь, нужно забыть про раздел подкачки, все прекрасно работает и без него. Для SSD лучше использовать не журналируемую файловую систему. Журнал нужен для того, чтобы, после пропадании электропитания, восстановить незавершенные транзакции — не потерять данные и оставить ФС целостной. Так как большинство SSD используются в ноутбуках/нетбуках, где присутствует батарея, пропадание электропитания практически невозможно, журнал не нужен. Я использую 100 Мб под /boot с ext2, 20 Гб как / с ext4 и все остальное под /home, так же с ext4. Файловую систему ext4 я выбрал так как она позволяет отключать журнал после создания файловой системы, делается это так:

root@localhost:~$ tune2fs -o journal_data_writeback /dev/sda1
root@localhost:~$ tune2fs -O ^has_journal /dev/sda1
root@localhost:~$ e2fsck -f /dev/sda10

Так же, для увеличения производительности, к опциям монтирования в fstab рекомендуется добавить:

relatime,nodiratime,discard,commit=60

Здесь у некоторых может возникнуть подозрение, что использование noatime эффективнее чем relatime. Это не так, relatime обновляет время доступа только при изменении файла или изменении времени доступа. Это нужно для нормальной работы некоторых программ, в том числе почтовых клиентов. Опция discard включает поддержку TRIM. Так же откладываем до раза в минуту запись изменений на накопитель commit=60.

Логи на рабочей станции мало кому нужны после перезагрузки, поэтому целесообразно разместить их, как и временные файлы, в оперативной памяти. Для этого добавим такие строки в fstab:

tmpfs	 /tmp           tmpfs	defaults,noatime,mode=1777	0 0
tmpfs	 /var/tmp	tmpfs	defaults,noatime,mode=1777	0 0
tmpfs	 /var/log	tmpfs	defaults,noatime,mode=0755	0 0

I/O планировщик

Планировщик cfq, используемый по умолчанию в большинстве дистрибутивов лучше заманить на noop. Для этого к опциям ядра в конфиге загрузчика нужно добавить:

elevator=noop

Параметры ядра

Включаем «режим ноутбука» для подсистемы виртуальной памяти, в таком режиме, ядро будет откладывать запись на диск, пока в этом не появится неотложная необходимость. Кроме того повысим таймаут между сбросом буферов до 15 секунд:

vm.laptop_mode = 5
vm.dirty_writeback_centisecs = 15000

Firefox & Chrome

Временные файлы мы перенесли в оперативную память, но браузеры хранят свой кеш в домашнем каталоге пользователя, который у нас на SSD. Нужно либо переместить кеш с SSD, либо выключить его. Я выбрал последний вариант.

Для этого в адресной строке Firefox введем about:config и изменим параметр:

browser.cache.disk.enable: false

В Chrome немного сложнее, запретить кеш раз и навсегда нельзя, вместо этого нужно каждый раз запускать браузер с параметром --disk-cache-size=0:

google-chrome --disk-cache-size=0

Или создать alias:

alias google-chrome='google-chrome --disk-cache-size=0'

Кэш пакетных менеджеров

Так же может быть полезным вынести кэш менеджера пакетов в ОЗУ. Для deb-based дистрибутивов нужно добавить в fstab:

tmpfs   /var/cache/apt/archives tmpfs   defaults        	0 0

Для rpm-based дистрибутивов нужно добавить в fstab:

tmpfs   /var/cache/yum tmpfs   defaults        			0 0

UPD20130310: Обновлены обции монтирования, добавлен вынос кеша пакетных менеджеров в ОЗУ.

Тем кто использует такие операционные системы как Gentoo и FreeBSD пакеты ccache и distcc должны быть хорошо знакомы, те кто использует бинарные дистрибутивы так же могли о них слышать.

Ccache — кеш C/C++ компиляторов. При компилировании какого-либо файла вычисляется его хэш, если файл с таким хэшем есть в локальном кеше, то файл не будет повторно компилироваться, вместо этого будет использован файл из кеша. Так как при обновлении программы, как правило, изменяются не все файлы исходного кода, использование кеша позволяет существенно ускорить не только повторную компиляцию программы, но и ее обновлений.

Distcc — позволяет компилировать исходные коды C/C++/ObjC на нескольких компьютерах. Поддерживает кросс-платформенное компилирование. Для отсутствия ошибок в программ скомпилированных посредством distcc на всех компьютерах должна быть установлена одинаковая версия gcc, например 4.3.x, при этом x — может отличаться.

Рассмотрим установку и настройку ccache и distcc в бинарном дистрибутиве, на примере Debian Linux. Некоторые могут сказать, подобные программы в бинарном дистрибутиве не нужны, в общем то это справедливо, но только до тех пор, пока не требуется использование apt-build, make-kpkg и вас полностью устраивает набор ПО и их версий включенных в текущий релиз.

Пакеты ccache и distcc включены в стандартные репозитории Debian, поэтому их установка сводится к выполнению одной команды:

root@localhost:~$ apt-get install ccache distcc

Настройка Ccache

Чтобы начать использовать ccache во время компиляции нужно установить несколько переменных окружения, сделаем это через .profile или .bashrc, добавим такие строки:

export PATH=/usr/lib/ccache:$PATH
export CC="ccache gcc"
export HOSTCC="ccache gcc"
export HOSTCXX="ccache g++"
export CCACHE_DIR="/var/cache/.ccache"

Переменная CCACHE_DIR — устанавливает каталог где хранится кеш C/C++ компиляторов, по умолчанию она равна $HOME/.ccache.

Настройка Distcc

Данная будет полезна только тем у кого в распоряжении есть несколько компьютеров с одной версией gcc, например ПК и ноутбук, или ноутбук или домашний сервер.

Все настройки демона distcc в Debian находятся в файле /etc/default/distcc:

 
STARTDISTCC="true"
 
ALLOWEDNETS="127.0.0.1 192.168.0.0/24"
 
LISTENER="0.0.0.0"
 
JOBS="4"

Число джобов не должно быть больше числа ядер:

root@localhost:~$ cat /proc/cpuinfo |grep processor |wc -l
4

Таким образом следует настроить distcc на каждом хосте. После настройки демонов их нужно запустить:

root@localhost:~$ invoke-rc.d distcc start

Теперь клиентская часть, в .profile или .bashrc, добавим:

export CCACHE_PREFIX="distcc"
export CONCURRENCY_LEVEL=7
export DISTCC_HOSTS="localhost/3 192.168.0.2/2 192.168.0.3/2"

В переменной DISTCC_HOSTS указывается перечень хостов, через слеш указывается максимальное число параллельных задач компиляции которое может быть принято хостом, кроме того, если хост находится не в локальной сети, есть смысл включить lzo-компрессию. Для локальной машины стоит указать число задач на 1 меньше максимального, так как, кроме непосредственно процесса компиляции, она будет обрабатывать задачи отправляемые на удаленные хосты посредством distcc.
Переменная CONCURRENCY_LEVEL устанавливает максимальное число параллельных задач компиляции в момент времени.

На последок, немного практики, соберем ядро Linux 2.6.36 на копьютере с процессором Intel Atom D510:

root@localhost:/usr/src/linux-2.6.36$ time make-kpkg --initrd --revision=atom1 kernel_image
kernel_headers
...
real	64m37.225s
user	135m48.470s
sys	27m38.509s

Подчистим за собой

root@localhost:/usr/src/linux-2.6.36$ make mrproper
root@localhost:/usr/src/linux-2.6.36$ make-kpkg clean

И соберем ядро еще раз:

root@localhost:/usr/src/linux-2.6.36$ time make-kpkg --initrd --revision=atom1 kernel_image
kernel_headers
...
real	21m36.359s
user	31m15.794s
sys	12m5.879s

Статистика ccache выглядит при этом примерно так:

root@localhost:/usr/src/linux-2.6.36$ ccache -s
cache directory                     /var/ccache/.ccache
cache hit (direct)                 17112
cache hit (preprocessed)              18
cache miss                          8624
called for link                      110
unsupported source language          117
unsupported compiler option         4494
no input file                       4224
files in cache                     25844
cache size                           1.5 Gbytes
max cache size                       2.0 Gbytes