File qserv of Package systemd-qserv
#!/usr/bin/env bash
#: Title : qserv
#: Sypnosis : qserv [options]
#: Date Created : Thu Feb 18 10:45:54 PHT 2012
#: Last Edit : Tue Sep 10 07:03:56 PHT 2013
#: License : GPL-2+0
#: Version : 1.0
#: Author : Jason V. Ferrer '<jetchisel@opensuse.org>'
#: Description : A simple interactive script that handles systemd services for OpenSUSE.
#: Options : [ -h --help ][ -? ][ -a --about][ -v --version ]
#: Note : This is just a front end to systemd's systemctl and a not replacement.
# NOTE :
# :
# TODO :
# Only root can deal with systemctl, as a normal user you need to enter the roots password. or use your favorite sudo utility.
###############################################################################################################################
# The menu still needs some (professional) redesigning but overall functionality was tested and seems to be working as expected.
shopt -s extglob
shopt -s checkwinsize
COLUMNS=$(tput cols)
LINES=$(tput lines)
trap 'COLUMNS=$(tput cols) LINES=$(tput lines)' WINCH
## The colors
if [[ -t 1 ]]; then
red=$(tput setaf 1)
bold=$(tput bold)
normal=$(tput sgr0)
gb=$(tput setaf 2 && tput bold) #"$green$bold"
rb=$(tput setaf 1 && tput bold)
fi
half=$(($COLUMNS / 2))
barso=
Heading() { "$@";}
samp() { "$@"; }
if [[ $DISPLAY ]]; then ## the trap for COLUMNS is still buggy!
barso=$(for ((j=0;j<=$(($half + 2));j++)); do printf "%s" '='; done)
Heading() { printf "%s\n %$(($half - 4))s \n%s\n\n" "$Barso" "$Title" "$Barso"; }
samp() { printf "%s\n %$(($half))s \n%s\n\n" "$Barso" "$Example $Sample" "$Barso" ; }
else
barso=$(for ((j=0;j<$COLUMNS;j++)); do printf "%s" '='; done)
Heading() { printf "%s\n %$(($half + 26))s \n%s\n\n" "$Barso" "$Title" "$Barso" ;}
samp() { printf "%s\n %$(($half + 48))s \n%s\n\n" "$Barso" "$Example $Sample" "$Barso" ; }
fi
version_() { version='Systemd-qserv 1.0'; printf "\n%s\n\n" "$version"; }
printf -v Barso "%s$barso%s" "$gb" "$normal"
printf -v Title "%sWelcome to qserv press the H key for help%s" "$bold" "$normal" ##
## This is the menu where you can choose from. You only need to press the number or letter from the choices the -n1 from read does the magic
Menu() {
action_=(Start Stop Restart Reload Enable Disable Query List Sysmode 'Man qserv' Help About Quit)
all_=({1..9} M H A Q)
for i in "${!all_[@]}"; do
printf -v all "%s[${all_[i]}]%s" "$gb" "$normal"
printf -v action "%s${action_[i]}%s" "$bold" "$normal"
printf "%s\n" "$all $action"
done
echo
}
_foos=("list_" "quit" "Man_" "Return_")
_bars=("List" "Quit" "Man" "Return")
for i in "${!_foos[@]}"
do printf -v "${_foos[$i]}" "%s${_bars[$i]}%s" "$gb" "$normal"
done
notes() {
sample=(apache2 sshd mysql nfs cifs cups vboxdrv)
printf -v Sample "%s${sample[*]}%s" "$gb" "$normal"
printf -v Example "%sservices are:%s"
samp
printf "%s\n" "$Return_: Return to main menu." "$list_: List services." "$quit: Exit ${0##*/}"
}
sysnote() {
printf -v key "%sJust key in the arguments to systemctl%s" "$bold" "$normal"
printf "%s\n %$(($half - 4))s \n%s\n\n" "$Barso" "$key" "$Barso"
cat <<-EOF
$Man_ : Read systemctl's man page.
$list_: List services.
$quit: Exit ${0##*/}
$Return_: Return to main menu.
EOF
}
About() {
foos_=("float" "MainDev" "Bman")
bars_=("1.0" "MAINTAINER AND DEVELOPER:" "INITIAL PACKAGER FOR openSUSE:")
for i in "${!foos_[@]}"
do printf -v "${foos_[$i]}" "%s${bars_[$i]}%s" "$bold" "$normal"
done
less <<-EOF
You are using version $float
Systemd-qserv is just a front end to systemctl and not a replacement for it.
It was written in the hope that user's will not have a hard time switching
to systemd. It's goal is to make one's life easier when dealing with systemd's
units (*.services.) This program only scratches the surface about what can be
done. OpenSUSE has a nice tool called yast/yast2 to deal with such advance task!
This program is free software you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful
but WITHOUT ANY WARRANTY without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
$MainDev
Jason V. Ferrer 'Jetchisel <jetchisel@opensuse.org>'
$Bman
Boris Manojlovic 'bmanojlovic <boris@steki.net>'
Some detailed information you can find in this site.
http://jason.ferrer.com.ph/2012/03/systemd-qserv.html
EOF
clear
}
usage() {
cat <<-EOF
Usage: ${0##*/} [ -h --help ][ -? ][ -a --about][ -v --version ]
EOF
}
Help() {
foos=("interactive" "looks" "author")
bars=("INTERACTIVE" "SEE ALSO" "AUTHOR")
for i in "${!foos[@]}"
do printf -v "${foos[$i]}" "%s${bars[$i]}%s" "$bold" "$normal"
done
less <<-EOF
Usage: ${0##*/} [ -h --help ][ -? ][ -a --about][ -v --version ]
To use the $interactive menu just run ${0##*/} without any option.
Press 1 to start service(s):
Press 2 to stop service(s):
Press 3 to restart services(s):
Press 4 to reload service(s):
Press 5 to enable service(s):
Press 6 to disable service(s):
Press 7 to check the status of a specific service(s):
Press 8 to list available services:
Press 9 systemctl mode:
Press M qserv man page:
Press Q to quit this menu:
You can put one or more service at a time and it can be without a '*.service' ie sshd apache2 mysql
or with a '*.service' extension ie 'sshd.service apache2.service mysql.service' or a mix of both!
The only limitation in systemctl mode is using a command that it does not recognize! Press the return
key during the systemctl mode to acquire a more detailed info about it's units.
$looks
systemctl(1)
$author
Jason V. Ferrer 'Jetchisel <jetchisel@opensuse.org>'
EOF
clear
}
Solution() {
line=()
while read -ra _line; do
[[ "${_line[0]}" != *.service ]] && continue
line+=("${_line[0]}")
done < <(systemctl list-units --all)
printf -v output "%s|" "@(${line[@]%.service})"
output=${output%%|}
temp=("${serv[@]%.service}") ## remove the extension if there is any. no extension is not affected.
## so mixing a service with or without extension is allowed.
combined=()
tmps=() ## This creates an array which only is listed in systemctl list-units --all.
for serve in "${temp[@]}"; do
[[ $serve != $output ]] && continue
tmps+=("$serve")
done
tmps_=() ## This creates an array which is not listed in systemctl list-units --all.
for serve_ in "${temp[@]}"; do
[[ $serve_ != $output ]] || continue
tmps_+=("$serve_")
done
combined+=("${tmps[@]}" "${tmps_[@]}") ## combined tmps_ and tmps
"$@"
}
colored() { ## colored output of error and 'active (running)'
old='error'
old_='active (running)' ##
printf -v new "%s$old%s" "$rb" "$normal"
printf -v new_ "%s$old_%s" "$gb" "$normal"
while IFS= read -u8 -r one; do
one=${one//$old/$new} ## A simple search and replace using PE.
printf "%s\n" "${one//$old_/$new_}"
done 8< <(systemctl status "${temp[@]/%/.service}") | less
}
paused() {
echo
printf -v prompt "%sDo you want to see the status? Y\N %s" "$gb" "$normal"
read -r -e -p "$prompt" -n1 button
case "$button" in
[Yy]) colored ;;
[Nn]) return ;;
*) printf "%s\n\n" "Invalid answer!"
paused
esac
}
list() { ## We only need the services.
Old=failed
old=error
final=()
printf -v new "%s$old%s" "$rb" "$normal"
printf -v New "%s$Old%s" "$rb" "$normal"
mapfile -t lines < <(systemctl list-units --all)
for i in "${!lines[@]}"; do
[[ ${lines[i]%% *} != *.service ]] && continue
final+=("${lines[i]//$old/$new}")
done
printf "%s\n" "${final[@]//$Old/$New}" | less
}
## the empty variable we define global.
printf -v empty "%sPlease enter a service!%s" "$bold" "$normal"
Progress() { ## A simple progress meter :-)
echo ## we only need the echo to have an additional blank space.
i=0
while ((i <= 100)); do
printf "\r%1d%% complete..." $i
((i += RANDOM%5+2))
## Will accept all arguments in systemctl. So you can run "Progress systemctl blah...blah" :-)
done
echo
}
forced() {
## Some service is not listed but that does not mean they dont exist, most probably they are disabled.
printf "\n%s$rb${tmps_[*]} $normal is not listed as a service (probably disabled) trying..!\n" >&2
}
start_() {
## check if input is both listed and not listed in systemctl list-units --all.
## the variable "$output" is the list that has the listed services.
if ((${#tmps[@]})) && ((${#tmps_[@]})); then
## Some service is not listed but that does not mean they dont exist, most probably they are disabled.
forced
## Process them both with systemctl and let the pause function handle the errors.
## 2>/dev/null also discards the Progress function's error printing to stder.
Progress < <(systemctl start "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been started. (or at least tried)"
paused
## Check if input is ONLY listed in systemctl list-units --all. The variable "$output" holds it.
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
## Process it directly with systemctl.
Progress < <(systemctl start "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been started. (or at least tried)"
paused
else
## return to menu if all the input is not valid.
forced
Progress < <(systemctl start "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
start() { ## We use the 'clear' external program to clear the cluttered screen.
while :; do ## Again a while loop so we will not exit the session without the q button.
clear
notes
printf -v prompt "\n%s(Enter the service(s) to start) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;; ## not allowed using the empty variable at line 250.
[Ll]|[Ll][Ii][Ss][Tt]) list ;; ## some false positive testing :D
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution start_ ;; ## check for extension and without extension
esac
done
}
stop_() {
if ((${#tmps[@]})) && ((${#tmps_[@]}));then
forced
Progress < <(systemctl stop "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been stopped. (or at least tried)"
paused
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
Progress < <(systemctl stop "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been stopped. (or at least tried)"
paused
else
forced
Progress < <(systemctl stop "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
stop() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to stop) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution stop_ ;;
esac
done
}
restart_() {
if ((${#tmps[@]})) && ((${#tmps_[@]}));then
forced
Progress < <(systemctl restart "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been restarted. (or at least tried)"
paused
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
Progress < <(systemctl restart "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been restarted. (or at least tried)"
paused
else
forced
Progress < <(systemctl restart "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
restart() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to restart) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution restart_ ;;
esac
done
}
reload_() {
if ((${#tmps[@]})) && ((${#tmps_[@]}));then
forced
Progress < <(systemctl reload "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been reloaded. (or at least tried)"
paused
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
Progress < <(systemctl reload "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been reloaded. (or at least tried)"
paused
else
forced
Progress < <(systemctl reload "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
reload() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to reload) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution reload_;;
esac
done
}
Enable_() {
if ((${#tmps[@]})) && ((${#tmps_[@]}));then
forced
Progress < <(systemctl enable "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been enabled. (or at least tried)"
paused
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
Progress < <(systemctl enable "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been enabled. (or at least tried)"
paused
else
forced
Progress < <(systemctl enable "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
Enable() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to enable) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution Enable_ ;;
esac
done
}
disable_() {
if ((${#tmps[@]})) && ((${#tmps_[@]}));then
forced
Progress < <(systemctl disable "${combined[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been disabled. (or at least tried)"
paused
elif ((${#tmps[@]})) && ((! ${#tmps_[@]})); then
Progress < <(systemctl disable "${tmps[@]/%/.service}" 2>/dev/null) && printf "\n%s\n" "$gb${tmps[*]}$normal has been disabled. (or at least tried)"
paused
else
forced
Progress < <(systemctl disable "${tmps_[@]/%/.service}" 2>/dev/null)
paused
fi
}
disable() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to disable) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) Solution disable_ ;;
esac
done
}
query() {
while :; do
clear
notes
printf -v prompt "\n%s(Enter the service(s) to query) ==> %s" "$gb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
"") printf "\n%s$empty" 2>&1; sleep 1 ;;
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0 ;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
!(*.service)|*.service) temp=("${serv[@]%.service}")
colored ;;
esac
done
}
##Systemctl mode you can do things like '--system daemon-reload'.
Systemctl() {
while :; do
clear
sysnote
printf -v prompt "\n%ssystemctl:~>%s " "$rb" "$normal"
read -r -e -p "$prompt" -a serv
[[ ${serv[@]} ]] && history -s "${serv[@]}"
case "${serv[@]}" in
[Ll]|[Ll][Ii][Ss][Tt]) list ;;
[Mm]|[Mm][Aa][Nn]) man systemctl ;;
[Qq]|[Qq][Uu][Ii][Tt]) clear; exit 0;;
[Rr]|[Rr][Ee][Tt][Uu][Rr][Nn]) clear; break ;;
*) systemctl "${serv[@]}"; sleep 3;;
esac
done
}
choice() {
printf -v prompt "%s(Enter your choice) ==>%s " "$gb" "$normal" ##
read -r -e -p "$prompt" -n1 serv
}
Quit() {
clear
exit 0
}
Unknown () {
single=(H help)
var=(H_ help_)
for n in "${!single[@]}"; do
printf -v "${var[$n]}" "%s${single[$n]}%s" "$gb" "$normal"
done
echo
printf "%s" "Unknown option press the $H_ key for $help_"!
sleep 2
}
## This is where it all started :-).
MainScript() {
while :; do
clear
Heading
Menu
choice
case $serv in
1) start ;;
2) stop ;;
3) restart ;;
4) reload ;;
5) Enable ;;
6) disable ;;
7) query ;;
8) list ;;
9) Systemctl ;;
[Aa]) About ;;
[Qq]) Quit ;; ## Exit when the Q or q button is pressed.
[Hh]) Help ;;
[Mm]) man qserv ;; ## Read qserv man page.
*) Unknown ;;
esac
clear
done
}
## parsing options
while :; do
case "$1" in
-h | --help | -\?) Help; exit 0 ;;
-a | --about) About; exit 0 ;;
-v | --version) version_; exit 0 ;;
--) shift; break ;;
-*) echo "WARN: Unknown option (ignored): $1" >&2
usage
exit 1 ;;
'') MainScript ;; # no more options. start MainScript
*) usage ; exit 1
esac
done
## Penito la musica!