Skip to content

Instantly share code, notes, and snippets.

@Daniel-Abrecht
Created February 10, 2022 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Daniel-Abrecht/fe72299f62597f5b5087698ff2273c88 to your computer and use it in GitHub Desktop.
Save Daniel-Abrecht/fe72299f62597f5b5087698ff2273c88 to your computer and use it in GitHub Desktop.
#!/bin/bash
# The MIT License (MIT)
#
# Copyright © 2022
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the “Software”), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set -e
self="$(realpath "$0")"
if [ "$(id -u)" != 0 ]
then
pkexec "$self" "$@"
exit $?
fi
declare -A short_opts=(
[t]=type
[p]=property
[s]=signal
[n]=lines
[o]=output
[H]=host
[M]=machine
[a]=all
[r]=recursive
[l]=full
[T]=showtransaction
[q]=quiet
[f]=force
[h]=help
)
declare -A option_argcount=(
[type]=1
[state]=1
[property]=1
[jobmode]=1
[checkinhibitors]=1
[killwho]=1
[signal]=1
[what]=1
[message]=1
[root]=1
[presetmode]=1
[lines]=1
[output]=1
[bootloadermenu]=1
[bootloaderentry]=1
[rebootargument]=1
[timestamp]=1
[host]=1
[machine]=1
[legend]=1
[P]=0
[all]=0
[recursive]=0
[reverse]=0
[after]=0
[before]=0
[withdependencies]=0
[full]=0
[value]=0
[showtypes]=0
[showtransaction]=0
[fail]=0
[i]=0
[dryrun]=0
[quiet]=0
[noblock]=0
[wait]=0
[user]=0
[system]=0
[failed]=0
[nowall]=0
[global]=0
[noreload]=0
[noaskpassword]=0
[force]=0
[now]=0
[runtime]=0
[firmwaresetup]=0
[plain]=0
[mkdir]=0
[marked]=0
[readonly]=0
[nopager]=0
[help]=0
[version]=0
)
declare -A opts
args=()
die(){
printf "%s\n" "$*" >&2
exit 1
}
read_kv(){
if [[ "$1" == *=* ]]
then
has_value=1
IFS== read -r key value <<<"$1"
else
has_value=0
value=
key="$1"
fi
}
pre_shift(){
if [ "$1" = 0 ]
then die "$2"
fi
}
function_exists(){
if [[ "$(type -t "$1")" == function ]]
then return 0
else return 1
fi
}
key=
value=
has_value=
while [ $# -gt 0 ]
do
arg="$1"; shift
case "$arg" in
--*)
read_kv "${arg:2}"
count="${option_argcount["$key"]}"
if ! [ -n "$count" ]
then die "systemctl: unrecognized option '--$key'"
fi
if [ "$has_value" = 1 ] && [ "$count" = 0 ]
then die "Option --$key doesn't take an argument"
fi
if [ "$has_value" = 0 ] && [ "$count" -gt 0 ]
then value="$1"; pre_shift "$#" "systemctl: option requires an argument -- '$key'"; shift
fi
value=("$value")
while [ "$count" -gt "${#value[@]}" ]
do value+=("$1"); pre_shift "$#" "systemctl: option requires an argument -- '$key'"; shift
done
opts["$key"]="${value[*]}"
value=
;;
-*)
read_kv "${arg:1}"
i=0
while [ "$i" -lt "${#key}" ]
do
k="${key[i]}"
i=$((i + 1))
name="${short_opts["$k"]}"
if ! [ -n "$name" ]
then echo "systemctl: unrecognized option '-$k'"
fi
count="${option_argcount["$name"]}"
if ! [ -n "$count" ]
then die "systemctl: unrecognized option '-$k'/'--$name'"
fi
if [ "$has_value" = 1 ] && [ "$count" = 0 ]
then die "Option --$name doesn't take an argument"
fi
if [ "$has_value" = 0 ] && [ "$count" -gt 0 ]
then value="$1"; pre_shift "$#" "systemctl: option requires an argument -- '$k'/'$name'"; shift
fi
value=("$value")
while [ "$count" -gt "${#value[@]}" ]
do value+=("$1"); pre_shift "$#" "systemctl: option requires an argument -- '$k'/'$name'"; shift
done
opts["$name"]="${value[*]}"
value=
has_value=0
done
;;
*) args+=("$arg") ;;
esac
done
unset key value has_value
if [ "${#args[@]}" = 0 ]
then args=( list-units )
fi
service_file=
unit_type=
unit=
parse_unit(){
unit_type=service
service_file=
if [[ "$1" == *\.* ]]
then IFS='.' read -r unit unit_type <<<"$1"
else unit="$1"
fi
if [ "$unit_type" = service ] && [ -x "/etc/init.d/$unit" ]
then service_file="/etc/init.d/$unit"
fi
}
systemctl_halt(){
halt
}
systemctl_poweroff(){
poweroff
}
systemctl_reboot(){
reboot
}
systemctl_start(){
[ $# != 0 ] || die "Too few arguments"
ret=0
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
if ! service "$unit" start
then ret=3
fi
done
return $ret
}
systemctl_stop(){
ret=0
[ $# != 0 ] || die "Too few arguments"
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
if ! service "$unit" stop
then ret=3
fi
done
return $ret
}
systemctl_reload(){
[ $# != 0 ] || die "Too few arguments"
ret=0
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
if ! service "$unit" force-reload || service "$unit" reload
then ret=3
fi
done
return $ret
}
systemctl_restart(){
[ $# != 0 ] || die "Too few arguments"
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
if ! service "$unit" restart
then return $?
fi
done
}
systemctl_try-restart(){
systemctl_restart "$@"
return $?
}
systemctl_reload-or-restart(){
[ $# != 0 ] || die "Too few arguments"
while [ $# != 0 ]
do
parse_unit "$1"; shift
[ "$unit_type" = service ] || die "Unsupported unit type"
if service "$unit" status &>/dev/null
then
if ! systemctl_reload "$1" || systemctl_restart "$1"
then return $?
fi
fi
done
}
systemctl_try-reload-or-restart(){
[ $# != 0 ] || die "Too few arguments"
while [ $# != 0 ]
do
parse_unit "$1"; shift
[ "$unit_type" = service ] || die "Unsupported unit type"
if ! systemctl_reload-or-restart "$@"
then return $?
fi
done
}
systemctl_is-active(){
[ $# != 0 ] || die "Too few arguments"
ret=0
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type"
ret=3
fi
if service "$unit" status &>/dev/null
then
echo active
else
echo inactive
ret=3
fi
done
return $ret
}
systemctl_status(){
if [ $# = 0 ]
then
service --status-all
return $?
else
ret=0
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! active="$(systemctl_is-active "$unit.$unit_type")"
then ret=3
fi
if [ -n "$service_file" ]
then loaded="loaded ($service_file)"
else loaded="not-found"
fi
printf "• %s\n loaded: %s\n Active: %s\n\n" "$unit.$unit_type" "$loaded" "$active"
done
return $ret
fi
}
systemctl_enable(){
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
update-rc.d "$unit" defaults
update-rc.d "$unit" enable
done
return 0
}
systemctl_disable(){
while [ $# != 0 ]
do
parse_unit "$1"; shift
if ! [ "$unit_type" = service ]
then
echo "Unsupported unit type" >&2
continue
fi
update-rc.d "$unit" defaults-disabled
update-rc.d "$unit" disable
done
return 0
}
systemctl_reenable(){
systemctl_enable "$@"
return $?
}
systemctl_is-enabled(){ echo >&2 "operation is-enabled is not implemented yet"; }
systemctl_list-units(){ echo >&2 "operation list-units is not implemented yet"; }
systemctl_list-sockets(){ echo >&2 "operation list-sockets is not implemented yet"; }
systemctl_list-timers(){ echo >&2 "operation list-timers is not implemented yet"; }
systemctl_is-failed(){ echo >&2 "operation is-failed is not implemented yet"; }
systemctl_show(){ echo >&2 "operation show is not implemented yet"; }
systemctl_cat(){ echo >&2 "operation cat is not implemented yet"; }
systemctl_help(){ echo >&2 "operation help is not implemented yet"; }
systemctl_list-dependencies(){ echo >&2 "operation list-dependencies is not implemented yet"; }
systemctl_isolate(){ echo >&2 "operation isolate is not implemented yet"; }
systemctl_kill(){ echo >&2 "operation kill is not implemented yet"; }
systemctl_clean(){ echo >&2 "operation clean is not implemented yet"; }
systemctl_freeze(){ echo >&2 "operation freeze is not implemented yet"; }
systemctl_thaw(){ echo >&2 "operation thaw is not implemented yet"; }
systemctl_set-property(){ echo >&2 "operation set-property is not implemented yet"; }
systemctl_bind(){ echo >&2 "operation bind is not implemented yet"; }
systemctl_mount-image(){ echo >&2 "operation mount-image is not implemented yet"; }
systemctl_service-log-level(){ echo >&2 "operation service-log-level is not implemented yet"; }
systemctl_service-log-target(){ echo >&2 "operation service-log-target is not implemented yet"; }
systemctl_reset-failed(){ echo >&2 "operation reset-failed is not implemented yet"; }
systemctl_list-unit-files(){ echo >&2 "operation list-unit-files is not implemented yet"; }
systemctl_preset(){ echo >&2 "operation preset is not implemented yet"; }
systemctl_preset-all(){ echo >&2 "operation preset-all is not implemented yet"; }
systemctl_mask(){ echo >&2 "operation mask is not implemented yet"; }
systemctl_unmask(){ echo >&2 "operation unmask is not implemented yet"; }
systemctl_link(){ echo >&2 "operation link is not implemented yet"; }
systemctl_revert(){ echo >&2 "operation revert is not implemented yet"; }
systemctl_add-wants(){ echo >&2 "operation add-wants is not implemented yet"; }
systemctl_edit(){ echo >&2 "operation edit is not implemented yet"; }
systemctl_get-default(){ echo >&2 "operation get-default is not implemented yet"; }
systemctl_set-default(){ echo >&2 "operation set-default is not implemented yet"; }
systemctl_list-machines(){ echo >&2 "operation list-machines is not implemented yet"; }
systemctl_list-jobs(){ echo >&2 "operation list-jobs is not implemented yet"; }
systemctl_cancel(){ echo >&2 "operation cancel is not implemented yet"; }
systemctl_show-environment(){ echo >&2 "operation show-environment is not implemented yet"; }
systemctl_set-environment(){ echo >&2 "operation set-environment is not implemented yet"; }
systemctl_unset-environment(){ echo >&2 "operation unset-environment is not implemented yet"; }
systemctl_import-environment(){ echo >&2 "operation import-environment is not implemented yet"; }
systemctl_daemon-reload(){ echo >&2 "operation daemon-reload is not implemented yet"; }
systemctl_daemon-reexec(){ echo >&2 "operation daemon-reexec is not implemented yet"; }
systemctl_log-level(){ echo >&2 "operation log-level is not implemented yet"; }
systemctl_log-target(){ echo >&2 "operation log-target is not implemented yet"; }
systemctl_service-watchdogs(){ echo >&2 "operation service-watchdogs is not implemented yet"; }
systemctl_is-system-running(){ echo >&2 "operation is-system-running is not implemented yet"; }
systemctl_default(){ echo >&2 "operation default is not implemented yet"; }
systemctl_rescue(){ echo >&2 "operation rescue is not implemented yet"; }
systemctl_emergency(){ echo >&2 "operation emergency is not implemented yet"; }
systemctl_kexec(){ echo >&2 "operation kexec is not implemented yet"; }
systemctl_exit(){ echo >&2 "operation exit is not implemented yet"; }
systemctl_switch-root(){ echo >&2 "operation switch-root is not implemented yet"; }
systemctl_suspend(){ echo >&2 "operation suspend is not implemented yet"; }
systemctl_hibernate(){ echo >&2 "operation hibernate is not implemented yet"; }
systemctl_hybrid-sleep(){ echo >&2 "operation hybrid-sleep is not implemented yet"; }
systemctl_suspend-then-hibernate(){ echo >&2 "operation suspend-then-hibernate is not implemented yet"; }
set +e
if function_exists "systemctl_${args[0]}"
then "systemctl_${args[0]}" "${args[@]:1}"
else die "Unknown operation ${args[0]}"
fi
exit $?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment