Как сменить владельца после выполнения перехвата после обновления?

Gitolite и веб-сервер хранятся на одном сервере. каталог /var/www/site является клоном репо "сайт". Пользователь Git состоит в группе www-data. У меня в /home/git/repositories/site.git/hooks/post-update hook:

#!/bin/sh    
unset GIT_DIR
cd /var/www/site && git pull origin master

Все работало отлично, но после "вытащить" все обновленные или новые файлы сменить владельца на git:git. Я не знаю, как сменить владельца без привилегий пользователя root. Какие-либо предложения?

Я нашел хороший подход (после обновления):

#!/bin/sh

PATH=/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
PROJECT="projectname"
GIT_URL="http://factory.domain.ru/git"

git update-server-info

if [ ! -f $1 ]; then
    exit 0
fi

while [ -n "$1" ]
do
    REF=`echo $1 | awk --field-separator="/" '{print $2}'`
    if [ $REF = "branches" -o $REF = "heads" ]; then
        BRANCH=`echo $1 | awk --field-separator="/" '{print $3}'`

        if [ ! -d /srv/www/$PROJECT/repo/master ]; then
            mkdir -p /srv/www/$PROJECT/repo
            GIT_SSL_NO_VERIFY=true git clone $GIT_URL/$PROJECT /srv/www/$PROJECT/repo/master
        fi

        if [ ! -d /srv/www/$PROJECT/repo/$BRANCH ]; then
            GIT_SSL_NO_VERIFY=true git clone -b $BRANCH $GIT_URL/$PROJECT /srv/www/$PROJECT/repo/$BRANCH
        else
            cd /srv/www/$PROJECT/repo/$BRANCH
            GIT_SSL_NO_VERIFY=true git fetch origin
            GIT_SSL_NO_VERIFY=true git reset --hard origin/$BRANCH
            GIT_SSL_NO_VERIFY=true git clean -d -f
            GIT_SSL_NO_VERIFY=true git checkout
            GIT_SSL_NO_VERIFY=true git pull
        fi
    fi
    shift
done

И "обновить":

#!/bin/sh

refname="$1"
oldrev="$2"
newrev="$3"

PROJECT="projectname"

# --- Safety check
if [ -z "$GIT_DIR" ]; then
        echo "Don't run this script from the command line." >&2
        echo " (if you want, you could supply GIT_DIR then run" >&2
        echo "  $0 <ref> <oldrev> <newrev>)" >&2
        exit 1
fi

if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
        echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
        exit 1
fi

# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
        newrev_type=delete
else
        newrev_type=$(git cat-file -t $newrev)
fi

BRANCH=`echo $1 | awk --field-separator="/" '{print $3}'`

delete () {
    mv /srv/www/$PROJECT/repo/$BRANCH /srv/www/$PROJECT/repo/$BRANCH.removed_by_git
    rm -rf /srv/www/$PROJECT/repo/$BRANCH.removed_by_git
}

case "$refname","$newrev_type" in
        refs/heads/*,delete)
                # delete branch
                delete
                ;;
        refs/remotes/*,delete)
                # delete tracking branch
                delete
                ;;
esac

exit 0

habrahabr.ru

3 ответа

Решение

Как сказал @ThiefMaster, вы не можете таким образом изменить владельца файла, но есть другой способ обойти эту проблему.

Когда вы выходите из какой-либо системы разработки (возможно, из той же системы, что и система развертывания, возможно, из какой-то другой) и используете gitolite для доступа, вы нажимаете ssh://git@server/repo (или некоторый вариант URL, но в любом случае, используя ssh для компьютера сервера gitolite, чтобы войти на этот сервер как пользователь git- часы настроены для входа в систему как gitolite но на основе вашего вопроса вы используете пользователя git). За исключением того, как работает аутентификация, однако, с точки зрения сервера, "developer@dev-host, толкающий меня, пользователь git", по сути, такой же, как "я, пользователь git, вытягивающий из developer@dev-host". Вот почему, когда вы запускаете команды вроде cd /var/www/site && git pull origin masterновые файлы принадлежат пользователю gitэто пользователь git выполняет слияние с "своим" локальным репо, а затем выполняет cd а также git pull наступает на другой репо.

Причина developer@dev-host может сш в git@server во-первых, это сервер ~git/.ssh/authorized_keys файл содержит открытый ключ для developer@dev-host (через репозиторий администратора gitolite и разнообразную магию, которая применяется при добавлении пользовательских ключей). Итак, предположим, пользователь git@server имеет свою собственную пару ключей ssh, и скажем, что вы хотите /var/www/site принадлежать пользователю www-site, Тогда если пользователь www-site имеет домашний каталог (/var/lib/www-site возможно) и этот домашний каталог имеет .ssh/authorized_keys пользователь, авторизующий файл gitключ, то пользователь git может ssh в качестве пользователя www-site, Ваш хук после обновления будет делать что-то вроде этого:

#! /bin/sh

# update running copy on real host
update_master() {
    ssh www-site@server "cd /var/www/site && git pull origin master"
}

# update test copy on test host
update_test() {
    ssh www-site@testhost "cd /var/www/site && git pull origin test"
}

for ref do
    case "$ref" in
    refs/heads/master) update_master;;
    refs/heads/test) update_test;;
    *) ;; # ignore other branches
done

(Я добавил код, чтобы распознать две конкретные ветви и выполнить обновления только для них. Примечание: ничего из этого не проверено.)

Вы не можете без предоставления пользователю корневого доступа - однако, вы можете сделать это через sudo поэтому он ничего не может сделать, кроме как сменить владельца этой папки.

После настройки sudo таким способом вы можете просто добавить sudo chown -R www-data:www-data /var/www/site на крючок.

# su requireduser -c 'git pull origin branch'

Другие вопросы по тегам