uscr 23.12.2012 17:46

СкриптыКак я синхронизирую.

Стадия 0. Признать проблему.



Добрый день, товарищи! Меня зовут uscr и я синхронизирую Не так давно (около года назад) я набрёл на сайтик simpledesktops.com. Очень уж понравились мне тамошние обои. То есть так понравились, что мне даже стало не плевать, что стоит у меня в качестве обоев рабочего стола. Одновременно с этим я полюбил алиасы команд. А потом я проникся многострочным приглашением командной строки. Но у меня много компьютеров, поэтому мне приходилось следить за актуальностью алиасов, переменной PS1 и установленными обоями. Меня это быстро утомило и нарушило сон. С нарушением сна я смириться не смог и сделал mkdir ~/.bin && vim /etc/crontab
Зачем я это сделал и почему я стал спать лучше читайте под катом.
Дисклеймер: последнее время я обнаружил, что инструкциями из моих постов никто не пользуется. Потому, я просто расскажу про свои костыли и попрошу у вас совета по уборке в скриптах. А уж если кто найдёт нечто для себя полезное, или задаст дельные вопросы, буду рад безмерно.

На самом деле, всё начинается не с ~/.bin, а с дропбокса. Да, да. Всё, что должно синхронизироваться я просто кладу в дропбокс. Впрочем, способ синхронизации между компьютерами не важен. Я могу завтра перейти на использование ftp и ничего глобального менять не придётся.

Итак, команда ls Dropbox/Scripts/homebin/, запущенная на моём компьютере, покажет такой вывод:
deploy.sh ps1.sh sync.sh

В crontab обнаруживаются такая строка:
*/5 * * * * root su -l nazarovd -c '/home/nazarovd/.bin/sync.sh' > /dev/null

Всё это приводит к тому, что каждые 5 минут апдейтится обоина на рабочем столе, приглашение командной строки и содержимое каталога $HOME/.bin

Стадия 1. Забываем о том, как менять фоновую картинку.



Скрипт sync.sh выглядит так:
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#/bin/bash

WALLPAPER_PATH="/home/nazarovd/Dropbox/Images/wallpapers/"

export DISPLAY=:0.0
export XAUTHORITY=/home/nazarovd/.Xauthority

#Set new wallpaper
test=`ls -t $WALLPAPER_PATH | head -n1`
if [ ! -z "$test" ]; then
touch /tmp/.sync.wallpaper.checksum
oldmd5sum=`cat /tmp/.sync.wallpaper.checksum`
curmd5sum=`echo $test | md5sum | cut -d ' ' -f1`
if [ "$oldmd5sum" != "$curmd5sum" ]; then
gsettings set org.gnome.desktop.background picture-uri file://$WALLPAPER_PATH$test
if [ $? -ne 0 ]; then
gconftool-2 -t string -s /desktop/gnome/background/picture_filename $WALLPAPER_PATH$test
fi
echo $curmd5sum > /tmp/.sync.wallpaper.checksum
fi
fi

~/Dropbox/Scripts/homebin/deploy.sh sync
~/Dropbox/Scripts/homebin/ps1.sh update



Здесь определяется самый молодой файл (последний добавленный) в каталоге с обоями, затем от его имени высчитывается хеш. На основании высчитанного и запомненного хеша принимается решение: "обоина устарела или нет?". Нужно это для... Ни для чего. Просто не люблю, когда что-нибудь происходит просто так, а без высчитывания хеша обоина обновлялась бы раз в 5 минут просто так. Если обоину нужно сменить, запускается gsettings, который работает в новых бубунтах (кажется, начиная с 11.04), а вот если что-то пошло не так, то это значит, что мы на старой убунте (у меня самая старая - 10.04) и нужно ставить обоину через реестр (gconftool). Как я ни бился, заставить обоину отрисовываться сразу у меня не получилось. Так что на старой убунте обоина меняется только после перезагрузки.

Выгода от стадии 1:

для смены обоины, нужно просто сохранить её в /home/nazarovd/Dropbox/Images/wallpapers/ и ждать 5 минут (или дать команду newwllppr - это алиас функции set_wallpaper, а про алиасы и функции чуть ниже).

Стадия 2. Не следим за актуальностью .bashrc.



