#!/bin/sh # Filename: systemctl # Location: /usr/sbin/ # Author: bgstack15@gmail.com # Startdate: 2020-01-10 13:02:14 # Title: # Purpose: # Package: systemdtl # History: # Usage: # Should be mostly like systemctl from systemd. # Reference: ftemplate.sh 2019-05-02a ; framework.sh 2018-05-02a # man 1 systemctl # Improve: # x restart X(.service)? # x start # x stop # x enable # x status # x disable # x mask # x unmask # x is-enabled # x is-active # x list-unit-files --full # x reload-or-try-restart X # x condrestart X # x daemon-reload --system # x --now fiversion="2019-05-02a" systemctlversion="2020-01-10a" usage() { ${PAGER:-/usr/bin/less -F} >&2 </dev/null # Delayed cleanup if test -z "${SYSTEMCTL_NO_CLEAN}" ; then # nohup /bin/bash </dev/null 2>&1 & #sleep "${SYSTEMCTL_CLEANUP_SEC:-300}" ; /bin/rm -r "${SYSTEMCTL_TMPDIR:-NOTHINGTODELETE}" 1>/dev/null 2>&1 ; #EOF /bin/rm -r "${SYSTEMCTL_TMPDIR:-NOTHINGTODELETE}" 1>/dev/null 2>&1 ; fi } CTRLC() { # use with: trap "CTRLC" 2 # useful for controlling the ctrl+c keystroke : } CTRLZ() { # use with: trap "CTRLZ" 18 # useful for controlling the ctrl+z keystroke : } parseFlag() { flag="$1" hasval=0 case ${flag} in # INSERT FLAGS HERE "d" | "debug" | "DEBUG" | "dd" ) setdebug ; ferror "debug level ${debug}" ; __debug_set_by_param=1 ;; "u" | "usage" | "help" | "h" ) usage ; exit 0 ;; "V" | "fcheck" | "version" ) ferror "${scriptfile} version ${systemctlversion}" ; exit 0 ;; #"i" | "infile" | "inputfile" ) getval ; infile1=${tempval} ;; "c" | "conf" | "conffile" | "config" ) getval ; conffile="${tempval}" ;; "now" ) export SYSTEMCTL_NOW=1 ;; "full") export SYSTEMCTL_FULL=1 ;; "system") export SYSTEMCTL_SYSTEM=1 ;; esac debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}" ; } } # DETERMINE LOCATION OF FRAMEWORK f_needed=20181030 ___frameworkpath="$( find $( echo "${FRAMEWORKPATH}" | tr ':' ' ' ) -maxdepth 1 -mindepth 0 -name 'framework.sh' 2>/dev/null )" while read flocation ; do if test -e ${flocation} ; then __thisfver="$( sh ${flocation} --fcheck 2>/dev/null )" ; if test ${__thisfver:-0} -ge ${f_needed} ; then frameworkscript="${flocation}" ; break ; elif test -n "${___thisfver}" ; then printf "Obsolete: %s %s\n" "${flocation}" "${__thisfver}" 1>&2 ; fi ; fi ; done <&2 && exit 4 # INITIALIZE VARIABLES # variables set in framework: # today server thistty scriptdir scriptfile scripttrim # is_cronjob stdin_piped stdout_piped stderr_piped sendsh sendopts . ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2 infile1= outfile1= define_if_new logfile "/var/log/systemctl.log" define_if_new interestedparties "bgstack15@gmail.com" # SIMPLECONF define_if_new default_conffile "/etc/systemdtl.conf" #define_if_new defuser_conffile ~/.config/systemctl/systemctl.conf #define_if_new SYSTEMCTL_TMPDIR "$( mktemp -d )" #tmpfile1="$( TMPDIR="${SYSTEMCTL_TMPDIR}" mktemp )" #tmpfile2="$( TMPDIR="${SYSTEMCTL_TMPDIR}" mktemp )" # REACT TO OPERATING SYSTEM TYPE case $( uname -s ) in Linux) : ;; FreeBSD) : ;; *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 3 ;; esac ## REACT TO ROOT STATUS #case ${is_root} in # 1) # proper root # : ;; # sudo) # sudo to root # : ;; # "") # not root at all # #ferror "${scriptfile}: 5. Please run as root or sudo. Aborted." # #exit 5 # : # ;; #esac # SET CUSTOM SCRIPT AND VALUES #setval 1 sendsh sendopts<&2 } # MAIN LOOP #{ printf "%s\n" "${*}" >> "${logfile}" #echo "thiscount=${thiscount}" #x=1 #while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; #do # eval thisopt="\${opt${x}}" # echo "thisopt${x}=${thisopt}" # x=$(( x + 1 )) #done # actions actionlist="" case "${action}" in restart|start|stop|status|reload|condrestart|try-restart|reload-or-try-restart) # re-map a few actions case "${action}" in "reload-or-try-restart") action=restart ;; esac x=1 while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; do eval thisopt="\${opt${x}}" thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )" actionstatement="$( printf "%s" "service ${thisopt} ${action};" )" actionlist="${actionlist:+${actionlist} }${actionstatement}" x=$(( x + 1 )) done ;; enable|disable|mask|unmask) case "${action}" in mask) action=disable ;; unmask) action=enable ;; esac x=1 while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; do eval thisopt="\${opt${x}}" thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )" actionstatement="$( printf "%s" "update-rc.d ${thisopt} ${action};" )" actionlist="${actionlist:+${actionlist} }${actionstatement}" test "${SYSTEMCTL_NOW}" = "1" && { case "${action}" in enable) nowaction=start ;; disable) nowaction=stop ;; esac actionstatement="$( printf "%s" "service ${thisopt} ${nowaction:-stop};" )" actionlist="${actionlist:+${actionlist} }${actionstatement}" } x=$(( x + 1 )) done ;; daemon-reload) debuglev 1 && echo "${action} is a NOP." ;; list-unit-files) # Future improvement: can consume --full, but I do not care enough to deal with it now. ls -Al /etc/init.d ;; is-enabled) currentrunlevel="$( who -r | grep -oE 'run-level\s+[[:digit:]]+' | awk '{print $NF}' )" responsenumber=1 # loop through each service on the command line x=1 while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; do eval thisopt="\${opt${x}}" thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )" #actionstatement="$( printf "%s" "service ${thisopt} ${action};" )" scriptfile="$( find "/etc/rc${currentrunlevel}.d" -mindepth 1 -maxdepth 1 -name "S??${thisopt}" 2>/dev/null )" responsetext="disabled" # if file exists, let us return 0. if test -n "${scriptfile}" ; then debuglev 2 && echo "${scriptfile}" responsenumber=0 # any "enabled" response makes systemctl return 0 responsetext="enabled" fi echo "${responsetext:-UNKNOWN}" x=$(( x + 1 )) done exit "${responsenumber}" ;; is-active) responsenumber=3 x=1 while test ${x:-${thiscount}} -le $(( thiscount - 1 )) && test ${thiscount} -gt 1 ; do eval thisopt="\${opt${x}}" thisopt="$( echo "${thisopt}" | sed -r -e 's/\.service$//;' )" #actionstatement="$( printf "%s" "service ${thisopt} ${action};" )" servicestatus="$( service "${thisopt}" status 1>/dev/null 2>&1 ; echo "${?}" )" responsetext="stopped" # if file exists, let us return 0. if test ${servicestatus:-1} -eq 0 ; then responsenumber=0 responsetext="active" fi echo "${responsetext:-unknown}" x=$(( x + 1 )) done exit "${responsenumber}" ;; *) ferror "Fatal! 2. Unable to understand action ${action}. Aborted." exit 2 ;; esac # list of actions echo "Need to perform these commands:" echo "${actionlist}" #} | tee -a ${logfile} # EMAIL LOGFILE #${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties} ## STOP THE READ CONFIG FILE #return_code 0 #fi ; done ; }