# #script daemon and logging support by nohup # #TODO: replace shell scripting by LUA? # export LANG=C export PATH=${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # export SCRIPTLOGFILE='' # export ALLARGS="$@" # export SCRIPTPID="$$" # export SCRIPTTAG="$0" # export SCRIPTSELFT="$0" # export SCRIPTMARK="$(echo "$SCRIPTSELFT" | tr '/-' '_')" # export DAEMONED # if [ -z "$TARGETARCH" ] then TARGETARCH=$(cat /proc/xiaoqiang/model) fi # export TARGETARCH # #for debug #export DAEMONSTDIOFILE="/tmp/daemon/stdio/${SCRIPTMARK}.log" if [ -z "$DAEMONSTDIOFILE" ] then DAEMONSTDIOFILE='/dev/null' fi export DAEMONSTDIOFILE # if [ -z "$DAEMONSYSLOGFILE" ] then DAEMONSYSLOGFILE='syslog' # #%##DAEMONSYSLOGFILE=$(cat /etc/config/system 2>/dev/null| grep log_file | awk '{print $3}' | tr -d "'") #%##if [ -z "$DAEMONSYSLOGFILE" ] #%##then #%## DAEMONSYSLOGFILE='/var/log/messages' #%##fi #%##basexec mkdir -p $(dirname $DAEMONSYSLOGFILE 2>/dev/null) fi # export DAEMONSYSLOGFILE # #ash array support, no lock, no cleanup/gc, use carefully # export SCRIPTARRAYDIR="/tmp/arrays/${SCRIPTMARK}/" # klogger(){ local msg="$@" test -z "$msg" && return 1 #echo "$msg" echo "$msg" >> /dev/kmsg 2>/dev/null return 0 } logexit(){ local msg="$@" klogger "$msg" elog "$msg" exit 1 } basexec(){ local cmdline="$@" test -z "$cmdline" && return 1 $cmdline if [ $? -ne 0 ] then logexit "ERROR: BASEXEC FAILED: $cmdline, PROC EXITED." fi return 0 } # getdefaultrouteip(){ echo "$(ip route list | grep '^default via ' | grep -v 'tap' | head -n 1| awk '{print $3}')" } getdefaultroutedev(){ echo "$(ip route list | grep '^default via ' | grep -v 'tap' | head -n 1| awk '{print $5}')" } getactivegatewayip(){ echo "$(ip route list | grep '^default via ' | head -n 1| awk '{print $3}')" } getactivegatewaydev(){ echo "$(ip route list | grep '^default via ' | grep -v 'tap' | head -n 1| awk '{print $5}')" } getlanip(){ echo "`ip route list dev br-lan | head -n1|awk '{print $7}'`" } getlanipmask(){ echo "`ip route list dev br-lan | head -n1|awk '{print $1}'`" } lanipwait(){ lanip='no-ip' wcnt=0 timelimit="$1" test -z "$timelimit" && timelimit=30 lanip=`getlanip` #conlog "DEBUG: waiting up to $timelimit seconds for lan ip setup." while [ $wcnt -lt $timelimit ] do lanip=`getlanip` if [ -n "$lanip" ] then break fi sleep 1 let wcnt=$wcnt+1 done # if [ -z "$lanip" ] then if [ $timelimit -le 0 ] then return 1 fi dlog "ERROR: probe lan ip failed: $(/sbin/ifconfig br-lan 2>&1)" /sbin/ifconfig | grep -q '^br-lan' if [ $? -ne 0 ] then dlog "WARNING: network interface br-lan no exist." fi dlog "ERROR: lan ip no configured after $timelimit seconds." return 1 fi if [ $timelimit -le 0 ] then return 0 fi dlog "LAN ip config: $lanip" return 0 } iptexec(){ local exitcode local execline local capfile local execnt execline="$@" test -z "$execline" && return 0 basexec mkdir -p /tmp/logexec/ capfile="/tmp/logexec/log.$$.$(date -u +%s)" exitcode=0 for execnt in 1 2 3 4 5 6 do $execline > $capfile 2>&1 exitcode=$? if [ $exitcode -ne 0 ] then cat $capfile 2>/dev/null | grep -iq 'Resource temporarily unavailable' if [ $? -ne 0 ] then break else sleep 1 fi else break fi done if [ $exitcode -ne 0 ] then dlog "iptexec final: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog fi rm -f $capfile return $exitcode } iptsexec(){ local exitcode local execline local capfile local execnt execline="$@" test -z "$execline" && return 0 basexec mkdir -p /tmp/logexec/ capfile="/tmp/logexec/log.$$.$(date -u +%s)" exitcode=0 for execnt in 1 2 3 4 5 6 do $execline > $capfile 2>&1 exitcode=$? if [ $exitcode -ne 0 ] then cat $capfile 2>/dev/null | grep -iq 'Resource temporarily unavailable' if [ $? -ne 0 ] then break else sleep 1 fi else break fi done rm -f $capfile return $exitcode } iptnewchain(){ local exitcode local execline local capfile local execnt execline="$@" test -z "$execline" && return 0 execline="iptables $execline" basexec mkdir -p /tmp/logexec/ capfile="/tmp/logexec/log.$$.$(date -u +%s)" exitcode=0 for execnt in 1 2 3 4 5 6 do $execline > $capfile 2>&1 exitcode=$? if [ $exitcode -ne 0 ] then # cat $capfile 2>/dev/null | grep -iq 'Chain already exists' test $? -eq 0 && exitcode=0 && break cat $capfile 2>/dev/null | grep -iq 'Resource temporarily unavailable' if [ $? -ne 0 ] then break else sleep 1 fi else break fi done if [ $exitcode -ne 0 ] then dlog "iptnewchain final: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog fi rm -f $capfile return $exitcode } iptremoverule(){ local exitcode local execline local capfile local execnt execline="$@" test -z "$execline" && return 0 execline="iptables $execline" basexec mkdir -p /tmp/logexec/ capfile="/tmp/logexec/log.$$.$(date -u +%s)" exitcode=0 for execnt in 1 2 3 4 5 6 7 8 9 0 do $execline > $capfile 2>&1 exitcode=$? #delete more test $exitcode -eq 0 && continue cat $capfile 2>/dev/null | grep -iq 'No chain/target/match by that name' test $? -eq 0 && exitcode=0 && break cat $capfile 2>/dev/null | grep -iq 'Resource temporarily unavailable' test $? -ne 0 && break # #iptables v1.4.10: Couldn't load target `lanuploadtraffic':File not found # cat $capfile 2>/dev/null | grep -iq 'File not found' test $? -ne 0 && exitcode=0 && break #other errors sleep 1 done if [ $exitcode -ne 0 ] then dlog "iptremoverule final: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog fi rm -f $capfile return $exitcode } # iptremoveall(){ iptremoverule $@ return $? } # killpid(){ local onepid ksig onepid=$1 ksig=$2 if [ -z "$onepid" ] then return 0 fi test -z "$ksig" && ksig=15 # if [ $onepid -le 100 ] then return 0 fi timelimit=5 wcnt=0 while [ : ] do if [ "$ksig" = '0' ] then kill -${ksig} $onepid 2>/dev/null return $? fi kill -${ksig} $onepid 2>/dev/null test $? -ne 0 && return 0 let wcnt=$wcnt+1 test $wcnt -gt $timelimit && break sleep 1 done kill -9 $onepid 2>/dev/null test $? -eq 0 && return 1 return 0 # } killpidfile(){ local pidfile pidfile=$1 if [ -z "$pidfile" ] then return 0 fi if [ ! -s "$pidfile" ] then return 0 fi killpid "$(cat $pidfile 2>/dev/null)" "$2" return $? } # waitpidfile(){ local timeout pidfile show timeout=$2 pidfile=$1 show=$3 test -z "$pidfile" && dlog "WARNING: waitpidfile, need arg pidfile." && return 0 test -z "$timeout" && timeout=90 let timeout=$timeout+1-1 2>/dev/null test $? -ne 0 -a "$timeout" != '0' && dlog "WARNING: waitpidfile, invalid arg timeout: $timeout" && return 0 test ! -s "$pidfile" && return 0 lckpid=$(cat "$pidfile" 2>/dev/null) if [ -n "$show" -a $timeout -gt 0 ] then dlog "" dlog "" dlog "WARNING: waiting $timeout seconds for pidfile $pidfile($lckpid) ..." dlog "" dlog "" fi wcnt=0 while [ : ] do lckpid="`cat "$pidfile" 2>/dev/null`" test -z "$lckpid" && return 0 kill -0 "$lckpid" 2>/dev/null if [ $? -ne 0 ] then return 0 fi let wcnt=$wcnt+1 test $wcnt -lt $timeout || break sleep 1 done if [ $timeout -gt 0 ] then echo "" echo "" echo "WARNING: waiting timeout after $timeout seconds for $pidfile($lckpid) ..." echo "" echo "" fi return 1 } waitbootcheck(){ local timeout timeout=$1 waitpidfile '/tmp/bootcheck.lock' "$timeout" return $? } isipaddress(){ echo "$@"|grep -q '^[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}$' return $? } isnumber(){ local chknum test "$@" = '0' && return 0 let chknum=$@+1-1 2>/dev/null return $? } addroute(){ #return 0 for ok, will output error msg local routeline oneop opok errstr routeline="$@" test -z "$routeline" && dlog "ERROR: empty arg for addroute." && return 1 opok=1 for oneadd in 1 2 3 4 5 do errstr=$(route add $routeline 2>&1) if [ -n "$errstr" ] then echo $errstr | grep -q 'File exists' if [ $? -eq 0 ] then opok=0 else echo "$errstr" fi fi break done return $opok } ipaddradd(){ local ipmask ipdev exitcode ipmask=$1 ipdev=$2 exitcode=0 test -z "$ipdev" && return 1 ip addr add ${ipmask} dev $ipdev > /tmp/$$.ipaddradd.log 2>&1 if [ $? -ne 0 ] then cat /tmp/$$.ipaddradd.log 2>/dev/null | grep -i -q 'File exists' exitcode=$? fi rm -f /tmp/$$.ipaddradd.log return $exitcode } ipaddrdel(){ local ipmask ipdev exitcode ipmask=$1 ipdev=$2 test -z "$ipdev" && return 1 exitcode=0 ip addr del ${ipmask} dev $ipdev > /dev/null 2>&1 return $exitcode } delroute(){ #return 0 for ok, will output error msg local routeline oneop opok errstr routeline="$@" test -z "$routeline" && dlog "ERROR: empty arg for delroute." && return 1 opok=1 for oneadd in 1 2 3 4 5 do errstr=$(route del $routeline 2>&1) if [ -n "$errstr" ] then echo $errstr | grep -q 'No such process' if [ $? -eq 0 ] then opok=0 else echo "$errstr" fi break fi done return $opok } # strcut1() { local onestr onepart onecnt outstr onestr="$@" onecnt=0 outstr='' for onepart in $onestr do let onecnt=$onecnt+1 test $onecnt -le 1 && continue if [ -z "$outstr" ] then outstr="$onepart" else outstr="$outstr $onepart" fi done echo "$outstr" return 0 } # strcut2() { local onestr onepart onecnt outstr onestr="$@" onecnt=0 outstr='' for onepart in $onestr do let onecnt=$onecnt+1 test $onecnt -le 2 && continue if [ -z "$outstr" ] then outstr="$onepart" else outstr="$outstr $onepart" fi done echo "$outstr" return 0 } # strcut3() { local onestr onepart onecnt outstr onestr="$@" onecnt=0 outstr='' for onepart in $onestr do let onecnt=$onecnt+1 test $onecnt -le 3 && continue if [ -z "$outstr" ] then outstr="$onepart" else outstr="$outstr $onepart" fi done echo "$outstr" return 0 } # strcut4() { local onestr onepart onecnt outstr onestr="$@" onecnt=0 outstr='' for onepart in $onestr do let onecnt=$onecnt+1 test $onecnt -le 4 && continue if [ -z "$outstr" ] then outstr="$onepart" else outstr="$outstr $onepart" fi done echo "$outstr" return 0 } # stringmatchstart(){ #return 0 for ok local cmplist rawstr cmpcnt cmppos rawpos cmplen rawlen onecmp oneraw cmplist=$1 test -z "$cmplist" && return 0 rawstr=$(tailspacepos 2 $@) cmplen=${#cmplist} rawlen=${#rawstr} if [ $rawlen -lt $cmplen ] then #dlog "stringmatchstart: $cmplist is no match len $rawstr // $rawlen -lt $cmplen : $@" return 1 fi if [ "${rawstr:0:$cmplen}" != "$cmplist" ] then #dlog "stringmatchstart: $cmplist is no match start $rawstr // $rawlen -lt $cmplen : $@" return 1 fi #dlog "stringmatchstart: $cmplist is match start $rawstr : $@" return 0 } pipematchstart(){ local chkstr oneline chkstr="$1" while read oneline do stringmatchstart "X$chkstr" "X$oneline" test $? -eq 0 && echo "$oneline" done } #echo val for match getspacepos(){ local pos rawargs chkcnt pos=$1 rawargs=$@ test -z "$pos" && return 1 let pos=$pos+1 2>/dev/null if [ $? -ne 0 ] then return 1 fi #dlog "DEBUG: getspacepos rawargs: $rawargs, pos=$pos" chkcnt=0 for oneflag in $rawargs do let chkcnt=$chkcnt+1 test $chkcnt -eq 1 && continue if [ $chkcnt -eq $pos ] then echo "$oneflag" #dlog "DEBUG: getspacepos ret rawargs: $rawargs, pos=$pos => $oneflag" return 0 fi done return 0 } # pipegetspacepos(){ local chkstr oneline chkstr="$1" while read oneline do getspacepos "$chkstr" "$oneline" done } #echo val for match tailspacepos(){ #return string after pos local pos rawargs chkcnt tailstr pos=$1 rawargs=$@ test -z "$pos" && return 1 let pos=$pos+1-1 2>/dev/null if [ $? -ne 0 ] then return 1 fi #dlog "DEBUG: tailspacepos rawargs: $rawargs, pos=$pos" chkcnt=0 for oneflag in $rawargs do let chkcnt=$chkcnt+1 test $chkcnt -eq 1 && continue if [ $chkcnt -le $pos ] then continue fi if [ -z "$tailstr" ] then tailstr="$oneflag" else tailstr="$tailstr $oneflag" fi #dlog "DEBUG: tailspacepos rawargs: $rawargs, pos=$pos => $oneflag, tailstr=$tailstr" done echo "$tailstr" return 0 } ## #stringtrim() # | sed 's/^ *//g' #} ## #This will remove all spaces ... #echo " test test test " | tr -d ' ' # #This will remove trailing spaces... # #echo " test test test " | sed 's/ *$//g' #which results in # # test test test #This will remove leading spaces... # #echo " test test test " | sed 's/^ *//g' #which results in # #test test test #This will remove both trailing and leading spaces # #echo " test test test " | sed -e 's/^ *//g' -e 's/ *$//g' #which results in # #test test test # charlistinclude(){ #return 0 for ok local cmplist rawstr cmpcnt cmppos rawpos cmplen rawlen onecmp oneraw cmplist=$1 test -z "$cmplist" && return 0 rawstr=$@ cmplen=${#cmplist} rawlen=${#rawstr} cmpcnt=0 cmppos=0 rawpos=0 while [ $cmppos -lt $cmplen ] do onecmp=${cmplist:$cmppos:1} let rawpos=$cmplen+1 while [ $rawpos -lt $rawlen ] do oneraw=${rawstr:$rawpos:1} #dlog "charlistinclude: '$onecmp' vs '$oneraw' // '$rawstr'" if [ "$onecmp" = "$oneraw" ] then let cmpcnt=$cmpcnt+1 break fi let rawpos=$rawpos+1 done let cmppos=$cmppos+1 done if [ $cmpcnt -lt $cmplen ] then #dlog "charlistinclude: '$cmplist' is $cmpcnt / $cmplen nomatch '$rawstr' // '$@'" return 1 else #dlog "charlistinclude: '$cmplist' is $cmpcnt / $cmplen match '$rawstr' // '$@'" return 0 fi } charlistlimit(){ #return 0 for ok local cmplist rawstr cmpcnt cmppos rawpos cmplen rawlen onecmp oneraw cmplist=$1 test -z "$cmplist" && return 0 rawstr=$(tailspacepos 2 $@) cmplen=${#cmplist} rawlen=${#rawstr} cmpcnt=0 rawpos=0 while [ $rawpos -lt $rawlen ] do oneraw=${rawstr:$rawpos:1} cmppos=0 while [ $cmppos -lt $cmplen ] do onecmp=${cmplist:$cmppos:1} if [ "$onecmp" != "$oneraw" ] then dlog "charlistlimit: $cmplist is nolimit $rawstr // $onecmp != $oneraw : $@" return 1 fi let cmppos=$cmppos+1 done let rawpos=$rawpos+1 done dlog "charlistlimit: $cmplist is limit $rawstr : $@" return 0 } charlistdel(){ #return 0 for ok local cmplist rawstr cmpcnt cmppos rawpos cmplen rawlen onecmp oneraw outstr cmplist=$1 test -z "$cmplist" && return 0 rawstr=$@ cmplen=${#cmplist} rawlen=${#rawstr} cmpcnt=0 rawpos=0 let rawpos=$cmplen+1 outstr='' while [ $rawpos -lt $rawlen ] do oneraw=${rawstr:$rawpos:1} cmppos=0 isinclude=0 while [ $cmppos -lt $cmplen ] do onecmp=${cmplist:$cmppos:1} if [ "$onecmp" = "$oneraw" ] then #dlog "charlistdel: skipped $onecmp vs $oneraw" isinclude=1 break fi let cmppos=$cmppos+1 done let rawpos=$rawpos+1 test $isinclude -ne 0 && continue if [ -z "$outstr" ] then outstr=$oneraw else outstr=${outstr}${oneraw} fi done #dlog "charlistdel: $cmplist del from $rawstr => $outstr // $@" echo "$outstr" return 0 } #TODO: replace grep #tr -d '[a-zA-Z0-9-_.]' validAlphaNum(){ #check input, return 0 for ok local invalidstr invalidstr=$(echo "$@" | tr -d '[a-zA-Z0-9-_.]') if [ -z "$invalidstr" ] then #dlog "validAlphaNum: $@ -> true [0-9A-Za-z:-]" return 0 else #dlog "validAlphaNum: $@ -> false [0-9A-Za-z:-]" return 1 fi } validAlphaNum3(){ #return 0 for ok local checkstr checklen onechar validstr validlen onevalid isincluded checkstr="$@" test -z "$checkstr" && return 1 validstr='01234567890abcdefghijklnmopqrstuvwxyzABCDEFGHIJKLNMOPQRSTUVWXYZ:-_.' # checklen=${#checkstr} while [ : ] do let checklen=$checklen-1 test $checklen -ge 0 || break onechar=${checkstr:$checklen:1} validlen=${#validstr} isincluded=0 while [ : ] do let validlen=$validlen-1 test $validlen -ge 0 || break onevalid=${validstr:$validlen:1} if [ "$onechar" = "$onevalid" ] then isincluded=1 #echo "DEBUG: '$onechar' included in $validstr" break fi done if [ $isincluded -eq 0 ] then #echo "DEBUG: '$onechar' NOT included in $validstr" return 1 fi done #echo "DEBUG: '$checkstr' all included in $validstr" return 0 } validAlphaNum2(){ #check input, return 0 for ok #TODO: remove grep echo "$@" | grep -q '^[0-9A-Za-z:-_\.]\+$' if [ $? -eq 0 ] then #dlog "validAlphaNum: $@ -> true [0-9A-Za-z:-]" return 0 else #dlog "validAlphaNum: $@ -> false [0-9A-Za-z:-]" return 1 fi } #set or update arrfastset(){ #$1 arrname, $2 key $3-... value local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrkey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 arrvalue=$(strcut2 "$@") test -z "$arrvalue" && return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" #dlog "ARRAY DEBUG: set, dir: $arrdir, name: $arrname, key:$arrkey, vaule: $arrvalue" basexec mkdir -p $arrdir && echo "$arrvalue" > "$arrdir$arrkey" 2>/dev/null test -$? -ne 0 && logexit "ERROR: arrfastset save to file $arrdir$arrkey failed." return 0 } arrset(){ #$1 arrname, $2 key $3-... value local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrkey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 validAlphaNum $arrname || return 1 validAlphaNum $arrkey || return 1 arrfastset $@ return $? } #del arrfastdel(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrkey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" #dlog "ARRAY DEBUG: del, dir: $arrdir, name: $arrname, key:$arrkey, vaule: $arrvalue" rm -f "$arrdir$arrkey" return $? } #del arrdel(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrkey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 validAlphaNum $arrname || return 1 validAlphaNum $arrkey || return 1 arrfastdel $@ return $? } #del all arrdelall(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 validAlphaNum $arrname || return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" rm -rf "$arrdir" return $? } #key list all arrkeylist(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir allkeys arrname="$1" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 validAlphaNum $arrname || return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" allkeys='' #if [ "$arrname" = 'mactrafficdata' ] # then # dlog "DEBUG: arr name: $arrname" # dlog "DEBUG: arr dir: $arrdir" # dlog "DEBUG: arr cmd: ls -A $arrdir 2>&1" # ls -A $arrdir 2>&1 | pipelog dlog #fi for arrkey in $(ls -A $arrdir 2>/dev/null) do test -d "$arrdir$arrkey" && continue if [ -z "$allkeys" ] then allkeys="$arrkey" else allkeys="$allkeys $arrkey" fi done #if [ "$arrname" = 'mactrafficdata' ] # then # dlog "DEBUG: key list: $allkeys" #fi echo "$allkeys" return 0 } arrkeys(){ arrkeylist $@ } arrfastgetfile(){ local onekey arrname arrname="$1" onekey="$2" test -z "$onekey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" #dlog "ARRAY DEBUG: arrfastgetfile, dir: $arrdir, name: $arrname, key:$arrkey, vaule: $arrvalue" echo "$arrdir$onekey" } arrdump(){ local dumpkeys onekey arrname arrname="$1" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 dumpkeys=$(arrkeys $@) dlog "ARRAY DUMP:" dlog "ARRAY NAME: $arrname" dlog "ARRAY KEYS: $dumpkeys" for onekey in $dumpkeys do dlog "$onekey $(arrfastgetfile $arrname $onekey) => $(arrfastget $arrname $onekey)" done dlog "ARRAY DUMP: ---" } arrkeydump(){ local onekey arrname arrname="$1" onekey="$2" test -z "$onekey" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 dlog "ARRAY KEYS DUMP:" dlog "ARRAY NAME: $arrname" dlog "ARRAY KEYS: $onekey" dlog "ARRAY VAL: $(arrfastget $arrname $onekey)" dlog "ARRAY KEYS DUMP: --- $(arrfastgetfile $arrname $onekey)" } #get arrfastget(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" test ! -f "$arrdir$arrkey" && return 1 read arrvalue < $arrdir$arrkey 2>/dev/null #dlog "ARRAY DEBUG: get, dir: $arrdir, name: $arrname, key:$arrkey, vaule: $arrvalue" echo "$arrvalue" return 0 } # #get arrget(){ #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 validAlphaNum $arrname || return 1 validAlphaNum $arrkey || return 1 arrfastget $@ return $? } # #check exist arrcheck(){ #return 0 for exist #$1 arrname, $2 key local arrname arrkey arrvalue arrdir arrname="$1" arrkey="$2" test -z "$arrname" && return 1 test -z "$SCRIPTARRAYDIR" && return 1 #validAlphaNum $arrname || return 1 #validAlphaNum $arrkey || return 1 arrdir="${SCRIPTARRAYDIR}/${arrname}/" test ! -f "$arrdir$arrkey" && return 1 return 0 } # flog(){ msg="$@" test -z "$msg" && return 0 DATE="`date`" test -n "$SCRIPTLOGFILE" && echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $SCRIPTLOGFILE 2>/dev/null return 0 } # dlog(){ local msg msg="$@" test -z "$msg" && return 0 DATE="`date`" if [ -z "$DAEMONSYSLOGFILE" -o "$DAEMONSYSLOGFILE" = 'syslog' ] then msg=$(echo "$msg" | sed -e 's#^-#_#') /usr/bin/logger -t "${SCRIPTTAG}[${SCRIPTPID}]" "$msg" else echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $DAEMONSYSLOGFILE 2>/dev/null fi test -n "$SCRIPTLOGFILE" && echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $SCRIPTLOGFILE 2>/dev/null return 0 } # elog(){ msg="$@" test -z "$msg" && return 0 DATE="`date`" if [ -z "$DAEMONSYSLOGFILE" -o "$DAEMONSYSLOGFILE" = 'syslog' ] then msg=$(echo "$msg" | sed -e 's#^-#_#') /usr/bin/logger -t "${SCRIPTTAG}[${SCRIPTPID}]" "$msg" else echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $DAEMONSYSLOGFILE 2>/dev/null fi test -n "$SCRIPTLOGFILE" && echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $SCRIPTLOGFILE 2>/dev/null echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> /proc/$$/fd/2 2>/dev/null return 0 } # conlog(){ msg="$@" test -z "$msg" && return 0 DATE="`date`" if [ -z "$DAEMONSYSLOGFILE" -o "$DAEMONSYSLOGFILE" = 'syslog' ] then msg=$(echo "$msg" | sed -e 's#^-#_#') /usr/bin/logger -t "${SCRIPTTAG}[${SCRIPTPID}]" "$msg" else echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $DAEMONSYSLOGFILE 2>/dev/null fi echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> /dev/console 2>/dev/null test -n "$SCRIPTLOGFILE" && echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $SCRIPTLOGFILE 2>/dev/null return 0 } # conelog(){ msg="$@" test -z "$msg" && return 0 DATE="`date`" if [ -z "$DAEMONSYSLOGFILE" -o "$DAEMONSYSLOGFILE" = 'syslog' ] then msg=$(echo "$msg" | sed -e 's#^-#_#') /usr/bin/logger -t "${SCRIPTTAG}[${SCRIPTPID}]" "$msg" else echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $DAEMONSYSLOGFILE 2>/dev/null fi echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> /dev/console 2>/dev/null test -n "$SCRIPTLOGFILE" && echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> $SCRIPTLOGFILE 2>/dev/null echo "$DATE ${SCRIPTTAG}[${SCRIPTPID}]: $msg" >> /proc/$$/fd/2 2>/dev/null return 0 } #TODO: fix line length limit pipelog(){ logfun="$@" if [ -z "$logfun" ] then dlog "ERROR: pipelog fun arg no defined." return 1 fi type -t $logfun >/dev/null 2>&1 if [ $? -ne 0 ] then dlog "ERROR: pipelog fun $logfun no defined." return 1 fi while read onelogline do $logfun "$onelogline" done } #TODO: fix line length limit lpipelog(){ logfun="$@" if [ -z "$logfun" ] then dlog "ERROR: pipelog fun arg no defined." return 1 fi type -t $logfun >/dev/null 2>&1 if [ $? -ne 0 ] then dlog "ERROR: pipelog fun $logfun no defined." return 1 fi while [ : ] do while read onelogline do $logfun "$onelogline" done sleep 3 done } slog(){ #usage: slog uuid dlog "msg" local logmark logfun logmsg logstat logmark="$1" logfun="$2" logmsg="$@" if [ -z "$logfun" ] then dlog "ERROR: slog fun arg no defined." return 1 fi if [ "$logfun" = 'release' ] then arrfastset slogmark $logmark 0 return 0 fi type -t $logfun >/dev/null 2>&1 if [ $? -ne 0 ] then dlog "ERROR: pipelog fun $logfun no defined." return 1 fi logstat=$(arrfastget slogmark $logmark) #dlog "slog arrfastget slogmark $logmark = $logstat" if [ "$logstat" = '1' ] then #already mark return 0 fi arrfastset slogmark $logmark 1 logmsg=$(echo "$logmsg" | sed -e "s/^$logmark //"|sed -e "s/^$logfun //") $logfun "$logmsg" return 0 } #echo val for match getoptval(){ pos=$1 #logger "ALLARGS: $ALLARGS, pos=$pos" test -z "$pos" && return 1 let pos=$pos+1-1 2>/dev/null if [ $? -ne 0 ] then return 0 fi chkcnt=0 for oneflag in $ALLARGS do echo "$oneflag" | grep -q '^-' if [ $? -eq 0 ] then continue fi let chkcnt=$chkcnt+1 if [ $chkcnt -eq $pos ] then echo "$oneflag" #logger "ALLARGS: $ALLARGS, pos=$pos, oneflag=$oneflag" return 1 fi done return 0 } strippath() { stmsg="$@" newstr="${stmsg}${stmsg}" while [ : ] do newstr=`echo "${stmsg}" | sed -e 's/\/\//\//g'` if [ "${newstr}" != "${stmsg}" -a -n "${newstr}" ] then stmsg="${newstr}" else break; fi done echo "${newstr}" } slaprtrim() { onexcu=`strippath $@` onexcu=`echo ${onexcu} | sed -e 's/\/$//'` echo $onexcu } slapltrim() { onexcu=`strippath $@` onexcu=`echo ${onexcu} | sed -e 's/\/$//'` echo $onexcu } # argmatch(){ #1 for match local chk chk="$@" test -z "$chk" && echo 0 && return 0 for onechk in $chk do for onearg in $ALLARGS do if [ "$onechk" = "$onearg" ] then echo 1 return 1 fi done done echo 0 return 0 } # setlogfile(){ newlogfile="$1" test -z "$newlogfile" && return 0 echo "" > $newlogfile 2>/dev/null if [ $? -ne 0 ] then conlog "ERROR: can not write to logfile $newlogfile" return 0 fi SCRIPTLOGFILE="$newlogfile" } # linecat(){ local catfiles onefile oneline catfiles="$@" for onefile in $catfiles do if [ ! -f "$onefile" ] then #dlog "WARNING: linecat, file no found: $onefile" continue fi while read oneline do echo "$oneline" done < $onefile done } dlogexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? dlog "logexec: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog rm -f $capfile return $exitcode } # dlogselftexec(){ local exitcode local execline local capfile execline="$SCRIPTSELFT" test -z "$execline" && return 0 execline="$execline selftexec" test "$(argmatch selftexec)" = '1' && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? dlog "logexec: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog rm -f $capfile exit $exitcode } # echoexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? if [ $exitcode -ne 0 ] then dlog "logexec: exitcode $exitcode, $execline" fi cat $capfile rm -f $capfile return $exitcode } # echoelogexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? cat $capfile 2>/dev/null | pipelog elog if [ $exitcode -ne 0 ] then elog "logexec: exitcode $exitcode, $execline" fi rm -f $capfile return $exitcode } echoconlogexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? cat $capfile 2>/dev/null | tee | pipelog conlog if [ $exitcode -ne 0 ] then conlog "logexec: exitcode $exitcode, $execline" fi rm -f $capfile return $exitcode } # echodlogexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 capfile="/tmp/logexec/log.$$.$(date -u +%s)" basexec mkdir -p /tmp/logexec/ $execline > $capfile 2>&1 exitcode=$? cat $capfile 2>/dev/null | tee | pipelog dlog if [ $exitcode -ne 0 ] then dlog "logexec: exitcode $exitcode, $execline" fi rm -f $capfile return $exitcode } # logexec(){ local exitcode local execline local capfile execline="$@" test -z "$execline" && return 0 basexec mkdir -p /tmp/logexec/ capfile="/tmp/logexec/log.$$.$(date -u +%s)" $execline > $capfile 2>&1 exitcode=$? if [ $exitcode -ne 0 ] then dlog "logexec: exitcode $exitcode, $execline" cat $capfile 2>/dev/null | pipelog dlog fi rm -f $capfile return $exitcode } # setexitmark(){ # setpid="$1" if [ -z "$setpid" ] then setpid=$SCRIPTPID fi # if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon setexitmark." exit 1 fi arrset run exit_${SCRIPTLOCK} "$setpid" #dlog "set proc $$ lock, exit $?, $SCRIPTSELFT // $setpid => ${SCRIPTARRAYDIR}/run/lock" #dlog "set proc $$ lock ret: $(arrget run lock)" if [ $? -ne 0 ] then conlog "ERROR: create daemon exitmark($setpid) failed." exit 1 fi # } # getexitmark(){ # if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon getexitmark." exit 1 fi echo "$(arrfastget run exit_${SCRIPTLOCK})" return 0 } # delexitmark(){ # if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon delexitmark." exit 1 fi arrfastdel run exit_${SCRIPTLOCK} return $? } # getlockedprocpid(){ if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon lock." exit 1 fi lockedpid="$(arrget run lock_${SCRIPTLOCK})" test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: getlockedprocpid: arrget run lock_${SCRIPTLOCK} => $lockedpid" echo "$lockedpid" return 0 } releaselockedprocpid(){ if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon unlock." exit 1 fi setexitmark lockedpid="$(arrget run lock_${SCRIPTLOCK})" #test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: releaselockedprocpid: arrget run lock_${SCRIPTLOCK} => $lockedpid" dlog "DEBUG: releaselockedprocpid: arrget run lock_${SCRIPTLOCK} => $lockedpid" arrdel run "lock_${SCRIPTLOCK}" return $? } setproclock(){ # setpid="$1" if [ -z "$setpid" ] then setpid=$SCRIPTPID fi test -z "$setpid" && return 0 let setpid=$setpid+1-1 2>/dev/null test $? -ne 0 && return 1 # if [ -z "$SCRIPTLOCK" ] then SCRIPTLOCK=$SCRIPTMARK fi validAlphaNum "${SCRIPTLOCK}" if [ $? -ne 0 ] then conlog "ERROR: invalid SCRIPTLOCK(${SCRIPTLOCK}) for daemon lock." exit 1 fi arrset run lock_${SCRIPTLOCK} "$setpid" #dlog "set proc $$ lock, exit $?, $SCRIPTSELFT // $setpid => ${SCRIPTARRAYDIR}/run/lock" #dlog "set proc $$ lock ret: $(arrget run lock)" if [ $? -ne 0 ] then elog "ERROR: create daemon lock failed: arrset run lock_${SCRIPTLOCK} $setpid" exit 1 else test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: setproclocked: arrset run lock_${SCRIPTLOCK} => $setpid" fi # } checkproclock(){ local waitlck local replaceproc # #check lock, return 0 for no locked, 1 for locked # test -z "$SCRIPTPID" && SCRIPTPID=$$ test -z "$SCRIPTSELFT" && SCRIPTSELFT=$0 # waitlck="$1" replaceproc="$2" test -z "$waitlck" && waitlck=1 let waitlck=$waitlck+1-1 2>/dev/null if [ $? -ne 0 ] then waitlck=1 fi test $waitlck -le 0 && waitlck=0 # wcnt=0 #SCRIPTLOCK will effect in getlockedprocpid lckpid=$(getlockedprocpid) if [ "$lckpid" = "$SCRIPTPID" ] then #it's me test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: checkproclock, no locked, myself: $SCRIPTPID" return 0 fi if [ -z "$lckpid" ] then test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: checkproclock, no locked, lockpid no exist." return 0 fi kill -0 "$lckpid" 2>/dev/null if [ $? -ne 0 ] then #no running test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: checkproclock, no locked, $lckpid no running." return 0 fi if [ "$replaceproc" = 'replaceproc' ] then dlog "WARNING: try to replace old proc ${lckpid}" killpid $lckpid fi if [ $waitlck -gt 1 ] then dlog "INFO: proclock waiting $lckpid, timeout $waitlck" fi running=0 while [ : ] do running=0 lckpid=$(getlockedprocpid) if [ -n "$lckpid" ] then kill -0 "$lckpid" 2>/dev/null if [ $? -ne 0 ] then #no running break else running=1 fi else break fi let wcnt=$wcnt+1 test $wcnt -ge $waitlck && break sleep 1 done # if [ $waitlck -gt 1 ] then if [ $running -ne 0 ] then dlog "WARNING: pid lock waiting $lckpid timeout after $wcnt seconds." else dlog "INFO: pid lock waiting $lckpid finish after $wcnt seconds." fi else test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: checkproclock, no locked, max wait $waitlck seconds, esp $wcnt seconds, pid $lckpid" fi #test -n "$lckpid" && dlog "DEBUG: checkproclock, $waitlck seconds, waiting for $lckpid running=$running, after $wcnt seconds." return $running } # procgodaemon(){ #no lock set/check if [ `echo "$SCRIPTSELFT"|grep -c '^/'` -eq 0 ] then elog "ERROR: script must start by absolute path." exit 1 fi # #check lock # checkproclock 1 if [ $? -ne 0 ] then test "$1" = 'fixme' && dlog "FIXME: already running, pid $(getlockedprocpid))" && exit 1 exit 0 #else # elog "INFO: no running" fi # delexitmark # DAEMONED='' if [ `argmatch blocking daemon status checkconf` -eq 0 -a -x "$SCRIPTSELFT" ] then # if [ -z "$SCRIPTNICE" ] then SCRIPTNICE=10 fi let SCRIPTNICE=$SCRIPTNICE+1-1 2>/dev/null if [ $? -ne 0 ] then SCRIPTNICE=10 fi setproclock basexec mkdir -p /tmp/daemon/stdio/ touch $DAEMONSTDIOFILE if [ $? -ne 0 ] then elog "ERROR: create STDIO file failed: touch $DAEMONSTDIOFILE $(tuch $DAEMONSTDIOFILE 2>&1)" exit 1 fi #fifofile="/tmp/daemon/${SCRIPTMARK}.fifo" #rm -f $fifofile #mkfifo $fifofile #if [ $? -ne 0 ] # then # elog "ERROR: create FIFO pipe failed: mkfifo $fifofile $(mkfifo $fifofile 2>&1)" # exit 1 #fi #nohup cat $fifofile 2>&1 < /dev/null | pipelog dlog & #pipepid=$! #dlog "DEBUG: pipelog pid: $pipepid" #disable msg: nohup: ignoring input by cat /dev/zero #nice -n $SCRIPTNICE nohup $SCRIPTSELFT $ALLARGS daemon >> $fifofile 2>&1 < /dev/zero & SCRIPTTITLE=$(echo "$SCRIPTTITLE"|tr '/\- ' '_') nice -n $SCRIPTNICE nohup $SCRIPTSELFT $ALLARGS daemon "$SCRIPTTITLE" >> $DAEMONSTDIOFILE 2>&1 < /dev/zero & runcode=$? daemonedpid=$! # if [ $runcode -ne 0 ] then elog "ERROR: execute // $SCRIPTSELFT $ALLARGS daemon // failed:" elog "ERROR: got invalid exitcode: $runcode" exit 1 fi if [ -z "$daemonedpid" ]; then elog "ERROR: execute // $SCRIPTSELFT $ALLARGS daemon // failed:" elog "ERROR: got invalid pid: $daemonedpid" exit 1 fi test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: setproclock for daemon: $daemonedpid" setproclock "$daemonedpid" test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: running background: $daemonedpid" exit 0 else #already daemon # trap daemon only trap daemonexit SIGTERM SIGINT DAEMONED='yes' export PROC_LOCK_DEBUG='FALSE' fi setproclock "$SCRIPTPID" # } export SCRIPTWARNED=0 waitcleanup(){ test $SCRIPTWARNED -eq 0 && elog "INFO: waiting for cleanup ..." let SCRIPTWARNED=$SCRIPTWARNED+1 sleep 1 test $SCRIPTWARNED -ge 10 && exit 0 } daemonexit(){ delexitmark trap waitcleanup SIGTERM SIGINT SCRIPTWARNED=0 dlog "INFO: exiting ..." type -t daemonstop >/dev/null 2>&1 if [ $? -eq 0 ] then dlog "INFO: cleanup befor exit ..." daemonstop 2>&1 | pipelog dlog fi dlog "INFO: exited." exit 0 } daemonexited(){ local exitcode=$1 test -z "$exitcode" && exitcode=0 #like daemonexit type -t daemonpostexit >/dev/null 2>&1 if [ $? -eq 0 ] then dlog "INFO: post exit ..." daemonpostexit 2>&1 | pipelog dlog fi exit $exitcode } proc_ctl(){ if [ "$1" = 'restart' -o "$1" = 'reload' ] then trap - SIGTERM SIGINT SIGQUIT narg=`echo $@ | sed -e 's/restart//g'|sed -e 's/reload//g'|sed -e 's/ / /g'` $0 stop $narg >/dev/null 2>&1 sleep 1 $0 start $narg 2>&1 exit $? fi # if [ "$1" = 'status' ] then #return 0 for running trap - SIGTERM SIGINT SIGQUIT lckpid=$(getlockedprocpid) if [ -n "$lckpid" ] then kill -0 "$lckpid" 2>/dev/null if [ $? -eq 0 ] then # running test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: check proc lock status, running, pid: $lckpid" test "$2" != 'mute' && elog "INFO: running, pid: $lckpid" exit 0 else test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: check proc lock status, no running, pid: $lckpid" fi else test "${PROC_LOCK_DEBUG}" = 'TRUE' && dlog "DEBUG: check proc lock status, no lockpid" fi test "$2" != 'mute' && elog "INFO: no running." exit 1 fi if [ "$1" = 'stop' -o "$1" = 'kill' ] then # ctlop="$1" # killsig=15 # trap - SIGTERM SIGINT SIGQUIT lckpid=$(getlockedprocpid) if [ -n "$lckpid" ] then kill -0 "$lckpid" 2>/dev/null if [ $? -ne 0 ] then #no running daemonexited 0 fi # setexitmark # #conlog "WARNING: PROC_CALLER=$PROC_CALLER" # #/etc/init.d/rcS K shutdown # #/etc/init.d/rcS S boot # kill -$killsig "$lckpid" 2>/dev/null if [ $? -ne 0 ] then elog "ERROR: stop pid $lckpid failed." exit 1 else if [ "$PROC_CALLER" = "/etc/init.d/rcS K shutdown" ] then # export PROC_CALLER='/etc/init.d/rcS K shutdown' dlog "WARNING: fast $ctlop for system shutdown($PROC_CALLER)." releaselockedprocpid dlog "WARNING: kill all sleep for system shutdown($PROC_CALLER)." killall sleep daemonexited 0 fi wcnt=0 waitlimit=120 while [ : ] do lckpid=$(getlockedprocpid) test -z "$lckpid" && break if [ "$ctlop" = 'kill' ] then kill -9 "$lckpid" 2>/dev/null else sleep 1 fi kill -0 "$lckpid" 2>/dev/null || break let wcnt=$wcnt+1 test $wcnt -ge $waitlimit && break done kill -0 "$lckpid" 2>/dev/null if [ $? -ne 0 ] then elog "INFO: $ctlop pid $lckpid ok." else elog "ERROR: waiting for pid $lckpid exit timeout after $waitlimit seconds, KILLED." kill -9 "$lckpid" 2>/dev/null fi fi fi daemonexited 0 fi } procdaemon(){ #check lock #daemon proc_ctl $ALLARGS #set lock if [ "$DAEMONBYPASS" != 'yes' ] then # procgodaemon $ALLARGS # #else # dlog "daemon: bypass $SCRIPTSELFT $ALLARGS" fi } runintimeusage(){ echo "USAGE: runintimeusage " } runintime(){ timeout=$1 cmdline=$@ test -z "$timeout" && return 0 let timeout=$timeout+1-1 2>/dev/null test $? -ne 0 && runintimeusage && echo "ERROR: timeout($timeout) should be 1 - 120" && return 1 test $timeout -gt 120 -o $timeout -le 0 && runintimeusage && echo "ERROR: timeout($timeout) should be 1 - 120" && return 1 cmdline=$(echo $cmdline | sed -e "s/$timeout //") if [ -z "$cmdline" ] then runintimeusage echo "ERROR: command arg not found." return 1 fi #echo "DEBUG: running /$cmdline/$timeout ..." nowts=$(date +%s) doid=`echo "$nowts/$cmdline/$timeout"|md5sum|awk '{print $1}'` dofile="/tmp/`basename $0`.$$.$doid.tmp" touch $dofile $cmdline > $dofile 2>&1 & runcode=$? lookpid=$! wcnt=0 addlist='' while [ $wcnt -le $timeout ] do kill -0 $lookpid 2>/dev/null if [ $? -ne 0 ] then #it exited break fi let wcnt=$wcnt+1 sleep 1 done kill $lookpid 2>/dev/null linecat $dofile rm -f $dofile return $runcode # } find_mtd_part() { local PART="$(grep "\"$1\"" /proc/mtd | awk -F: '{print $1}')" local PREFIX=/dev/mtdblock PART="${PART##mtd}" [ -d /dev/mtdblock ] && PREFIX=/dev/mtdblock/ echo "${PART:+$PREFIX$PART}" } # getmtdbyname() { find_mtd_part $@ } # overlaymountdir(){ local showmnt local ovldir showmnt="$1" # #check ' /tmp/overlay-disabled' first # ovldir=`df | grep ' /tmp/overlay-disabled$'|awk '{print $6}'` if [ -z "$ovldir" ] then ovldir=`df | grep ' /overlay$'|awk '{print $6}'` fi if [ -z "$ovldir" ] then # if [ -n "$showmnt" ] then conlog "ERROR: overlay no mounted." conlog "---" conlog "INFO: current mount table:" conlog "---" # df | while read oneline do conlog "$oneline" done # fi # return 1 fi if [ -n "$showmnt" ] then conlog "INFO: overlay mounted: $ovldir" df 2>&1 | while read oneline do conlog "$oneline" done fi echo "$ovldir" return 0 } getoverlaydir(){ local showmnt showmnt="$1" local ovldir # #check ' /tmp/overlay-disabled' first # ovldir=$(overlaymountdir $@) if [ -n "$ovldir" ] then echo "$ovldir" return 0 fi # #waiting for overlay mount # conlog "---" conlog "INFO: waiting for overlay mounted, up to 60 seconds." conlog "---" # ovldir='' wcnt=0 while [ $wcnt -le 60 ] do ovldir=$(overlaymountdir) if [ -n "$ovldir" ] then break fi let wcnt=$wcnt+1 sleep 1 done # if [ -z "$ovldir" ] then conlog "ERROR: waiting for overlay mounted failed after 60 seconds." return 1 fi if [ -n "$showmnt" ] then conlog "INFO: overlay mounted: ${ovldir}" df | while read oneline do conlog "$oneline" done fi echo "$ovldir" return 0 } # ipalivecheck(){ local chkip mute pingret arpret chkip="$1" mute="$2" # test -z "$chkip" && return 1 # #check ip with ping and arp # /usr/bin/arp -d $chkip 2>/dev/null for fcnt in 1 2 3 4 5 6 7 8 9 10 do pingret=`ping -c 1 -w 1 $chkip | grep ': seq='|grep -c ' time='` arpret=`/usr/bin/arp -n | grep -v '00:00:00:00:00:00'|grep -v 'incomplete'|grep "^$chkip"` if [ $pingret -gt 0 -o -n "$arpret" ] then break fi done if [ $pingret -le 0 -a -z "$arpret" ] then test "$mute" = '0' && dlog "WARNING: $chkip unreachable." return 1 #else # dlog "DEBUG: $chkip alive: $arpret" fi return 0 } iplocalcheck(){ #return 0 for ok, local chkip mute arpret mark chkip="$1" mute="$2" mark="$3" test -z "$mark"&&mark='local' # test -z "$chkip" && return 1 # #check ip with ping and arp # ####niclist="`ifconfig | grep 'Link encap:' | awk '{print $1}'`" ##### ####for onenic in $niclist ####do #### #check p-to-p #### ifconfig $onenic 2>/dev/null | grep -i 'inet'|awk -F':' '{print $3}'|awk '{print $1}'|grep -q "$chkip" #### if [ $? -eq 0 ] #### then #### #p-to-p link: inet addr:10.0.109.10 P-t-P:10.0.109.254 Mask:255.255.255.255 #### return 0 #### fi ####done # #p-to-p link: inet addr:10.0.109.10 P-t-P:10.0.109.254 Mask:255.255.255.255 ifconfig | grep -q "P-t-P:$chkip " if [ $? -eq 0 ] then return 0 fi #my local ip is false ifconfig | grep -q "inet addr:$chkip " if [ $? -eq 0 ] then return 1 fi # #check ether /usr/bin/arp -d $chkip 2>/dev/null for fcnt in 1 2 3 4 do ping -c 1 -w 1 $chkip >/dev/null 2>&1 arpret=`/usr/bin/arp -n | grep -v '00:00:00:00:00:00'|grep -v 'incomplete'|grep "^$chkip"` if [ -n "$arpret" ] then break fi done if [ -z "$arpret" ] then test "$mute" = '0' && dlog "WARNING: $chkip unreachable in ${mark}." return 1 #else # dlog "DEBUG: $chkip reachable in ${mark}: $arpret" fi return 0 } iplocalethercheck(){ iplocalcheck $1 $2 'local ethernet' return $? } # ipconfictcheck(){ local chklist chknics onenic nicmac chkip cmpnic dupmac isconfict lannet wannet isconfict=0 chklist="$@" test -z "$chklist" && chklist='eth0.2 br-lan' for onenic in $chklist do nicmac=$(ifconfig eth0.2|grep 'HWaddr '|awk '{print $5}') chkip=$(/sbin/ifconfig $onenic 2>/dev/null | grep 'inet addr:' | awk -F'inet addr:' '{print $2}'| awk '{print $1}') chknics="$onenic" for cmpnic in $chknics do dupmac=$(/usr/bin/arping -D -f -b -c 1 -w 1 -s 0.0.0.0 -I $cmpnic $chkip 2>&1 | grep 'reply from ' | tr -d '[]' | awk -F"$chkip " '{print $2}'|awk '{print $1}') if [ -n "$dupmac" ] then test "$(arrfastget ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic})" != "1" && dlog "WARNING: IP of ${onenic}/${nicmac} $chkip confict with mac $dupmac at $cmpnic" arrfastset ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic} 1 let isconfict=$isconfict+1 else test "$(arrfastget ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic})" = "1" && dlog "INFO: IP confict of ${onenic}/${nicmac} $chkip at ${cmpnic} is gone." arrfastset ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic} 0 fi done done wannet=$(ip route list dev eth0.2 2>/dev/null| awk '/scope/{print$1}'|head -n1|pipegetspacepos 1) test -z "$wannet" && return $isconfict lannet=$(ip route list dev br-lan 2>/dev/null| awk '/scope/{print$1}'|head -n1|pipegetspacepos 1) if [ "$lannet" = "$wannet" ] then let isconfict=$isconfict+1 test "$(arrfastget ipconfict laneqwan)" != "1" && dlog "WARNING: wan network $wannet confict with lan network $lannet" arrfastset ipconfict laneqwan 1 else test "$(arrfastget ipconfict laneqwan)" = "1" && dlog "INFO: wan network $wannet confict with lan network $lannet is gone." arrfastset ipconfict laneqwan 0 fi return $isconfict } ipconfictcheck2(){ local chklist onenic nicmac chkip cmpnic dupmac isconfict lannet wannet isconfict=0 chklist="$@" test -z "$chklist" && chklist='eth0.2 br-lan' for onenic in $chklist do nicmac=$(ifconfig eth0.2|grep 'HWaddr '|awk '{print $5}') chkip=$(/sbin/ifconfig $onenic 2>/dev/null | grep 'inet addr:' | awk -F'inet addr:' '{print $2}'| awk '{print $1}') for cmpnic in $chklist do dupmac=$(/usr/bin/arping -D -f -b -c 1 -w 1 -s 0.0.0.0 -I $cmpnic $chkip 2>&1 | grep 'reply from ' | tr -d '[]' | awk -F"$chkip " '{print $2}'|awk '{print $1}') if [ -n "$dupmac" ] then test "$(arrfastget ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic})" != "1" && dlog "WARNING: IP of ${onenic}/${nicmac} $chkip confict with mac $dupmac at $cmpnic" arrfastset ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic} 1 let isconfict=$isconfict+1 else test "$(arrfastget ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic})" = "1" && dlog "INFO: IP confict of ${onenic}/${nicmac} $chkip at ${cmpnic} is gone." arrfastset ipconfict ${nicmac}-${onenic}-${chkip}-${cmpnic} 0 fi done done wannet=$(ip route list dev eth0.2 2>/dev/null| head -n1|pipegetspacepos 1) test -z "$wannet" && return $isconfict lannet=$(ip route list dev br-lan | head -n1|pipegetspacepos 1) if [ "$lannet" = "$wannet" ] then let isconfict=$isconfict+1 test "$(arrfastget ipconfict laneqwan)" != "1" && dlog "WARNING: wan network $wannet confict with lan network $lannet" arrfastset ipconfict laneqwan 1 else test "$(arrfastget ipconfict laneqwan)" = "1" && dlog "INFO: wan network $wannet confict with lan network $lannet is gone." arrfastset ipconfict laneqwan 0 fi return $isconfict } # #2013-11-27 21:18:29.000000000 #+%Y-%m-%d-%H:%M:%S # timestamp2date(){ local onets="$1" test -z "$onets" && return 1 echo "$(date -u -D '%s' -d "$onets" +%Y.%m.%d-%H:%M:%S)" return $? } rrd2timestamp(){ local onets="$@" local cnvts test -z "$onets" && return 1 onets="$(echo $onets | tr ' ' '-')" cnvts="$(date -u +'%s' -d "$onets" -D '%Y-%m-%d-%H:%M:%S')" test -z "$cnvts" && return 1 echo "$cnvts" return 0 } setclock2timestamp(){ local onets="$1" test -z "$onets" && return 1 tsstr="$(timestamp2date $onets)" test -z "$tsstr" && return 1 date -s "$tsstr" return $? } # basexec mkdir -p /tmp/daemon/ && basexec mkdir -p $SCRIPTARRAYDIR if [ $? -ne 0 ] then conlog "ERROR: lib.scripthelper.sh create directory /tmp/daemon/ and $SCRIPTARRAYDIR failed: $(basexec mkdir -p /tmp/daemon/ 2>&1) $(basexec mkdir -p $SCRIPTARRAYDIR 2>&1)" exit 1 fi # #trap daemonexit SIGTERM SIGINT SIGFPE SIGSTP #trap daemonexit SIGTERM SIGINT # trap - SIGTERM SIGINT SIGFPE SIGQUIT # ##