Если кто не знал, алиасы, приглашение командной строки и прочие полезности настраиваются в файлике ~/.bashrc. А у меня, вместо кучи строк, добавлена всего одна: "source ~/Dropbox/Scripts/bashrc_addons/bashrc". В свою очередь файл
~/Dropbox/Scripts/bashrc_addons/bashrc выглядит так:
1
2
3
4
source /home/nazarovd/Dropbox/Scripts/bashrc_addons/aliases
source /home/nazarovd/Dropbox/Scripts/bashrc_addons/functions
source /home/nazarovd/Dropbox/Scripts/bashrc_addons/colors
source /home/nazarovd/Dropbox/Scripts/bashrc_addons/exports


Эти файлы подгружают (сверху вниз): алиасы, вспомогательные функции, алиасы для цветового оформления, различные переменные.

Показываю файлики целиком и не даю никаких описаний. Понадобится - спрашивайте:

aliases:
#ISG
alias ISG_eg='ssh 10.251.249.11'
alias ISG_lub='ssh 10.10.16.33'
#alias ISG_bird='ssh 10.10.16.4'
alias ISG_bird='ssh 10.10.10.253'
alias ISG_tom='ssh 10.10.10.253'

#SERVERS
alias radius43='ssh 10.10.10.43'
alias radius11='ssh 10.10.10.11'
alias radius39='ssh 10.10.10.39'
alias 0.3='ssh 192.168.0.3'
alias monitor='ssh 10.10.10.41'

#DIFFERENT
alias itelnet='~/Dropbox/Scripts/firefox_telneting/i_telneter.py'
alias sshrsync='rsync -e ssh --progress -axuS --partial'
alias reload_addons='source ~/Dropbox/Scripts/bashrc_addons/bashrc'
alias reload_all='source ~/.bashrc'
alias newwllppr='set_wallpaper'
alias share='~/Dropbox/Scripts/fileshare/share.sh'
alias showbashrcaddons='cat ~/Dropbox/Scripts/bashrc_addons/*'
alias torrentadd='~/Dropbox/Scripts/torrentadd/torrentadd.sh'
alias downloadsite='wget -r -k -l 50 -p -E -nc --wait=5'


functions:
WALLPAPER_PATH="/home/nazarovd/Dropbox/Images/wallpapers/"
let CRIT_LOAD=2

function set_wallpaper {

test=`ls -t $WALLPAPER_PATH | head -n1`
if [ ! -z "$test" ]; then
gsettings set org.gnome.desktop.background picture-uri file://$WALLPAPER_PATH$test 2>/dev/null
if [ $? -ne 0 ]; then
gconftool-2 -t string -s /desktop/gnome/background/picture_filename $WALLPAPER_PATH$test
fi
fi

}

