Created
February 10, 2022 11:00
-
-
Save Daniel-Abrecht/fe72299f62597f5b5087698ff2273c88 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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