]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGPP/scripts/utilities.sh
Merge branch 'feature-movesplit'
[u/mrichter/AliRoot.git] / PWGPP / scripts / utilities.sh
CommitLineData
6192bc61 1#!/usr/bin/env bash
3fc2dd01 2#library of useful PWGPP related bash functions
3#it REQUIRES BASH 4 !!!!
4#blame: Mikolaj Krzewicki, mkrzewic@cern.ch
5
6if [ ${BASH_VERSINFO} -lt 4 ]; then
7 echo "bash version >= 4 needed, you have ${BASH_VERSION}, exiting..."
8 exit 1
9fi
10
11PWGPP_runMap="
122010 108350 139517
132011 140441 170593
142012 171590 193766
07566ff3 152013 194308 199146
162014 202369 206695
172015 999999 999999
182016 999999 999999
3fc2dd01 19"
20
21parseConfig()
22{
78eed544 23 #parse command line arguments, they have to be in the form
24 # option=value
25 #they are then set in the environment
26 #
27 #optionally a config file can be specified in the arguments:
28 # configFile=<someFile>
29 #config file sets variables: option=value
30 #command line options override config file
3fc2dd01 31 #
32 #recommended way of using (at the beginning of your funcion/script):
33 # if ! parseConfig "${@}"; then return; fi
34
78eed544 35 local args=("$@")
3fc2dd01 36 local opt=""
37
38 #first check if we will need to decode spaces
39 local encodedSpaces=""
40 for opt in "${args[@]}"; do
41 [[ "${opt}" =~ encodedSpaces=.* ]] \
42 && encodedSpaces=1 \
43 && break
44 done
45
46 #then look for a configFile (if any)
47 for opt in "${args[@]}"; do
48 if [[ ${opt} =~ configFile=.* ]]; then
49 eval "${opt}"
50 [[ ! -f ${configFile} ]] \
51 && echo "configFile ${configFile} not found, exiting..." \
52 && return 1
53 echo "using config file: ${configFile}"
54 source "${configFile}"
55 break
56 fi
57 done
58
59 #then, parse the options as they override the options from configFile
60 for opt in "${args[@]}"; do
61 [[ -n ${encodedSpaces} ]] && opt="$(decSpaces ${opt})"
62 if [[ ! "${opt}" =~ .*=.* ]]; then
63 echo "badly formatted option ${var}, should be: option=value, stopping..."
64 return 1
65 fi
66 local var="${opt%%=*}"
67 local value="${opt#*=}"
68 #echo "${var}=${value}"
69 export ${var}="${value}"
70 done
71 return 0
72}
73
74guessRunData()
75{
76 #guess the period from the path, pick the rightmost one
21afcc52 77 #if $ocdbStorage is set it will be reset to the anchorYear (for MC)
3fc2dd01 78 period=""
79 runNumber=""
80 year=""
81 pass=""
82 legoTrainRunNumber=""
83 dataType=""
84 originalPass=""
85 originalPeriod=""
86 anchorYear=""
87 shortRunNumber=""
88
89 local oldIFS=${IFS}
90 local IFS="/"
21afcc52 91 [[ -z ${1} ]] && return 1
3fc2dd01 92 declare -a path=( $1 )
93 IFS="${oldIFS}"
94 local dirDepth=$(( ${#path[*]}-1 ))
95 for ((x=${dirDepth};x>=0;x--)); do
96
97 [[ $((x-1)) -ge 0 ]] && local fieldPrev=${path[$((x-1))]}
98 local field=${path[${x}]}
99 local fieldNext=${path[$((x+1))]}
100
101 [[ ${field} =~ ^[0-9]*$ && ${fieldNext} =~ (.*\.zip$|.*\.root$) ]] && legoTrainRunNumber=${field}
102 [[ -n ${legoTrainRunNumber} && -z ${pass} ]] && pass=${fieldPrev}
103 [[ ${field} =~ ^LHC[0-9][0-9][a-z].*$ ]] && period=${field%_*} && originalPeriod=${field}
104 [[ ${field} =~ ^000[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && runNumber=${field#000}
105 [[ ${field} =~ ^[0-9][0-9][0-9][0-9][0-9][0-9]$ ]] && shortRunNumber=${field}
106 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year=${field}
107 [[ ${field} =~ ^(^sim$|^data$) ]] && dataType=${field}
108 done
3fc2dd01 109 originalPass=${pass}
21afcc52 110
111 if [[ ${dataType} =~ sim ]]; then
112 [[ -n ${shortRunNumber} && -z ${runNumber} ]] && runNumber=${shortRunNumber}
113 pass="passMC"
114 originalPass="" #for MC not from lego, the runNumber is identified as lego train number, thus needs to be nulled
3fc2dd01 115 anchorYear=$(run2year $runNumber)
116 if [[ -z "${anchorYear}" ]]; then
117 echo "WARNING: anchorYear not available for this production: ${originalPeriod}, runNumber: ${runNumber}. Cannot set the OCDB."
118 return 1
119 fi
21afcc52 120 #modify the OCDB: set the year
3fc2dd01 121 ocdbStorage=$(setYear ${anchorYear} ${ocdbStorage})
122 else
123 ocdbStorage=$(setYear ${year} ${ocdbStorage})
124 fi
125
21afcc52 126 [[ -n ${shortRunNumber} && -z ${runNumber} && -z {dataType} ]] && runNumber=${shortRunNumber}
127 [[ -n ${shortRunNumber} && "${legoTrainRunNumber}" =~ ${shortRunNumber} ]] && legoTrainRunNumber=""
128 [[ -z ${legoTrainRunNumber} && ${dataType} == "data" ]] && pass=${path[$((dirDepth-1))]}
129 [[ -n ${legoTrainRunNumber} ]] && pass+="_lego${legoTrainRunNumber}"
130
3fc2dd01 131 #if [[ -z ${dataType} || -z ${year} || -z ${period} || -z ${runNumber}} || -z ${pass} ]];
132 if [[ -z ${runNumber} ]]
133 then
134 #error condition
135 return 1
136 fi
137
138 #ALL OK
139 return 0
140}
141
a510263c 142guessRunNumber()
143(
144 #guess the run number from the path, pick the rightmost one
145 if guessRunData "${1}"; then
146 echo ${runNumber}
147 return 0
148 fi
149 return 1
150)
151
152guessYear()
153(
154 #guess the year from the path, pick the rightmost one
155 if guessRunData "${1}"; then
156 echo ${year}
157 return 0
158 fi
159 return 1
160)
161
162guessPeriod()
163(
164 #guess the period from the path, pick the rightmost one
165 if guessRunData "${1}"; then
166 echo ${period}
167 return 0
168 fi
169 return 1
170)
171
3fc2dd01 172setYear()
173{
06878fe9 174 #set the year in the string
175 #usualy used to modify the year in $ocdbStorage
3fc2dd01 176 # ${1} - year to be set
177 # ${2} - where to set the year
06878fe9 178 #if AUTOYEAR is present in target - it will be replaced by the year
179 local yearSource=$(guessYearFast ${1})
180 local yearTarget=$(guessYearFast ${2})
3fc2dd01 181 local path=${2}
06878fe9 182 [[ ${yearSource} -ne ${yearTarget} && -n ${yearTarget} && -n ${yearSource} ]] \
4c0022d5 183 && path=${2/\/"${yearTarget}"/\/"${yearSource}"}
a62bb24d 184 path=${path/\/\//\/}
185 # The previous line would transform raw:// in raw:/
186 # The next fixes this
187 echo ${path/%:\//:\/\/}
3fc2dd01 188 return 0
189}
190
d2587a2f 191guessYearFast()
192{
193 #guess the year from the path, pick the rightmost one
06878fe9 194 #is string AUTOYEAR present, will be returned
d2587a2f 195 local IFS="/"
196 declare -a pathArray=( ${1} )
06878fe9 197 local field=""
198 local year=""
199 local autoYear=""
d2587a2f 200 for field in ${pathArray[@]}; do
06878fe9 201 [[ ${field} =~ ^20[0-9][0-9]$ ]] && year="${field}"
202 [[ ${field} == AUTOYEAR ]] && autoYear="${field}"
d2587a2f 203 done
06878fe9 204 [[ -n ${autoYear} ]] && year="${autoYear}"
d2587a2f 205 echo ${year}
206 return 0
207}
208
3fc2dd01 209run2year()
210{
211 #for a given run print the year.
212 #the run-year table is ${PWGPP_runMap} (a string)
213 #one line per year, format: year runMin runMax
214 local run=$1
215 [[ -z ${run} ]] && return 1
216 local year=""
217 local runMin=""
218 local runMax=""
219 while read year runMin runMax; do
220 [[ -z ${year} || -z ${runMin} || -z ${runMax} ]] && continue
221 [[ ${run} -ge ${runMin} && ${run} -le ${runMax} ]] && echo ${year} && break
222 done < <(echo "${PWGPP_runMap}")
223 return 0
224}
225
226hostInfo(){
227#
228# Hallo world - Print AliRoot/Root/Alien system info
229#
230
231#
232# HOST info
233#
234 echo --------------------------------------
235 echo
236 echo HOSTINFO
237 echo
238 echo HOSTINFO HOSTNAME" "$HOSTNAME
239 echo HOSTINFO DATE" "`date`
240 echo HOSTINFO gccpath" "`which gcc`
241 echo HOSTINFO gcc version" "`gcc --version | grep gcc`
242 echo --------------------------------------
243
244#
245# ROOT info
246#
247 echo --------------------------------------
248 echo
249 echo ROOTINFO
250 echo
251 echo ROOTINFO ROOT" "`which root`
252 echo ROOTINFO VERSION" "`root-config --version`
253 echo
254 echo --------------------------------------
255
256
257#
258# ALIROOT info
259#
260 echo --------------------------------------
261 echo
262 echo ALIROOTINFO
263 echo
264 echo ALIROOTINFO ALIROOT" "`which aliroot`
265 echo ALIROOTINFO VERSION" "`echo $ALICE_LEVEL`
266 echo ALIROOTINFO TARGET" "`echo $ALICE_TARGET`
267 echo
268 echo --------------------------------------
269
270#
271# Alien info
272#
273#echo --------------------------------------
274#echo
275#echo ALIENINFO
276#for a in `alien --printenv`; do echo ALIENINFO $a; done
277#echo
278#echo --------------------------------------
279
280#
281# Local Info
282#
283 echo PWD `pwd`
284 echo Dir
285 ls -al
286 echo
287 echo
288 echo
289
290 return 0
291}
292
293summarizeLogs()
294{
295 #validate and summarize the status of logs
296 #input is a list of logs, or a glob:
297 #example (summarizes logs in current and subdirs):
298 # summarizeLogs * */*
a510263c 299 #if no args given, process all files in PWD
3fc2dd01 300 #exit code 1 if some logs are not validated
301
302 #print a summary of logs
303 local input
304 local file=""
305 declare -A files
306 input=("${@}")
307 [[ -z "${input[*]}" ]] && input=( "${PWD}"/* )
308
309 #double inclusion protection+make full paths
310 for file in "${input[@]}"; do
07566ff3 311 [[ ! "${file}" =~ ^/ ]] && file="${PWD}/${file}"
3fc2dd01 312 files["${file}"]="${file}"
313 done
314
315 local logFiles
21630cdd 316 logFiles="\.*log$|^stdout$|^stderr$"
3fc2dd01 317
318 #check logs
319 local logStatus=0
320 local errorSummary=""
321 local validationStatus=""
322 declare -A coreFiles
323 for file in "${files[@]}"; do
324 [[ ! -f ${file} ]] && continue
325 #keep track of core files for later processing
21630cdd 326 [[ "${file##*/}" =~ ^core$ ]] && coreFiles[${file}]="${file}" && continue
327 [[ ! "${file##*/}" =~ ${logFiles} ]] && continue
3fc2dd01 328 errorSummary=$(validateLog ${file})
329 validationStatus=$?
330 [[ validationStatus -ne 0 ]] && logStatus=1
331 if [[ ${validationStatus} -eq 0 ]]; then
332 #in pretend mode randomly report an error in rec.log some cases
333 echo "${file} OK"
334 elif [[ ${validationStatus} -eq 1 ]]; then
335 echo "${file} BAD ${errorSummary}"
336 elif [[ ${validationStatus} -eq 2 ]]; then
337 echo "${file} OK MWAH ${errorSummary}"
338 fi
339 done
340
341 #report core files
342 for x in "${coreFiles[@]}"; do
343 echo ${x}
344 chmod 644 ${x}
07566ff3 345 #gdb --batch --quiet -ex "bt" -ex "quit" aliroot ${x} > stacktrace_${x//\//_}.log
346 gdb --batch --quiet -ex "bt" -ex "quit" aliroot ${x} > stacktrace.log
3fc2dd01 347 local nLines[2]
07566ff3 348 #nLines=($(wc -l stacktrace_${x//\//_}.log))
349 nLines=($(wc -l stacktrace.log))
3fc2dd01 350 if [[ ${nLines[0]} -eq 0 ]]; then
07566ff3 351 #rm stacktrace_${x//\//_}.log
352 rm stacktrace.log
3fc2dd01 353 else
354 logStatus=1
07566ff3 355 echo "${x%/*}/stacktrace.log"
3fc2dd01 356 fi
357 done
358
359 return ${logStatus}
360}
361
362validateLog()
363{
364 #validate one log file
365 #input is path to log file
366 #output an error summary on stdout
367 #exit code is 0 if validated, 1 otherwise
368 log=${1}
369 errorConditions=(
370 'There was a crash'
371 'floating'
372 'error while loading shared libraries'
373 'std::bad_alloc'
374 's_err_syswatch_'
375 'Thread [0-9]* (Thread'
376 'AliFatal'
3fc2dd01 377 '\.C.*error:.*\.h: No such file'
378 'segmentation'
d5dfad3c 379 'Segmentation fault'
3fc2dd01 380 'Interpreter error recovered'
381 ': command not found'
382 ': comando non trovato'
d5dfad3c 383 'core dumped'
3fc2dd01 384 )
385
386 warningConditions=(
387 'This is serious'
388 )
389
390 local logStatus=0
391 local errorSummary=""
392 local warningSummary=""
d5dfad3c 393 local errorCondition=""
394 for errorCondition in "${errorConditions[@]}"; do
395 local tmp=$(grep -m1 -e "${errorCondition}" ${log})
396 local error=""
397 [[ -n ${tmp} ]] && error=" : ${errorCondition}"
398 errorSummary+=${error}
3fc2dd01 399 done
400
d5dfad3c 401 local warningCondition=""
402 for warningCondition in "${warningConditions[@]}"; do
403 local tmp=$(grep -m1 -e "${warningCondition}" ${log})
404 local warning=""
405 [[ -n ${tmp} ]] && warning=" : ${warningCondition}"
406 warningSummary+=${warning}
3fc2dd01 407 done
408
409 if [[ -n ${errorSummary} ]]; then
410 echo "${errorSummary}"
411 return 1
412 fi
413
414 if [[ -n ${warningSummary} ]]; then
415 echo "${warningSummary}"
416 return 2
417 fi
418
419 return 0
420}
421
422mergeSysLogs()
423{
424 if [[ $# -lt 2 ]]; then
425 echo 'merge syslogs to an output file'
426 echo 'usage:'
427 echo 'mergeSysLogs outputFile inputFile1 inputFile2 ...'
428 return 0
429 fi
430 local outputFile
431 local inputFiles
432 local i
433 local x
434 local runNumber
435 outputFile=${1}
436 shift
437 inputFiles="$@"
438 i=0
439 if ! ls -1 ${inputFiles} &>/dev/null; then echo "the files dont exist!: ${inputFiles}"; return 1; fi
440 while read x; do
441 runNumber=$(guessRunNumber ${x})
442 [[ -z ${runNumber} ]] && echo "run number cannot be guessed for ${x}" && continue
443 awk -v run=${runNumber} -v i=${i} 'NR > 1 {print run" "$0} NR==1 && i==0 {print "run/I:"$0}' ${x}
444 (( i++ ))
445 done < <(ls -1 ${inputFiles}) > ${outputFile}
446 return 0
447}
448
449stackTraceTree()
450{
451 if [[ $# -lt 1 ]]; then
452 echo 'make stacktrace processing in case of standard root crash log'
453 echo 'input is a (list of) text files with the stack trace (either gdb aoutput'
454 echo 'produced with e.g. gdb --batch --quiet -ex "bt" -ex "quit" aliroot core,'
455 echo 'or the root crash log), output is a TTree formatted table.'
456 echo 'example usage:'
457 echo 'benchmark.sh stackTraceTree /foo/*/rec.log'
458 echo 'benchmark.sh stackTraceTree $(cat file.list)'
459 echo 'benchmark.sh stackTraceTree `cat file.list`'
460 return 0
461 fi
07566ff3 462 #cat "${@}" | gawk '
3fc2dd01 463 gawk '
464 BEGIN {
07566ff3 465 print "frame/I:method/C:line/C:cpass/I:aliroot/I:file/C";
3fc2dd01 466 RS="#[0-9]*";
467 aliroot=0;
468 read=1;
469 }
470 /There was a crash/ {read=1;}
471 /The lines below might hint at the cause of the crash/ {read=0;}
472 read==1 {
473 if ($3 ~ /Ali*/) aliroot=1; else aliroot=0;
474 gsub("#","",RT);
475 if ($NF!="" && RT!="" && $3!="") print RT" "$3" "$NF" "0" "aliroot" "FILENAME
476 }
07566ff3 477 ' "${@}" 2>/dev/null
478}
479
480plotStackTraceTree()
481{
482 #plot the stacktrace tree,
483 #first arg is the text file in the root tree format
484 #second arg is optional: a plot is written to file instead of screen
d5dfad3c 485 #third arg is optional: selection for plotting, default skip G_ stuff
07566ff3 486 local tree=$1
487 local plot=${2:-"crashes.png"}
d5dfad3c 488 local selection=${3:-'!strstr(method,\"G__\")'}
06c216e0 489 [[ ! -f ${tree} ]] && echo "plotStackTraceTree: no input file given" && return 1
07566ff3 490 aliroot -b <<EOF
491TTree* t=AliSysInfo::MakeTree("${tree}");
492TCanvas* canvas = new TCanvas("QA crashes","QA crashes",1);
d5dfad3c 493t->Draw("method","${selection}","");
07566ff3 494canvas->SaveAs("${plot}");
495.q
496EOF
497 return 0
3fc2dd01 498}
499
500encSpaces()
501{
502 echo "${1// /±@@±}"
503}
504
505decSpaces()
506{
507 echo "${1//±@@±/ }"
508}
509
07566ff3 510get_realpath()
511{
512 if [[ $# -lt 1 ]]; then
a510263c 513 echo "print the full path of a file or directory, like \"readlink -f\" on linux"
07566ff3 514 echo "Usage:"
a510263c 515 echo " get_realpath <someFileOrDir>"
07566ff3 516 return 0
517 fi
518 if [[ -f "$1" ]]
519 then
520 # file *must* exist
521 if cd "$(echo "${1%/*}")" &>/dev/null
522 then
523 # file *may* not be local
524 # exception is ./file.ext
525 # try 'cd .; cd -;' *works!*
526 local tmppwd="$PWD"
527 cd - &>/dev/null
528 else
529 # file *must* be local
530 local tmppwd="$PWD"
531 fi
a510263c 532 elif [[ -d "$1" ]]; then
533 if cd "$1" &>/dev/null; then
534 local tmppwd="$PWD"
535 cd - &>/dev/null
536 echo "$tmppwd"
537 return 0
538 else
539 return 1
540 fi
07566ff3 541 else
542 # file *cannot* exist
543 return 1 # failure
544 fi
545 # reassemble realpath
546 echo "$tmppwd"/"${1##*/}"
547 return 0 # success
548}
549
550printLogStatistics()
551{
552 #this function processes the summary logs and prints some stats
553 #relies on the summary log format produced by summarizeLogs()
554 # - how many checked logs in total
555 # - number of each type of problem
556 # example usage:
557 # printLogStatistics */*.log
558 [[ ! -f $1 ]] && return 1
d5dfad3c 559 echo "log statistics from: ${1%/*}"
07566ff3 560 #cat "${@}" | awk '
561 awk '
d5dfad3c 562 BEGIN {nOK=0; nCores=0; nStackTraces=0;}
07566ff3 563 /\/core/ {nCores++}
564 /\/stacktrace.log/ {nStackTraces++}
565 /OK/ {nOK++; nLogs++;}
566 /BAD/ {
567 nLogs++
568 err=""
569 write=0
570 for (i=3; i<=NF; i++)
571 {
2fe76e43 572 if ($i ~ /^\:$/)
07566ff3 573 write=1
574 else
575 write=0
576
577 if (write==0)
578 {
579 if (err=="") err=$i
580 else err=(err FS $i)
581 }
582
583 if (err != "" && (write==1 || i==NF))
584 {
585 sumBAD[err]++
586 err=""
587 }
588 }
589 }
590 END {
591 print ("number of succesful jobs: " nOK" out of "nLogs )
592 for (key in sumBAD)
593 {
594 print key": "sumBAD[key]
595 }
596 if (nCores>0) print "core files: "nCores", stack traces: "nStackTraces
597 }
598 ' "${@}"
599}
39b88d90 600
601createUniquePID()
602{
603 #create a unique ID for jobs running in parallel
604 #consists of the ip address of the default network interface, PID,
605 #if an argument is given, append it (e.g. a production ID)
606 #the fields are space separated with a tag for easy parsing
607 #spaces in the productionID will be encoded using encSpaces()
608 local productionID=""
609 [[ -n "${1}" ]] && productionID=$(encSpaces "${1}")
610 local defaultIP=$(/sbin/route | awk '$1=="default" {print $8}' | xargs /sbin/ifconfig | awk '/inet / {print $2}' | sed 's/.*\([0-9]?\.[0-9]?\.[0-9]?\.[0-9]?\)/$1/')
611 local id="ip:${defaultIP} pid:${BASHPID}"
612 [[ -n "${productionID}" ]] && id+=" prod:${productionID}"
613 echo "${id}"
614}
e0f33210 615
a510263c 616copyFileToLocal()
e0f33210 617(
a510263c 618 #copies a single file to a local destination: the file may either come from
619 #a local filesystem or from a remote location (whose protocol must be
620 #supported)
621 #copy is "robust" and it is repeated some times in case of failure before
622 #giving up (1 is returned in that case)
92092385 623 #origin: Dario Berzano, dario.berzano@cern.ch
a510263c 624 src="$1"
625 dst="$2"
626 ok=0
627 [[ -z "${maxCopyTries}" ]] && maxCopyTries=10
628
629 proto="${src%%://*}"
630
631 echo "copy file to local dest started: $src -> $dst"
632
633 for (( i=1 ; i<=maxCopyTries ; i++ )) ; do
634
635 echo "...attempt $i of $maxCopyTries"
636 rm -f "$dst"
637
638 if [[ "$proto" == "$src" ]]; then
639 cp "$src" "$dst"
640 else
641 case "$proto" in
642 root)
643 xrdcp -f "$src" "$dst"
644 ;;
645 http)
646 curl -L "$src" -O "$dst"
647 ;;
648 *)
649 echo "protocol not supported: $proto"
650 return 2
651 ;;
652 esac
653 fi
654
655 if [ $? == 0 ] ; then
656 ok=1
657 break
658 fi
659
660 done
661
662 if [[ "$ok" == 1 ]] ; then
663 echo "copy file to local dest OK after $i attempt(s): $src -> $dst"
e0f33210 664 return 0
665 fi
a510263c 666
667 echo "copy file to local dest FAILED after $maxCopyTries attempt(s): $src -> $dst"
668 return 1
669)
670
671paranoidCp()
672(
673 #recursively copy files and directories
674 #if target is a directory - it must exist!
675 #to avoid using find and the like as they kill
676 #the performance on some cluster file systems
677 #does not copy links to avoid problems
678 sourceFiles=("${@}")
679 destination="${sourceFiles[@]:(-1)}" #last element
680 unset sourceFiles[${#sourceFiles[@]}-1] #remove last element (dst)
681 #[[ ! -f "${destination}" ]]
682 for src in "${sourceFiles[@]}"; do
683 if [[ -f "${src}" && ! -h "${src}" ]]; then
684 paranoidCopyFile "${src}" "${destination}"
685 elif [[ -d "${src}" && ! -h "${src}" ]]; then
686 src="${src%/}"
687 dst="${destination}/${src##*/}"
688 mkdir -p "${dst}"
689 paranoidCp "${src}"/* "${dst}"
690 fi
691 done
692)
693
694paranoidCopyFile()
695(
696 #copy a single file to a target in an existing dir
697 #repeat a few times if copy fails
698 #returns 1 on failure, 0 on success
699 src=$(get_realpath "${1}")
700 dst=$(get_realpath "${2}")
701 [[ -d "${dst}" ]] && dst="${dst}/${src##*/}"
702 #some sanity check
703 [[ -z "${src}" ]] && echo "$1 does not exist" && return 1
704 [[ -z "${dst}" ]] && echo "$2 does not exist" && return 1
705 #check if we are not trying to copy to the same file
706 [[ "${src}" == "${dst}" ]] && echo "$dst==$src, not copying" && return 0
707 ok=0
708 [[ -z "${maxCopyTries}" ]] && maxCopyTries=10
709
710 echo "paranoid copy started: $src -> $dst"
711 for (( i=1 ; i<=maxCopyTries ; i++ )) ; do
712
713 echo "...attempt $i of $maxCopyTries"
714 rm -f "$dst"
715 cp "$src" "$dst"
716
717 cmp -s "$src" "$dst"
718 if [ $? == 0 ] ; then
719 ok=1
720 break
721 fi
722
723 done
724
725 if [[ "$ok" == 1 ]] ; then
726 echo "paranoid copy OK after $i attempt(s): $src -> $dst"
727 return 0
728 fi
729
730 echo "paranoid copy FAILED after $maxCopyTries attempt(s): $src -> $dst"
e0f33210 731 return 1
732)
733
da387e6e 734generPWD(){
735 #
736 # generate semirandom pwd using 2 keys
737 # Example usage:
738 # generPWD myserviceaccount10 key11
739 key0=$1
740 key1=$2
741 heslo0=`md5sum <<< "$key0 $key1" | cut -c 1-16`
742 heslo=`echo $heslo0 | cut -c 1-8| awk '{print toupper($0)}'`
743 heslo=$heslo`echo $heslo0 | cut -c 8-15| awk '{print tolower($0)}'`%
744 echo $heslo;
745}
746
f2e3b505 747#this makes debugging easier:
748#executes the command given as an argument in this environment
749#use case:
750# bashdb utilities.sh summarizeLogs * */*
751[[ $# != 0 ]] && eval "$@"