function prompt_command {
# get cursor position and add new line if we're not in first column
echo -en "\033[6n" && read -sdR CURPOS
[[ ${CURPOS##*;} -gt 1 ]] && echo " ↵"
}

PROMPT_COMMAND=prompt_command


function load_average {
# Load average

uptm=`uptime`

set -- `cat /proc/loadavg`
#uptm=`uptime`
five=$1
#five=`echo $uptm| awk '{print $9}' | sed 's/,$//g' | sed 's/,/./g'`
let int_five=`echo $five | cut -d '.' -f1`

ten=$2
#ten=`echo $uptm| awk '{print $10}' | sed 's/,$//g' | sed 's/,/./g'`
let int_ten=`echo $ten | cut -d '.' -f1`

fifteen=$3
#fifteen=`echo $uptm| awk '{print $11}' | sed 's/,$//g' | sed 's/,/./g'`
let int_fifteen=`echo $fifteen | cut -d '.' -f1`

#FIVE
if [ $int_five -gt $CRIT_LOAD ]; then
echo -ne "\e[0;31m"
fi
echo -n " $five"
if [ $int_five -gt $CRIT_LOAD ]; then
echo -ne "\e[0;33m"
fi

#TEN
if [ $int_ten -gt $CRIT_LOAD ]; then
echo -ne "\e[0;31m"
fi
echo -n " $ten"
if [ $int_ten -gt $CRIT_LOAD ]; then
echo -ne "\e[0;33m"
fi

echo -ne "\e[0;33m"
#FIFTEEN

if [ $int_fifteen -gt $CRIT_LOAD ]; then
echo -ne "\e[0;31m"
fi
echo -n " $fifteen "
if [ $int_fifteen -gt $CRIT_LOAD ]; then
echo -ne "\e[0;33m"
fi
}


colors:
txtblk='\[\e[0;30m\]' # Black - Regular
txtred='\[\e[0;31m\]' # Red
txtgrn='\[\e[0;32m\]' # Green
txtylw='\[\e[0;33m\]' # Yellow
txtblu='\[\e[0;34m\]' # Blue
txtpur='\[\e[0;35m\]' # Purple
txtcyn='\[\e[0;36m\]' # Cyan
txtwht='\[\e[0;37m\]' # White
bldblk='\[\e[1;30m\]' # Black - Bold
bldred='\[\e[1;31m\]' # Red
bldgrn='\[\e[1;32m\]' # Green
bldylw='\[\e[1;33m\]' # Yellow
bldblu='\[\e[1;34m\]' # Blue
bldpur='\[\e[1;35m\]' # Purple
bldcyn='\[\e[1;36m\]' # Cyan
bldwht='\[\e[1;37m\]' # White
unkblk='\[\e[4;30m\]' # Black - Underline
undred='\[\e[4;31m\]' # Red
undgrn='\[\e[4;32m\]' # Green
undylw='\[\e[4;33m\]' # Yellow
undblu='\[\e[4;34m\]' # Blue
undpur='\[\e[4;35m\]' # Purple
undcyn='\[\e[4;36m\]' # Cyan
undwht='\[\e[4;37m\]' # White
bakblk='\[\e[40m\]' # Black - Background
bakred='\[\e[41m\]' # Red
bakgrn='\[\e[42m\]' # Green
bakylw='\[\e[43m\]' # Yellow
bakblu='\[\e[44m\]' # Blue
bakpur='\[\e[45m\]' # Purple
bakcyn='\[\e[46m\]' # Cyan
bakwht='\[\e[47m\]' # White
txtrst='\[\e[0m\]' # Text Reset


exports:
#Disable dubles in history
export HISTCONTROL=erasedups:ignorespace

#History size
export HISTSIZE=10000


Но приглашение командной строки (а приглашение, если кто забыл, описывается в переменной PS1) нужно было сделать уникальным для каждого компьютера, при этом сохранить некий общий стиль. Поэтому, в рассмотренном выше sync.sh есть строка "~/Dropbox/Scripts/homebin/ps1.sh update", которая дёргает такой вот скрипт:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/bin/bash

source ~/Dropbox/Scripts/bashrc_addons/colors

BASEPS="/home/nazarovd/Dropbox/Scripts/bashrc_addons/PS1_base"

if [ "`id -u`" == "0" ]; then
USERNAMECOLOR=$txtred
else

hostname=`hostname`
sha=`echo $hostname | sha1sum`

let symb=1
let exit=0

while [ $exit -ne 1 ]; do
let symb+=1;
let color=${sha:$symb:1};
if [ $? -eq 0 ]; then
let exit=1;
fi;
done

while [ $color -gt 8 ]; do
let color=$color/2
done

if [ $color -eq 0 -o $color -eq 1 ]; then
let color=$color+2
fi

case $color in
2)
USERNAMECOLOR=$txtgrn
;;
3)
USERNAMECOLOR=$txtgrn
;;
4)
USERNAMECOLOR=$txtylw
;;
5)
USERNAMECOLOR=$txtblu
;;
6)
USERNAMECOLOR=$txtpur
;;
7)
USERNAMECOLOR=$txtcyn
;;
8)
USERNAMECOLOR=$txtwht
;;
esac
fi

PS1_base=`cat $BASEPS`

newPS="PS1=\"$txtcyn┌──$txtrst[ $USERNAMECOLOR\u$txtrst$PS1_base\""
curPS=`cat ~/.bashrc | grep PS1 | tail -n 1`

update () {
if [ "$newPS" != "$curPS" ]; then

if [ ! -z "`tail -n 1 ~/.bashrc | grep PS1`" ]; then
sed -i.bak '$d' ~/.bashrc
fi

echo $newPS >> ~/.bashrc
fi
}

case $1 in
'show')
echo $newPS
;;
'update')
update
;;
esac



Он запускает адовый рандом, который на основании имени хоста определяет цвет этого самого имени в приглашении (при этом рут всегда будет красным). Функция рандома ужасна, но она работает и на всех моих компьютерах выдала разные цвета, потому существует в таком виде. Когда цвет определён, из файла "/home/nazarovd/Dropbox/Scripts/bashrc_addons/PS1_base" извлекается "скелет" приглашения. Всё это смешивается и обматывается изолентой. Теперь проверяемся актуальность переменной PS1 в .bashrc и, если нужно, старая заменяется на новую. "скелет" у меня выглядит так:
1
$txtgrn@$txtcyn\h$txtrst ] [$txtylw\$(load_average)$txtrst] [ $txtcyn\t$txtrst ]\n$txtcyn├── $txtgrn\w$txtcyn\n$txtcyn└>$txtrst


