Skip to content

Commit a9599e7

Browse files
committed
Merge pull request #41 from github/upstream-merge
Upstream merge
2 parents bd8dfac + 46b4676 commit a9599e7

File tree

8 files changed

+127
-86
lines changed

8 files changed

+127
-86
lines changed

backup.config-example

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@ GHE_NUM_SNAPSHOTS=10
3232
# Any extra options passed to the rsync command. Nothing required by default.
3333
#
3434
#GHE_EXTRA_RSYNC_OPTS=""
35-
#
35+
3636
# If set to 'no', GHE_DATA_DIR will not be created automatically
3737
# and restore/backup will exit 8
3838
#
3939
#GHE_CREATE_DATA_DIR=yes
40+
41+
# If set to 'yes', git fsck will run on the repositories
42+
# and print some additional info.
43+
#
44+
# WARNING: do not enable this, only useful for debugging/development
45+
#GHE_BACKUP_FSCK=no

bin/ghe-backup

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ if $GHE_MAINTENANCE_MODE_ENABLED; then
210210
GHE_MAINTENANCE_MODE_ENABLED=false
211211
fi
212212

213+
# git fsck repositories after the backup
214+
if [ "$GHE_BACKUP_FSCK" = "yes" ]; then
215+
ghe-backup-fsck $GHE_SNAPSHOT_DIR ||
216+
failures="$failures fsck"
217+
fi
218+
213219
# If everything was successful, mark the snapshot as complete, update the
214220
# current symlink to point to the new snapshot and prune expired and failed
215221
# snapshots.

share/github-backup-utils/ghe-backup-config

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ BACKUP_UTILS_VERSION="$(cat share/github-backup-utils/version)"
2121
# Add the bin and share/github-backup-utils dirs to PATH
2222
PATH="$GHE_BACKUP_ROOT/bin:$GHE_BACKUP_ROOT/share/github-backup-utils:$PATH"
2323

24-
# The backup config file. This may be set in the environment.
25-
: ${GHE_BACKUP_CONFIG:="$GHE_BACKUP_ROOT/backup.config"}
26-
2724
# Parse out -v (verbose) argument
2825
if [ "$1" = "-v" ]; then
2926
GHE_VERBOSE=true
@@ -43,10 +40,11 @@ fi
4340
# backup.config value when set.
4441
GHE_HOSTNAME_PRESERVE="$GHE_HOSTNAME"
4542

46-
# Source in the backup config file from the local working copy location first
47-
# and then falling back to the system location.
43+
# Source in the backup config file from the copy specified in the environment
44+
# first and then fall back to the backup-utils root, home directory and system.
4845
config_found=false
49-
for f in "$GHE_BACKUP_CONFIG" "/etc/github-backup-utils/backup.config"; do
46+
for f in "$GHE_BACKUP_CONFIG" "$GHE_BACKUP_ROOT/backup.config" \
47+
"$HOME/.github-backup-utils/backup.config" "/etc/github-backup-utils/backup.config"; do
5048
if [ -f "$f" ]; then
5149
GHE_BACKUP_CONFIG="$f"
5250
. "$GHE_BACKUP_CONFIG"
@@ -58,7 +56,9 @@ done
5856
# Check that the config file exists before we source it in.
5957
if ! $config_found; then
6058
echo "Error: No backup configuration file found. Tried:" 1>&2
61-
echo " - $GHE_BACKUP_CONFIG" 1>&2
59+
[ -n "$GHE_BACKUP_CONFIG" ] && echo " - $GHE_BACKUP_CONFIG" 1>&2
60+
echo " - $GHE_BACKUP_ROOT/backup.config" 1>&2
61+
echo " - $HOME/.github-backup-utils/backup.config" 1>&2
6262
echo " - /etc/github-backup-utils/backup.config" 1>&2
6363
exit 2
6464
fi
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env bash
2+
#/ Usage: ghe-backup-fsck <snapshot-dir> [--print-nwo]
3+
#/
4+
#/ Run git fsck on backed up repositories.
5+
set -e
6+
7+
# Bring in the backup configuration
8+
cd $(dirname "$0")/../..
9+
. share/github-backup-utils/ghe-backup-config
10+
11+
echo "Running git fsck on repos..."
12+
13+
# Verify git is available.
14+
if ! git --version 1>/dev/null 2>&1; then
15+
echo "Error: git not found." 1>&2
16+
exit 1
17+
fi
18+
19+
sdir=$1
20+
repos=0
21+
errors=0
22+
log=$(mktemp)
23+
t_start=$(date +%s)
24+
25+
if [ -z "$sdir" ] || [ ! -d "$sdir" ]; then
26+
print_usage
27+
fi
28+
29+
if [ ! -d "$sdir/repositories" ]; then
30+
echo "Error: $sdir is not a valid snapshot." >&2
31+
exit 1
32+
fi
33+
34+
for repo in $(find $sdir/repositories/ -type d -name \*.git); do
35+
repos=$(($repos+1))
36+
before_time=$(date +%s)
37+
38+
status=$(
39+
set -e
40+
41+
cd $repo
42+
43+
nwo="-"
44+
if [ "$2" = "--print-nwo" ] && [ -f info/nwo ]; then
45+
nwo="$(cat info/nwo)"
46+
fi
47+
48+
if [ ! -f objects/info/alternates ] || grep -q '^\.\.' objects/info/alternates; then
49+
git fsck --no-dangling >$log 2>&1 && {
50+
echo "OK $repo $nwo"; exit
51+
}
52+
else
53+
GIT_ALTERNATE_OBJECT_DIRECTORIES=../network.git/objects git fsck --no-dangling >$log 2>&1 && {
54+
echo "WARN $repo $nwo (alternates absolute path)"; exit
55+
}
56+
fi
57+
58+
echo "ERROR $repo $nwo"
59+
)
60+
61+
elapsed_time=$(($(date +%s) - before_time))
62+
63+
if [[ ! "$status" =~ ^OK ]] || [ $elapsed_time -gt 5 ]; then
64+
echo "$status ${elapsed_time}s" 1>&3
65+
[ -n "$GHE_VERBOSE" ] && cat $log
66+
fi
67+
68+
case "$status" in
69+
OK*)
70+
;;
71+
ERROR*)
72+
errors=$(($errors+1))
73+
;;
74+
esac
75+
76+
done
77+
78+
echo "* Repos verified: $repos, Errors: $errors, Took: $(($(date +%s) - $t_start))s"
79+
80+
rm -f $log

