]>
Commit | Line | Data |
---|---|---|
d4ab9e58 | 1 | #!/bin/bash |
2 | # | |
3 | # - script to sync a group of files on alien with a local cache | |
4 | # downloads only new and updated files | |
5 | # - by default it mirrors the directory structure in a specified local location | |
6 | # (the local chache location and paths can be manipulated.) | |
7 | # - needs a configured config file (by default alienSync.config) | |
8 | # and a working alien environment (token and at least $ALIEN_DIR or $ALIEN_ROOT set) | |
9 | # | |
10 | # origin: Mikolaj Krzewicki, mikolaj.krzewicki@cern.ch | |
11 | # | |
c1fbf113 | 12 | if [ ${BASH_VERSINFO} -lt 4 ]; then |
13 | echo "bash version >= 4 needed, you have ${BASH_VERSION}, exiting..." | |
14 | exit 1 | |
15 | fi | |
16 | ||
d4ab9e58 | 17 | main() |
18 | { | |
19 | if [[ $# -lt 1 ]]; then | |
d56eeaab | 20 | echo "Usage: ${0##*/} configFile=/path/to/config" |
823ca2e7 | 21 | echo "expert: ${0##*/} alienFindCommand=\"alien_find /some/path/ file\" [opt=value]" |
22 | echo " ${0##*/} alienFindCommand=\"alien_find /some/path/ file\" localPathPrefix=\${PWD}" | |
23 | echo | |
ec4c302d | 24 | echo "by default files are downloaded to current dir, or \${alienSync_localPathPrefix}, if set." |
823ca2e7 | 25 | echo "At least specify alienFindCommand, either on command line or in the configFile." |
ec4c302d | 26 | echo "the logs go by default to localPathPrefix/alienSyncLogs" |
d4ab9e58 | 27 | return |
28 | fi | |
2c39ca2b | 29 | |
d4ab9e58 | 30 | # try to load the config file |
d56eeaab | 31 | #[[ ! -f $1 ]] && echo "config file $1 not found, exiting..." | tee -a $logFile && exit 1 |
32 | if ! parseConfig "$@"; then return 1; fi | |
33 | ||
2c39ca2b | 34 | [[ -z ${alienFindCommand} ]] && echo "alienFindCommand not defined!" && return 1 |
d56eeaab | 35 | |
6c8c572d | 36 | #if not set, use the default group |
37 | [[ -z ${alienSyncFilesGroupOwnership} ]] && alienSyncFilesGroupOwnership=$(id -gn) | |
d4ab9e58 | 38 | |
39 | # do some accounting | |
1e600c4f | 40 | [[ ! -d $logOutputPath ]] && echo "logOutputPath not available, creating..." && mkdir -p $logOutputPath && chgrp ${alienSyncFilesGroupOwnership} ${logOutputPath} |
d4ab9e58 | 41 | [[ ! -d $logOutputPath ]] && echo "could not create log dir, exiting..." && exit 1 |
42 | dateString=$(date +%Y-%m-%d-%H-%M) | |
43 | logFile=$logOutputPath/alienSync-$dateString.log | |
44 | echo "$0 $@"|tee -a $logFile | |
45 | echo ""|tee -a $logFile | |
46 | echo log: $logFile | |
47 | ||
48 | #be nice and allow group members access as well (002 will create dirs with 775 and files with 664) | |
49 | umask 0002 | |
50 | ||
51 | #lock | |
52 | lockFile=$logOutputPath/runningNow.lock | |
a43cff2f | 53 | [[ -f $lockFile && ${allowConcurrent} -ne 1 ]] && echo "locked. Another process running? ($lockFile)" | tee -a $logFile && exit 1 |
d4ab9e58 | 54 | touch $lockFile |
55 | [[ ! -f $lockFile ]] && echo "unable to create lock. exiting..." | tee -a $logFile && exit 1 | |
56 | ||
57 | #redirect all output to a log | |
58 | if [[ $allOutputToLog -eq 1 ]]; then | |
59 | exec 6>&1 | |
60 | exec 1>$logFile 2>&1 | |
61 | fi | |
2c39ca2b | 62 | |
d4ab9e58 | 63 | newFilesList=$logOutputPath/"newFiles.list" |
64 | rm -f $newFilesList | |
65 | touch $newFilesList | |
66 | redoneFilesList=$logOutputPath/"redoneFiles.list" | |
67 | rm -f $redoneFilesList | |
68 | touch $redoneFilesList | |
69 | updatedFilesList="${logOutputPath}/updatedFiles.list" | |
ec825842 | 70 | failedDownloadList="${logOutputPath}/failedDownload.list" |
71 | touch ${failedDownloadList} | |
72 | ||
d4ab9e58 | 73 | |
74 | # check the config | |
75 | [[ -z $alienFindCommand ]] && echo "alienFindCommand not defined, exiting..." && exitScript 1 | |
76 | [[ -z ${localPathPrefix} ]] && echo "localPathPrefix not defined, exiting..." && exitScript 1 | |
77 | [[ -z $logOutputPath ]] && echo "logOutputPath not defined, exiting..." && exitScript 1 | |
78 | [[ -z $secondsToSuicide ]] && echo "setting default secondsToSuicide of 10 hrs..." && secondsToSuicide=$(( 10*3600 )) | |
79 | ||
80 | # init alien | |
d4ab9e58 | 81 | [[ -z $ALIEN_ROOT && -n $ALIEN_DIR ]] && ALIEN_ROOT=$ALIEN_DIR |
82 | #if ! haveAlienToken; then | |
83 | # $ALIEN_ROOT/api/bin/alien-token-destroy | |
84 | $ALIEN_ROOT/api/bin/alien-token-init $alienUserName | |
85 | #fi | |
86 | #if ! haveAlienToken; then | |
87 | # if [[ $allOutputToLog -eq 1 ]]; then | |
88 | # exec 1>&6 6>&- | |
89 | # fi | |
90 | # echo "problems getting token! exiting..." | tee -a $logFile | |
91 | # exitScript 1 | |
92 | #fi | |
93 | #ls -ltr /tmp/gclient_env_$UID | |
94 | #cat /tmp/gclient_env_$UID | |
6c8c572d | 95 | source /tmp/gclient_env_$UID |
d4ab9e58 | 96 | |
97 | #set a default timeout for grid access | |
98 | [[ -z $copyTimeout ]] && copyTimeout=600 | |
99 | export GCLIENT_COMMAND_MAXWAIT=$copyTimeout | |
100 | ||
101 | localAlienDatabase=$logOutputPath/localAlienDatabase.list | |
102 | localFileList=$logOutputPath/localFile.list | |
103 | ||
104 | alienFileListCurrent=$logOutputPath/alienFileDatabase.list | |
105 | [[ ! -f $localFileList ]] && touch $localFileList | |
106 | candidateLocalFileDatabase=$logOutputPath/candidateLocalFileDatabase.list | |
107 | ||
108 | #here we produce the current alien file list | |
109 | if [[ -n ${useExistingAlienFileDatabase} && -f ${localAlienDatabase} ]]; then | |
110 | #we use the old one | |
111 | echo "using ${localAlienDatabase} instead of full alien search" | |
112 | echo cp -f ${localAlienDatabase} ${alienFileListCurrent} | |
113 | cp -f ${localAlienDatabase} ${alienFileListCurrent} | |
114 | else | |
115 | #we make a new one | |
116 | echo "eval $alienFindCommand > $alienFileListCurrent" | |
117 | eval "$alienFindCommand" > $alienFileListCurrent | |
118 | fi | |
119 | ||
120 | echo "number of files in the collection: $(wc -l $alienFileListCurrent)" | |
121 | #create a list of candidate destination locations | |
122 | #this is in case there are more files on alien trying to get to the same local destination | |
123 | #in which case we take the one with the youngest ctime (later in code) | |
124 | if [[ -n ${destinationModifyCommand} ]]; then | |
125 | echo eval "cat $alienFileListCurrent | ${destinationModifyCommand} | sed \"s,^,${localPathPrefix},\" > ${candidateLocalFileDatabase}" | |
126 | eval "cat $alienFileListCurrent | ${destinationModifyCommand} | sed \"s,^,${localPathPrefix},\" > ${candidateLocalFileDatabase}" | |
127 | fi | |
128 | ||
129 | #logic is: if file list is missing we force the md5 recalculation | |
130 | [[ ! -f $localAlienDatabase ]] && forceLocalMD5recalculation=1 && echo "forcing local MD5 sum recalculation" && cp -f $alienFileListCurrent $localAlienDatabase | |
131 | ||
132 | #since we grep through the files frequently, copy some stuff to tmpfs for fast access | |
133 | tmp=$(mktemp -d 2>/dev/null) | |
134 | if [[ -d $tmp ]]; then | |
135 | cp $localAlienDatabase $tmp | |
136 | cp $localFileList $tmp | |
137 | cp $alienFileListCurrent $tmp | |
138 | [[ -f ${candidateLocalFileDatabase} ]] && cp ${candidateLocalFileDatabase} ${tmp} | |
139 | else | |
140 | tmp=$logOutputPath | |
141 | fi | |
142 | ||
143 | echo "starting downloading:" | |
144 | lineNumber=0 | |
145 | alienFileCounter=0 | |
146 | localFileCounter=0 | |
147 | downloadedFileCounter=0 | |
148 | while read -r alienFile md5alien timestamp size | |
149 | do | |
150 | ((lineNumber++)) | |
151 | ||
152 | #sometimes the md5 turns out empty and is then stored as a "." to avoid problems parsing | |
153 | [[ "$md5alien" =~ "." ]] && md5alien="" | |
154 | ||
155 | [[ -n $timeStampInLog ]] && date | |
156 | [[ $SECONDS -ge $secondsToSuicide ]] && echo "$SECONDS seconds passed, exiting by suicide..." && break | |
157 | [[ "$alienFile" != "/"*"/"?* ]] && echo "WARNING: read line not path-like: $alienFile" && continue | |
158 | ((alienFileCounter++)) | |
159 | destination=${localPathPrefix}/${alienFile} | |
160 | destination=${destination//\/\///} #remove double slashes | |
161 | [[ -n ${destinationModifyCommand} ]] && destination=$( eval "echo ${destination} | ${destinationModifyCommand}" ) | |
162 | destinationdir=${destination%/*} | |
163 | [[ -n $softLinkName ]] && softlinktodestination=${destinationdir}/${softLinkName} | |
164 | tmpdestination="${destination}.aliensyncTMP" | |
a43cff2f | 165 | |
166 | #if we allow concurrent running (DANGEROUS) check if somebody is already trying to process this file | |
167 | if [[ -f ${tmpdestination} && ${allowConcurrent} -eq 1 ]]; then | |
168 | echo "$tmpdestination exists - concurrent donwload? skipping..." | |
169 | continue | |
170 | fi | |
d4ab9e58 | 171 | |
172 | if [[ -n ${destinationModifyCommand} ]]; then | |
173 | #find the candidate in the database, in case there are more files trying to go to the same | |
174 | #place due to $destinationModifyCommand which alters the final path, find the one | |
175 | #with the largest ctime (3rd field in the database list) and check if that is the current one | |
176 | #if not - skip | |
177 | #echo grep -n ${destination} $candidateLocalFileDatabase | sed "s/:/ /" | sort -rk4 | |
178 | #grep -n ${destination} $candidateLocalFileDatabase| sed "s/:/ /" | sort -rk4 | |
179 | #this guy contains: index of the original entry, local file name, md5, ctime | |
180 | candidateDBrecord=($(grep -n ${destination} $tmp/${candidateLocalFileDatabase##*/}| sed "s/:/ /" | sort -rk4|head -n1 )) | |
181 | originalEntryIndex=${candidateDBrecord[0]} | |
182 | [[ $lineNumber -ne $originalEntryIndex ]] && continue | |
183 | fi | |
2c39ca2b | 184 | |
d4ab9e58 | 185 | redownloading="" |
186 | if [[ -f ${destination} ]]; then | |
9c9427a5 | 187 | #soft link the downloaded file (maybe to provide a consistent link to the latest version) |
188 | if [[ -n $softlinktodestination ]]; then | |
189 | echo ln -sf ${destination} ${softlinktodestination} | |
190 | ln -sf ${destination} ${softlinktodestination} | |
d4ab9e58 | 191 | fi |
192 | ((localFileCounter++)) | |
193 | ||
194 | localDBrecord=($(grep $alienFile $tmp/${localAlienDatabase##*/})) | |
195 | md5local=${localDBrecord[1]} | |
196 | ||
197 | #sometimes the md5 turns out empty and is then stored as a "." to avoid problems parsing | |
198 | [[ "$md5local" =~ "." ]] && md5local="" | |
199 | ||
200 | if [[ $forceLocalMD5recalculation -eq 1 || -z $md5local ]]; then | |
c1fbf113 | 201 | md5recalculated=$(checkMD5sum ${destination}) |
d4ab9e58 | 202 | [[ "$md5local" != "$md5recalculated" ]] && echo "WARNING: local copy change ${destination}" |
203 | md5local=${md5recalculated} | |
204 | fi | |
205 | if [[ "$md5local" == "$md5alien" && -n $md5alien ]]; then | |
206 | echo "OK ${destination} $md5alien" | |
207 | if ! grep -q ${destination} $tmp/${localFileList##*/}; then | |
208 | echo ${destination} >> $localFileList | |
209 | fi | |
210 | continue | |
211 | fi | |
212 | if [[ -z $md5alien ]]; then | |
213 | if ! grep -q ${destination} $tmp/${localFileList##*/}; then | |
214 | echo ${destination} >> $localFileList | |
215 | fi | |
216 | echo "WARNING: missing alien md5, leaving the local file as it is" | |
217 | continue | |
218 | fi | |
219 | echo "WARNING: md5 mismatch ${destination}" | |
220 | echo " $md5local $md5alien" | |
221 | redownloading=1 | |
222 | fi | |
223 | ||
224 | [[ -f $tmpdestination ]] && echo "WARNING: stale $tmpdestination, removing" && rm $tmpdestination | |
225 | ||
1e600c4f | 226 | mkdir -p ${destinationdir} && chgrp ${alienSyncFilesGroupOwnership} ${destinationdir} |
d4ab9e58 | 227 | [[ ! -d $destinationdir ]] && echo cannot access $destinationdir && continue |
228 | ||
229 | #check token | |
230 | #if ! haveAlienToken; then | |
231 | # $ALIEN_ROOT/api/bin/alien-token-init $alienUserName | |
232 | # #source /tmp/gclient_env_$UID | |
233 | #fi | |
2c39ca2b | 234 | |
d4ab9e58 | 235 | export copyMethod |
236 | export copyScript | |
237 | export copyTimeout | |
238 | export copyTimeoutHard | |
239 | echo copyFromAlien "$alienFile" "$tmpdestination" | |
240 | [[ $pretend -eq 1 ]] && continue | |
241 | copyFromAlien $alienFile $tmpdestination | |
242 | chgrp ${alienSyncFilesGroupOwnership} $tmpdestination | |
243 | ||
244 | # if we didn't download remove the destination in case we tried to redownload | |
245 | # a corrupted file | |
246 | [[ ! -f $tmpdestination ]] && echo "file not downloaded" && rm -f ${destination} && continue | |
247 | ||
248 | downloadOK=0 | |
249 | #verify the downloaded md5 if available, validate otherwise... | |
250 | if [[ -n $md5alien ]]; then | |
c1fbf113 | 251 | md5recalculated=$(checkMD5sum ${tmpdestination}) |
252 | if [[ ${md5alien} == ${md5recalculated} ]]; then | |
d4ab9e58 | 253 | echo "OK md5 after download" |
254 | downloadOK=1 | |
255 | else | |
6c8c572d | 256 | echo "failed verifying md5 $md5alien of $tmpdestination" |
d4ab9e58 | 257 | fi |
258 | else | |
259 | downloadOK=1 | |
260 | fi | |
261 | ||
262 | #handle zip files - check the checksums | |
263 | if [[ $alienFile =~ '.zip' && $downloadOK -eq 1 ]]; then | |
264 | echo "checking integrity of zip archive $tmpdestination" | |
265 | if unzip -t $tmpdestination; then | |
266 | downloadOK=1 | |
267 | else | |
268 | downloadOK=0 | |
269 | fi | |
270 | fi | |
271 | ||
272 | if [[ $downloadOK -eq 1 ]]; then | |
273 | echo mv $tmpdestination ${destination} | |
274 | mv $tmpdestination ${destination} | |
275 | chgrp ${alienSyncFilesGroupOwnership} ${destination} | |
276 | ((downloadedFileCounter++)) | |
277 | if [[ -n $softlinktodestination ]]; then | |
278 | echo ln -s ${destination} $softlinktodestination | |
279 | ln -s ${destination} $softlinktodestination | |
280 | fi | |
281 | [[ -z $redownloading ]] && echo ${destination} >> $newFilesList | |
282 | [[ -n $redownloading ]] && echo ${destination} >> $redoneFilesList | |
283 | if ! grep -q ${destination} $tmp/${localFileList##*/}; then | |
284 | echo ${destination} >> $localFileList | |
285 | fi | |
286 | [[ -n ${postCommand} ]] && ( cd ${destinationdir}; eval "${postCommand}" ) | |
ec825842 | 287 | if grep -q ${alienFile} ${failedDownloadList}; then |
288 | echo "removing ${alienFile} from ${failedDownloadList}" | |
289 | grep -v ${alienFile} ${failedDownloadList} >tmpUpdatedFailed | |
290 | mv tmpUpdatedFailed ${failedDownloadList} | |
291 | fi | |
d4ab9e58 | 292 | else |
293 | echo "download not validated, NOT moving to ${destination}..." | |
6c8c572d | 294 | echo "removing $tmpdestination" |
d4ab9e58 | 295 | rm -f $tmpdestination |
ec825842 | 296 | echo ${alienFile} >> ${failedDownloadList} |
d4ab9e58 | 297 | continue |
298 | fi | |
299 | ||
a43cff2f | 300 | [[ -f $tmpdestination ]] && echo "WARNING: tmpdestination should not still be here! removing..." && rm -r ${tmpdestination} |
301 | ||
d4ab9e58 | 302 | if [[ $unzipFiles -eq 1 ]]; then |
200fd0c8 | 303 | echo unzip -o ${destination} -d ${destinationdir} |
304 | unzip -o ${destination} -d ${destinationdir} | |
d4ab9e58 | 305 | fi |
306 | ||
307 | echo | |
308 | done < ${alienFileListCurrent} | |
309 | ||
310 | [[ $alienFileCounter -gt 0 ]] && mv -f $alienFileListCurrent $localAlienDatabase | |
2c39ca2b | 311 | |
312 | echo "${0##*/} DONE" | |
d4ab9e58 | 313 | |
314 | if [[ $allOutputToLog -eq 1 ]]; then | |
315 | exec 1>&6 6>&- | |
316 | fi | |
317 | ||
318 | cat ${newFilesList} ${redoneFilesList} > ${updatedFilesList} | |
2c39ca2b | 319 | |
d4ab9e58 | 320 | echo alienFindCommand: |
321 | echo " $alienFindCommand" | |
322 | echo | |
323 | echo "files on alien: $alienFileCounter" | |
324 | echo "local files before: $localFileCounter" | |
325 | echo "files downloaded: $downloadedFileCounter" | |
326 | echo | |
327 | echo "new files:" | |
328 | echo | |
329 | cat $newFilesList | |
330 | echo | |
331 | echo "redone files:" | |
332 | echo | |
333 | cat $redoneFilesList | |
ec825842 | 334 | echo |
335 | echo | |
336 | ||
337 | #output the list of failed files to stdout, so the cronjob can mail it | |
338 | echo '###############################' | |
339 | echo "failed to download from alien:" | |
340 | echo | |
341 | local tmpfailed=$(mktemp) | |
342 | [[ "$(cat ${failedDownloadList} | wc -l)" -gt 0 ]] && sort ${failedDownloadList} | uniq -c | awk 'BEGIN{print "#tries\t file" }{print $1 "\t " $2}' | tee ${tmpfailed} | |
343 | ||
344 | [[ -n ${MAILTO} ]] && echo $logFile | mail -s "alienSync ${alienFindCommand} done" ${MAILTO} | |
d4ab9e58 | 345 | |
ec825842 | 346 | echo |
347 | echo | |
348 | echo '###############################' | |
349 | echo "eval ${executeEnd}" | |
350 | eval "${executeEnd}" | |
d4ab9e58 | 351 | |
352 | exitScript 0 | |
353 | } | |
354 | ||
355 | exitScript() | |
356 | { | |
357 | echo | |
358 | echo removing $lockFile | |
359 | rm -f $lockFile | |
360 | echo removing $tmp | |
361 | rm -rf $tmp | |
362 | exit $1 | |
363 | } | |
364 | ||
365 | alien_find() | |
366 | { | |
367 | # like a regular alien_find command | |
c1fbf113 | 368 | # output is a list with md5 sums and ctimes |
d4ab9e58 | 369 | executable="$ALIEN_ROOT/api/bin/gbbox find" |
370 | [[ ! -x ${executable% *} ]] && echo "### error, no $executable..." && return 1 | |
371 | [[ -z $logOutputPath ]] && logOutputPath="./" | |
372 | ||
373 | maxCollectionLength=10000 | |
374 | ||
375 | export GCLIENT_COMMAND_MAXWAIT=600 | |
376 | export GCLIENT_COMMAND_RETRY=20 | |
377 | export GCLIENT_SERVER_RESELECT=4 | |
378 | export GCLIENT_SERVER_RECONNECT=2 | |
379 | export GCLIENT_RETRY_DAMPING=1.2 | |
380 | export GCLIENT_RETRY_SLEEPTIME=2 | |
381 | ||
382 | iterationNumber=0 | |
383 | numberOfFiles=$maxCollectionLength | |
384 | rm -f $logOutputPath/alien_find.err | |
385 | while [[ $numberOfFiles -ge $maxCollectionLength && $iterationNumber -lt 100 ]]; do | |
386 | numberOfFiles=0 | |
387 | offset=$((maxCollectionLength*iterationNumber-1)); | |
388 | [[ $offset -lt 0 ]] && offset=0; | |
389 | $executable -x coll -l ${maxCollectionLength} -o ${offset} "$@" 2>>$logOutputPath/alien_find.err \ | |
390 | | while read -a fields; | |
391 | do | |
392 | nfields=${#fields[*]} | |
393 | turl="" | |
394 | md5="" | |
395 | ctime="" | |
396 | size="" | |
397 | for ((x=1;x<=${nfields};x++)); do | |
398 | field=${fields[${x}]} | |
399 | if [[ "${field}" == "md5="* ]]; then | |
400 | eval ${field} | |
401 | fi | |
402 | if [[ "${field}" == "turl="* ]]; then | |
403 | eval ${field} | |
404 | fi | |
405 | if [[ "${field}" == "ctime="* ]]; then | |
406 | eval ${field}" "${fields[((x+1))]} | |
407 | fi | |
408 | if [[ "${field}" == "size="* ]]; then | |
409 | eval ${field}" "${fields[((x+1))]} | |
410 | fi | |
411 | done | |
412 | ctime=$( date -d "${ctime}" +%s 2>/dev/null) | |
413 | [[ -z $md5 ]] && md5="." | |
414 | [[ -n "$turl" ]] && echo "${turl//"alien://"/} ${md5} ${ctime} ${size}" && ((numberOfFiles++)) | |
415 | done | |
416 | ((iterationNumber++)) | |
417 | done | |
418 | return 0 | |
419 | } | |
420 | ||
421 | alien_find_split() | |
422 | { | |
423 | #split the search in sub searches in the subdirectories of the base path | |
424 | basePath=${1} | |
425 | searchTerm=${2} | |
426 | subPathSelection=${3} | |
427 | [[ -z ${subPathSelection} ]] && subPathSelection=".*" | |
428 | gbbox ls ${basePath} 2>/dev/null | \ | |
429 | while read subPath; do | |
430 | [[ ! ${subPath} =~ ${subPathSelection} ]] && continue | |
431 | alien_find ${basePath}/${subPath} ${searchTerm} | |
432 | done | |
433 | } | |
434 | ||
435 | listCollectionContents() | |
436 | { | |
437 | #find the xml collections and print the list of filenames and hashes | |
438 | while read -a fields; do | |
439 | nfields=${#fields[*]} | |
440 | turl="" | |
441 | md5="" | |
442 | ctime="" | |
443 | for ((x=1;x<=${nfields};x++)); do | |
444 | field=${fields[${x}]} | |
445 | if [[ "${field}" == "md5="* ]]; then | |
446 | eval ${field} | |
447 | fi | |
448 | if [[ "${field}" == "turl="* ]]; then | |
449 | eval ${field} | |
450 | fi | |
451 | if [[ "${field}" == "ctime="* ]]; then | |
452 | eval "${field} ${fields[((x+1))]}" | |
453 | fi | |
454 | done | |
455 | ctime=$( date -d "${ctime}" +%s 2>/dev/null) | |
456 | [[ -n "$turl" ]] && echo "${turl//"alien://"/} ${md5} ${ctime}" | |
457 | done < <(catCollections $1 $2 2>/dev/null) | |
458 | } | |
459 | ||
460 | catCollections() | |
461 | { | |
462 | #print the contents of collection(s) | |
463 | if [[ $# -eq 2 ]]; then | |
464 | while read collection; do | |
465 | [[ $collection != "/"*"/"?* ]] && continue | |
466 | gbbox cat $collection | |
467 | done < <(alien_find $1 $2) | |
468 | elif [[ $# -eq 1 ]]; then | |
469 | gbbox cat $1 | |
470 | fi | |
471 | } | |
472 | ||
473 | haveAlienToken() | |
474 | { | |
475 | #only get a new token if the old one expires soon | |
476 | maxExpireTime=$1 | |
477 | [[ -z $maxExpireTime ]] && maxExpireTime=4000 | |
478 | [[ -z $ALIEN_ROOT ]] && echo "no ALIEN_ROOT!" && return 1 | |
479 | now=$(date "+%s") | |
480 | tokenExpirationTime=$($ALIEN_ROOT/api/bin/alien-token-info|grep Expires) | |
481 | tokenExpirationTime=$(date -d "${tokenExpirationTime#*:}" "+%s") | |
482 | secondsToExpire=$(( tokenExpirationTime-now )) | |
483 | if [[ $secondsToExpire -lt $maxExpireTime ]]; then | |
484 | return 1 | |
485 | else | |
486 | echo "token valid for another $secondsToExpire seconds" | |
487 | return 0 | |
488 | fi | |
489 | } | |
490 | ||
491 | copyFromAlien() | |
492 | { | |
493 | #copy the file $1 to $2 using a specified method | |
6c8c572d | 494 | #uses the "timeout" command to make sure the |
d4ab9e58 | 495 | #download processes will not hang forever. |
496 | # | |
d4ab9e58 | 497 | [[ -z $copyTimeout ]] && copyTimeout=600 |
498 | [[ -z $copyTimeoutHard ]] && copyTimeoutHard=1200 | |
499 | src=${1//"alien://"/} | |
500 | src="alien://${src}" | |
501 | dst=$2 | |
502 | if [[ "$copyMethod" == "tfilecp" ]]; then | |
1e600c4f | 503 | if which timeout &>/dev/null; then |
504 | echo timeout $copyTimeout root -b -q "$copyScript(\"$src\",\"$dst\")" | |
505 | timeout $copyTimeout root -b -q "$copyScript(\"$src\",\"$dst\")" | |
506 | else | |
507 | echo root -b -q "$copyScript(\"$src\",\"$dst\")" | |
508 | root -b -q "$copyScript(\"$src\",\"$dst\")" | |
509 | fi | |
d4ab9e58 | 510 | else |
1e600c4f | 511 | if which timeout &>/dev/null; then |
512 | echo timeout $copyTimeout $ALIEN_ROOT/api/bin/alien_cp $src $dst | |
513 | timeout $copyTimeout $ALIEN_ROOT/api/bin/alien_cp $src $dst | |
514 | else | |
515 | echo $ALIEN_ROOT/api/bin/alien_cp $src $dst | |
516 | $ALIEN_ROOT/api/bin/alien_cp $src $dst | |
517 | fi | |
d4ab9e58 | 518 | fi |
519 | } | |
520 | ||
d56eeaab | 521 | parseConfig() |
522 | { | |
523 | #config file | |
524 | configFile="" | |
525 | alienFindCommand="" | |
526 | secondsToSuicide=$(( 10*3600 )) | |
527 | localPathPrefix="${PWD}" | |
4c2b79c1 | 528 | #define alienSync_localPathPrefix in your env to have a default central location |
2c39ca2b | 529 | [[ -n ${alienSync_localPathPrefix} ]] && localPathPrefix=${alienSync_localPathPrefix} |
d56eeaab | 530 | unzipFiles=0 |
110208cb | 531 | allOutputToLog=0 |
d56eeaab | 532 | |
533 | args=("$@") | |
534 | ||
535 | #first, check if the config file is configured | |
536 | #is yes - source it so that other options can override it | |
537 | #if any | |
538 | for opt in "${args[@]}"; do | |
539 | if [[ ${opt} =~ configFile=.* ]]; then | |
540 | eval "${opt}" | |
541 | [[ ! -f ${configFile} ]] && echo "configFile ${configFile} not found, exiting..." && return 1 | |
542 | echo "using config file: ${configFile}" | |
543 | source "${configFile}" | |
544 | break | |
545 | fi | |
546 | done | |
547 | ||
548 | #then, parse the options as they override the options from file | |
549 | for opt in "${args[@]}"; do | |
550 | if [[ ! "${opt}" =~ .*=.* ]]; then | |
551 | echo "badly formatted option ${var}, should be: option=value, stopping..." | |
552 | return 1 | |
553 | fi | |
554 | local var="${opt%%=*}" | |
555 | local value="${opt#*=}" | |
556 | echo "${var} = ${value}" | |
557 | export ${var}="${value}" | |
558 | done | |
a43cff2f | 559 | |
560 | #things that by default depend on other variables should be set here, after the dependencies | |
561 | [[ -z ${logOutputPath} ]] && logOutputPath="${localPathPrefix}/alienSyncLogs" | |
d56eeaab | 562 | } |
563 | ||
c1fbf113 | 564 | checkMD5sum() |
565 | { | |
566 | local file="${1}" | |
567 | local md5="" | |
ce1d3292 | 568 | [[ ! -f ${file} ]] && return 1 |
c1fbf113 | 569 | if which md5sum &>/dev/null; then |
570 | local tmp=($(md5sum ${file})) | |
571 | md5=${tmp[0]} | |
572 | elif which md5 &>/dev/null; then | |
573 | local tmp=($(md5 ${file})) | |
574 | md5=${tmp[3]} | |
575 | fi | |
576 | echo ${md5} | |
577 | } | |
578 | ||
d4ab9e58 | 579 | main "$@" |