итог выглядит так:

PS1

Выгода от стадии 2:

Новый алиас, переменная среды или обновлённый PS1 правится в соответствующем файлике в дропбоксе, после чего он автоматически разлетится на все компы. А на машине, где уже отрыта консоль, нужно сделать reload_addons и увидеть результаты изменений сразу.

Стадия 3. Вообще не думаем.



Всё это хорошо, но как быть с новыми инсталляциями? Если настраиваться всё это руками, придётся много думать, а это лишает нас вновь обретённого спокойного сна! Поэтому, есть скрипт deploy.sh, который автоматизирует рутину и даёт подсказки там, где лучше всё делать руками. Итак, скрипт (скрипт делает ещё кое-что, в том числе ставит пакеты и настраивает скрипт монтирования Яндекс.диска):

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#!/bin/bash

BIN="$HOME/.bin"
YANDEXMOUNT='mount.yandex'
YANDEXDIR="$HOME/.yandex.disk"
YANDEXALIAS="$HOME/Яндекс.Диск"
ENCFSMOUNT="$HOME/dropbox.crypt"

install () {

mkdir $BIN
mkdir $YANDEXDIR
mkdir $ENCFSMOUNT
ln -s $YANDEXDIR $YANDEXALIAS

read -p 'username for yandexdisk: ' yandexuser
read -s -p 'password for yandexdisk: ' yandexpass

uid=`id | awk '{print $1}' | cut -d '=' -f2 | cut -d '(' -f1`
gid=`id | awk '{print $2}' | cut -d '=' -f2 | cut -d '(' -f1`

echo '#!/usr/bin/expect' > $BIN/$YANDEXMOUNT
echo 'spawn sudo mount.davfs -o "'defaults,uid=$uid,gid=$gid'" https://webdav.yandex.ru '"$HOME/.yandex.disk/" >> $BIN/$YANDEXMOUNT
echo 'expect "Username:"' >> $BIN/$YANDEXMOUNT
echo 'send "'$yandexuser'\r"' >> $BIN/$YANDEXMOUNT
echo 'expect "Password:"' >> $BIN/$YANDEXMOUNT
echo 'send "'$yandexpass'\r"' >> $BIN/$YANDEXMOUNT
echo "expect eof" >> $BIN/$YANDEXMOUNT
chmod +x $BIN/$YANDEXMOUNT

sudo apt-get -y update
sudo apt-get -y install davfs2 expect encfs vim

}

sync () {

echo `basename $1`
rsync -ar --progress --exclude "`basename $1`" `dirname $1`/* $BIN/ > /dev/null

}

settings() {

echo ''
echo ''
echo ''
echo 'Нужно разрешить выполнение sudo mount.davfs без пароля.'
echo 'Типа так:'
echo ''
echo '%admin ALL=(ALL) ALL'
echo '%admin ALL=NOPASSWD: /sbin/mount.davfs'
echo ''
echo 'Вот вывод whereis mount.davfs'
whereis mount.davfs
echo ''
echo ''
echo ''
read -p 'После нажатия любой клавиши откроется sudoers для редактирования'
sudo visudo
echo ''
echo ''
echo ''
echo 'Теперь нужно засунуть в крон скрипт - синхронизатор'
echo 'Типа так:'
echo "*/5 * * * * root su -l nazarovd -c '/home/nazarovd/.bin/sync.sh' > /dev/null"
echo ''
read -p 'После нажатия любой клавиши откроется crontab для редактирования'
sudo vim /etc/crontab
sudo restart cron
echo ''
echo ''
echo ''
echo 'В ~/.bashrc нужно дописать: '
echo ''
echo 'source ~/Dropbox/Scripts/bashrc_addons/bashrc'
echo ''
read -p 'После нажатия клавиши, файл откроется для редактирования'
vim ~/.bashrc
}

case $1 in
'install')
install
settings
sync
;;
'sync')
sync $0
;;
'settings')
settings
;;
esac



Этот же скрипт следит за актуальность каталога ~/.bin (при запуске с параметром sync), в котором раньше и лежали скрипты синхронизации, а теперь только всякие вспомогательные скриптики (на самом деле нет - этот каталог не используется мной совсем :) Все скрипты я запускаю сразу из дропбокса. ).