share/github-backup-utils/ghe-backup-repositories-cluster

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -84,68 +84,26 @@ echo "$config" > "$config_file"
8484

8585
opts="$GHE_EXTRA_SSH_OPTS -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PasswordAuthentication=no"
8686

87-
# Remote sync-in-progress file location. When this file exists, Git GC
88-
# operations are disabled on the GitHub instance.
89-
sync_in_progress_file="$GHE_REMOTE_DATA_USER_DIR/repositories/.sync_in_progress"
90-
9187
# Make sure root backup dir exists if this is the first run
9288
mkdir -p "$backup_dir"
9389

9490
# Removes the remote sync-in-progress file on exit, re-enabling GC operations
9591
# on the remote instance.
9692
cleanup() {
93+
# Enable remote GC operations
9794
for hostname in $hostnames; do
98-
ghe-ssh -F $config_file "$hostname:122" -- "sudo rm -f '$sync_in_progress_file'"
95+
ghe-gc-enable -F $config_file $hostname:$port
9996
done
10097
rm -f $config_file
10198
}
10299
trap 'cleanup' EXIT
103100
trap 'exit $?' INT # ^C always terminate
104101

105-
wait_pids=""
102+
# Disable remote GC operations
106103
for hostname in $hostnames; do
107-
# Touch the sync-in-progress file, disabling GC operations, and wait for all
108-
# active GC processes to finish on the remote side.
109-
echo "
110-
set -e
111-
sudo -u git touch '$sync_in_progress_file'
112-
113-
sanity=0
114-
while [ \$sanity -lt $GHE_GIT_COOLDOWN_PERIOD ]; do
115-
# note: the bracket synta[x] below is to prevent matches against the
116-
# grep process itself.
117-
if ps axo args | grep -E -e '^git( -.*)? nw-repac[k]( |$)' -e '^git( -.*)? g[c]( |$)' >/dev/null; then
118-
sleep 1
119-
sanity=\$(( sanity + 1 ))
120-
else
121-
exit 0
122-
fi
123-
done
124-
exit 7
125-
" | ssh -q $opts -p $port -F $config_file -l $user $hostname -- /bin/sh
126-
wait_pids="$wait_pids $hostname:$!"
127-
done
128-
129-
# strip leading space
130-
wait_pids="$(echo -e "${wait_pids}" | sed -e 's/^[[:space:]]*//')"
131-
132-
# wait for jobs one by one, bail on the first one
133-
for pid in $wait_pids; do
134-
# pull out pid:hostname pairs into vars
135-
wait_hostname="$(echo $pid | awk 'BEGIN {FS = ":" }; { print $1; }')"
136-
wait_pid="$(echo $pid | awk 'BEGIN {FS = ":" }; { print $2; }')"
137-
wait $wait_pid || {
138-
res=$?
139-
if [ $res = 7 ]; then
140-
echo "Error: Git GC processes remain after $GHE_GIT_COOLDOWN_PERIOD seconds on host: $wait_hostname. Aborting..." 1>&2
141-
fi
142-
exit $res
143-
}
144-
unset wait_hostname wait_pid
104+
ghe-gc-disable -F $config_file $hostname:$port
145105
done
146106

