blob: de9893b79b748bb596de380227e0425015c51891 (
plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
#!/bin/bash
# alfplayer
# 2014-06-12
#
# Mirror the whole Parabola repository using rsync and keep snapshots
set -e
script_filename="$(basename "$0")"
# Create temporary log file
log_tmp="$(mktemp -p /var/tmp)"
# Default configuration values.
# They can be overridden by setting the variables in the calling environment.
# 1 to set, 0 to unset
: ${repo:=rsync://repo.parabola.nu:875/repos}
: ${base_dir:=/srv/http}
: ${parabola_dir:=${base_dir}/parabola}
: ${oldest_version:=10} # snapshots older than this one will be deleted (see also no_delete above)
: ${log_file:=${script_filename}.log}
#: ${mail_to:=your@mail.com} # comment out to disable
#: ${date_exclude:=2014.06.19} # disable running this script this date (see next line)
: ${forcerun:=0} # force running on excluded date
: ${terminal:=1} # outputs to stdout using rsync --progress (and logs to a file)
: ${no_delete:=0} # disable deletion of oldest snapshots
#: ${TZ:=UTC} # set time zone
export TZ
# Lock with flock (provided by util-linux), save to log file and send email on exit
LOCKFILE="/var/lock/${script_filename}"
LOCKFD=99
_lock() { flock -$1 $LOCKFD; }
# Wait until there is no process writing to ${log_tmp}
# Waiting can be necessary if command groups are not executed until the end
_wait_log_tmp() {
if [[ -e "${log_tmp}" ]] ; then
while fuser "${log_tmp}" > /dev/null ; do
sleep 0.2
done
fi
}
_no_more_locking() {
set +e
# Save exit status
es=$?
_wait_log_tmp
cat "${log_tmp}" >> "${log_file}"
if [[ $? == 0 ]] ; then
log_written=1
else
echo "=> ERROR: Failed to write to log file: ${log_file}" >&2
fi
if [[ -e ${parabola_dir}.tmp ]] ; then
echo "=> WARNING: Directory with partial transfer ${LOCAL}.tmp remains in file system"
fi
if [[ ${mail_to} ]] ; then
echo "=> Sending output to ${mail_to}"
mail -s "[$(hostname)] ${script_filename}" "${mail_to}" < "${log_tmp}"
fi
if [[ ${log_written} == 1 ]] ; then
rm -f "${log_tmp}"
fi
if [[ $es != 0 ]] ; then
echo "=> WARNING: Unsuccessful script termination. Exit status: $es"
if [[ ${mail_to} ]] ; then
echo "=> Sending error notification to ${mail_to}"
mail -s "[$(hostname)] ${script_filename} failed. See logged output." "${mail_to}" < /dev/null
fi
fi
_lock u
_lock xn && \
rm -f $LOCKFILE
}
_prepare_locking() { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }
_prepare_locking
# Lock now. The lock is disabled automatically when the script exits (with any error code).
if ! _lock xn ; then
echo "=> ERROR: Could not obtain lock. Exiting." >&2
exit 1
fi
date="$(date +%Y.%m.%d)"
current="${parabola_dir}-${date}"
local_useful=0
{
if [[ ${date_exclude} && ${forcerun} != 1 ]] ; then
if [[ $DATE == ${date_exclude} ]] ; then
echo "Manually disabled: ${date}. Exiting."
exit 0
fi
fi
# Test if ${parabola_dir} is an existing symlink pointing to an existing directory
if [[ -h ${parabola_dir} ]] ; then
last_path="$(readlink -f "${parabola_dir}")"
if [[ -d ${last_path} ]] ; then
last="${last_path##*/}"
local_useful=1
else
echo "=> ERROR: ${parabola_dir} is a symlink which does not point to an existing directory." >&2
exit 1
fi
else
echo "=> ERROR: ${parabola_dir} does not exist or is not a symlink." >&2
exit 1
fi
echo
echo "=> Creating snapshot for date ${date}"
if [[ -e "${current}" ]] ; then
echo "${current} already exists. Exiting." >&2
exit 1
fi
if [[ -e "${parabola_dir}".tmp ]] ; then
echo "${parabola_dir}.tmp already exists. Resuming."
else
cp -al "${last_path}" "${parabola_dir}".tmp
fi
} &> >(tee -a "${log_tmp}")
_wait_log_tmp
rsync "${repo}"/ -rtvlH ${terminal:+--progress} --log-file="${log_tmp}" --safe-links --delete --link-dest="$base_dir"/archlinux/ --link-dest="$parabola_dir" "$parabola_dir".tmp
{
cd "$base_dir"
echo "=> Delete versions older than the ${oldest_version} oldest version"
delete_list=( $(for dir in parabola-* ; do echo "$(find "$dir" -type f -printf '%T@\n' | sort -n | tail -1) $dir" ; done | awk '{print $2}' | head -n -"${oldest_version}") )
for dir in ${delete_list[@]} ; do
if [[ ${no_delete} != 1 ]] ; then
echo "$dir"
rm -rf "$dir"
else
echo "DRY-RUN: rm -rf $dir"
fi
done
echo "=> Start serving the new repository version"
mv "${parabola_dir}.tmp" "${current}"
if [[ ${local_useful} == 1 ]] ; then
echo " => Deleting ${parabola_dir} symlink"
rm -rf "${parabola_dir}"
fi
# Create symlink
echo " => Creating symlink ${current} to ${parabola_dir}"
ln -s ${current##*/} ${parabola_dir}
echo "=> Disk space report"
df -h /
echo "=> ${script_filename} finished successfully. Finish time: $(date --rfc-3339=seconds)"
} &> >(tee -a "${log_tmp}")
_wait_log_tmp
|