Выгода от стадии 3:


На вновь установленной системе нужно настроить дропбокс, запустить deploy.sh install, сделать всё, что он попросит и получить настроенную систему (да, вся моя работа начинается и заканчивается в консоли, так что дополнения в .bashrc - вот всё, что мне нужно).

И всё?!


Да. Спасибо за внимание.


Тэги: синхронизация скрипты синхронизации
+ 10 -
Похожие Поделиться

mealsforall 23.12.2012 18:30 #
Альтернативно можно просто всё запихнуть в git, и делать git sync с любой машины. Тогда скрипты не надо писать.
uscr 23.12.2012 18:40 #
Гит умеет менять обои? И PS1 нужно везде одинаковую, но везде разную :)
Так что всё равно скрипты, а гит будет просто альтернативой дропбоксу.
mealsforall 23.12.2012 20:55 #
В общем-то да. Просто контроль более свежих версий файлов писать не надо.

А почему PS1 разный?

ЗЫ. А как ты обнаружил, что инструкциями из твоих постов никто не пользуется? :)
cppmm 24.12.2012 05:09 #
Собрал таки рабочий libastral? Требуем мана по сборке! :)
uscr 24.12.2012 08:48 #
ЗЫ. А как ты обнаружил, что инструкциями из твоих постов никто не пользуется? :)


Инструкции мои решают весьма специфические проблемы, которые не возникают у совсем новичков, а продвинутые пользователи решают их самостоятельно и готовые инструкции им не нужны.
uscr 24.12.2012 08:59 #
А почему PS1 разный?


Хостнейм разным цветом красится. Так он выглядит на домашнем компьютере, например:



Но сейчас я придумал, что можно ввести в PS1 переменную hostnamecolor и менять только значение переменной на разных машинах.
mealsforall 24.12.2012 22:20 #
Может быть, выставлять цвет как зависимость от айпи-адреса, например? Тогда не надо будет указывать вручную цвет для новых машин.
cppmm 24.12.2012 06:17 #
Я как всегда буду к скриптам придираться. :)
По первому, я бы убрал touch и сделал просто дополнительное условие. Что-то типа такого:
 1
2
3
4
5
6
7
8
9
10
11
if [ ! -z "$test" ]; then
curmd5sum=$(echo $test | md5sum | cut -d ' ' -f1)
if [ ! -e /tmp/.sync.wallpaper.checksum ] || [ "$(cat /tmp/.sync.wallpaper.checksum)" != "$curmd5sum" ]
then
echo "gsettings set org.gnome.desktop.background picture-uri file://$WALLPAPPER_PATH$test"
if [ $? -ne 0 ]; then
echo "gconftool-2 -t string -s /desktop/gnome/background/picture_filename $WALLPAPPER_PATH$test"
fi
echo $curmd5sum > /tmp/.sync.wallpaper.checksum
fi
fi


И да. Расположение временного файла лучше вынести в переменную. Если что-то повторяется в скрипте более одного раза, надо делать это переменной.
cppmm 24.12.2012 06:18 #
Да. Скопипастил из своих тестов. Разумеется, echo не нужны(просто у меня гнома нет и для проверки сделал так).
uscr 24.12.2012 08:51 #
Да. Поправлю.
cppmm 24.12.2012 06:23 #
Он запускает адовый рандом

А чем дефолтный рандом не угодил? На разных машинах он должен вполне нормальный результат показывать.
uscr 24.12.2012 08:52 #
Не совсем рандом, я неправильно выразился. Нужно, что бы если у машины hostname='ololo', то на всех машинах с таким хостнеймом был одинаковый цвет.
cppmm 24.12.2012 06:26 #
'В ~/.bashrc нужно дописать: '

А здесь разве не проще сделать это автоматически?
uscr 24.12.2012 08:53 #
Ну... Да... Можно и в кронтаб писать автоматом. Но что то я не стал этого делать.
ananas 25.12.2012 12:50 #
в рутовый кронтаб пихать синхронизацию пользовательского барахла - мягко говоря моветон.
man 1 crontab
le087 26.12.2012 23:11 #
Месье знает толк в извращениях, но мне нравится...

*прикидывает, как бы замутить подобное на 10 000 unix-аккаунтов*
mealsforall 28.12.2012 01:06 #
Зочем на тыщи аккаунтов?
dront78 29.12.2012 20:44 #
а зачем SSH через алиасы? автодополнением же неудобно становится пользоваться в отличии от ~/.ssh/config