147-
unset wait_pids
148-
149107
# If we have a previous increment, avoid transferring existing files via rsync's
150108
# --link-dest support. This also decreases physical space usage considerably.
151109
if [ -d "$backup_current" ]; then

share/github-backup-utils/ghe-backup-repositories-rsync

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,46 +51,20 @@ fi
5151
# Perform a host-check and establish GHE_REMOTE_XXX variables.
5252
ghe_remote_version_required "$host"
5353

54-
# Remote sync-in-progress file location. When this file exists, Git GC
55-
# operations are disabled on the GitHub instance.
56-
sync_in_progress_file="$GHE_REMOTE_DATA_USER_DIR/repositories/.sync_in_progress"
57-
5854
# Make sure root backup dir exists if this is the first run
5955
mkdir -p "$backup_dir"
6056

6157
# Removes the remote sync-in-progress file on exit, re-enabling GC operations
6258
# on the remote instance.
6359
cleanup() {
64-
ghe-ssh "$host" -- "sudo rm -f '$sync_in_progress_file'"
60+
# Enable remote GC operations
61+
ghe-gc-enable $host
6562
}
6663
trap 'cleanup' EXIT
6764
trap 'exit $?' INT # ^C always terminate
6865

69-
# Touch the sync-in-progress file, disabling GC operations, and wait for all
70-
# active GC processes to finish on the remote side.
71-
echo "
72-
set -e
73-
sudo -u git touch '$sync_in_progress_file'
74-
75-
sanity=0
76-
while [ \$sanity -lt $GHE_GIT_COOLDOWN_PERIOD ]; do
77-
# note: the bracket synta[x] below is to prevent matches against the
78-
# grep process itself.
79-
if ps axo args | grep -E -e '^git( -.*)? nw-repac[k]( |$)' -e '^git( -.*)? g[c]( |$)' >/dev/null; then
80-
sleep 1
81-
sanity=\$(( sanity + 1 ))
82-
else
83-
exit 0
84-
fi
85-
done
86-
exit 7
87-
" | ghe-ssh "$host" -- /bin/sh || {
88-
res=$?
89-
if [ $res = 7 ]; then
90-
echo "Error: Git GC processes remain after $GHE_GIT_COOLDOWN_PERIOD seconds. Aborting..." 1>&2
91-
fi
92-
exit $res
93-
}
66+
# Disable remote GC operations
67+
ghe-gc-disable $host
9468

9569
# Transfer repository data from a GitHub instance to the current snapshot
9670
# directory, using a previous snapshot to avoid transferring files that have

share/github-backup-utils/ghe-backup-store-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ if [ -d .git ]; then
1414
version_info="$version_info:$ref"
1515
fi
1616
echo "$version_info" |
17-
ghe-ssh "$GHE_HOSTNAME" -- "sudo dd of=$GHE_REMOTE_DATA_USER_DIR/common/backup-utils-version"
17+
ghe-ssh "$GHE_HOSTNAME" -- "sudo dd of=$GHE_REMOTE_DATA_USER_DIR/common/backup-utils-version >/dev/null 2>&1"
1818
fi

test/test-ghe-backup.sh

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,15 @@ fi
5454
mkdir "$GHE_REMOTE_DATA_USER_DIR/repositories"
5555
cd "$GHE_REMOTE_DATA_USER_DIR/repositories"
5656
mkdir alice bob
57-
mkdir alice/repo1.git alice/repo2.git bob/repo3.git
57+
mkdir alice/repo1.git alice/repo2.git bob/repo3.git alice/broken.git
5858

5959
# Initialize test repositories with a fake commit
6060
for repo in */*.git; do
6161
git init -q --bare "$repo"
6262
git --git-dir="$repo" --work-tree=. commit -q --allow-empty -m 'test commit'
6363
done
64+
# Break a repo to test fsck
65+
rm -f alice/broken.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904
6466

6567
begin_test "ghe-backup first snapshot"
6668
(
@@ -303,3 +305,18 @@ begin_test "ghe-backup empty git-hooks directory"
303305
[ ! "$(grep "[l]ink-dest arg does not exist" $TRASHDIR/out)" ]
304306
)
305307
end_test
308+
309+
begin_test "ghe-backup fsck"
310+
(
311+
set -e
312+
313+
export GHE_BACKUP_FSCK=yes
314+
ghe-backup | grep -q "Repos verified: 4, Errors: 1, Took:"
315+
# Verbose mode disabled by default
316+
! ghe-backup | grep -q "missing tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904"
317+
ghe-backup -v | grep -q "missing tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904"
318+
319+
export GHE_BACKUP_FSCK=no
320+
! ghe-backup | grep -q "Repos verified:"
321+
)
322+
end_test

0 commit comments

Comments
 (0)