Если во время создания снимка LVM выполняется операция Git, репозиторий можно (и будет) сделать снимок в поврежденном состоянии. (Это много обсуждалось http://www.reddit.com/r/programming/comments/1ax0oa/how_kdes_1500_git_repositories_almost_were_lost/ )
Вопрос в том, как это правильно решить. Доступ Git осуществляется через git-shell через ssh (с ключами) на Linux-машину. Остановка доступа примерно на 20 минут каждую ночь не проблема для нашего отдела, но, боюсь, дьявол кроется в деталях.
То, что я придумал до сих пор, заставляет меня чувствовать, что я изобретаю какое-то колесо, о котором я не знаю. из работы cron:
#!/bin/bash
# 0.
# poll during 20 min for ongoing git usage to stop
countdown=$((60*20))
while pgrep -u git >/dev/null ; do
sleep 1
countdown=$((countdown-1))
if [ $countdown -eq 0 ] ; then
break
fi
done
#1
#disable login to the git user by setting the shell to /bin/nologin
chsh -s /bin/nologin git
#2
#
# wait again for up to 20 min for all processes to complete
# (we *may* have just missed it between step 1 and 2)
#
countdown=$((60*20))
while pgrep -u git >/dev/null ; do
sleep 1
countdown=$((countdown-1))
if [ $countdown -eq 0 ] ; then
break
fi
done
#3
# kill too slow git sessions (This is actually safe)
if pgrep -u git >/dev/null ; then
killall -u git
sleep 30
fi
if pgrep -u git >/dev/null ; then
killall -9 -u git
sleep 10
fi
if pgrep -u git >/dev/null ; then
echo Failed to kill stale git $(pgrep -u git)
fi
#4
# make the lvm snapshot ...
#5
# change back the shell
chsh -s /usr/bin/git-shell git
Я очень хочу узнать, есть ли более стандартные решения или мое решение ошибочно.
Что-то в этом подходе кажется слишком надуманным. Я также не люблю думать о крайних случаях, таких как неработающие процессы. Кроме того, сервер может выйти из строя во время выполнения сценария, поэтому мне пришлось бы вернуть оболочку в git-shell, чтобы исправить это (либо через cron, либо при загрузке).
Я думаю, что правильный способ - использовать более подходящую стратегию резервного копирования. Зачем вам использовать снимки LVM, если вы можете просто создавать резервные копии с помощью самого git?
Простой, непроверенный пример
#!/bin/sh
cd /backups/git
for repo in $(ssh repo_host ls /srv/git); do
if [ ! -e $repo ]; then
git clone --mirror repo_host:/srv/git/$repo
else
(cd $repo; git fetch origin)
fi
done
Я не знаю стандартного решения для этого, и ваш подход кажется мне разумным. Несколько предостережений:
Я бы пошел дальше и заблокировал все входы в систему без полномочий root, поскольку вы действительно не хотите, чтобы пользователи входили в систему и выполняли какие-либо действия с вашим хранилищем, пока выполняются ваши операции LVM. К счастью, это довольно просто с /etc/nologin
, при условии, что ваша конфигурация PAM в /etc/pam.d
включает pam_nologin.so
. Многие дистрибутивы работают, но вы захотите протестировать. man pam_nologin
для подробностей.
Использовать pkill
вместо pgrep + killall. Он использует ту же логику сопоставления процессов и кода возврата, что и pgrep.
Вы перенаправляете STDOUT, но не STDERR. Один из приемов, который я использую, - это включение блоков команд, которые нужно перенаправить в {}
скобки и перенаправление вывода скобок. Просто помните, что эти скобки требуют возврата или ;
после последней команды, если вы делаете однострочник.
Пример №3:
{
echo foo
echo bar >&2 # output bar to STDERR
} >/dev/null 2>&1
Почему вы не блокируете вход по ssh на этот период? добавить в sshd_config:
#DenyGroups <a supplementary group for all git users>
затем в начале вашего резервного cronjob:
sed -i -e 's/^#DenyGroups/DenyGroups/' sshd_config
kill -HUP /var/run/sshd.pid
и переверните, когда закончите. Для пользователей, которые в настоящее время вошли в систему, я не знаю других вариантов, кроме как убить их сеансы, аналогично тому, что вы уже делаете. Или подождите, пока они выйдут из системы.