-
-
Save Node0/ef2f12469e27501f6cd67cb5db2ead0d to your computer and use it in GitHub Desktop.
Wrapper script to aid and shorten systemd commands
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
| # vim: tabstop=4 shiftwidth=4 fenc=utf-8 spell spelllang=en cc=120 | |
| # | |
| # FILE: systemctl-shell-accelerator.bash | |
| # DESCRIPTION: Convenience method wrappers for Systemd | |
| # LICENSE: Apache 2.0 | |
| # CREDITS: http://github.com/yaffare/systemd-shell-wrapper http://github.com/mortn/systemd-shell-wrapper | |
| # MODIFIED BY: https://gist.github.com/Node0/ef2f12469e27501f6cd67cb5db2ead0d | |
| # INSTALLATION: wget -SO/etc/profile.d/systemd-wrapper.sh https://gist.githubusercontent.com/Node0/ef2f12469e27501f6cd67cb5db2ead0d/raw/3109a02eea54c90038df623c0adac2eec2b59228/systemd-wrapper.sh | |
| # | |
| # Exit if not BASH_VERSION is set | |
| if [ -z "$BASH_VERSION" ]; then return; fi | |
| if [[ -f /etc/systemd/shell-wrapper.conf ]]; then | |
| source /etc/systemd/shell-wrapper.conf | |
| else | |
| HIDEDAEMONS=(console-getty console-shell debug-shell ftpd nscd sshdgenkeys \ | |
| systemd-readahead-collect systemd-readahead-drop systemd-readahead-replay) | |
| fi | |
| # some people seem to not have /usr/bin in $PATH when using sudo | |
| if [ -x $(which systemctl) ];then _systemctl=$(which systemctl); else _systemctl="/bin/systemctl";fi | |
| if [ -x $(which journalctl) ];then _journalctl=$(which journalctl); else _journalctl="/bin/journalctl";fi | |
| sdStart() { s_systemctl "start" $1; } | |
| sdStop() { s_systemctl "stop" $1; } | |
| sdRestart() { s_systemctl "restart" $1; } | |
| sdReload() { s_systemctl "reload" $1; } | |
| sdEnable() { s_systemctl "enable" $1; } | |
| sdDisable() { s_systemctl "disable" $1; } | |
| sdStat() { s_systemctl "status" $1; } | |
| sdShowFailed() { $_systemctl --failed; } | |
| sdAnalyze() { systemd-analyze $*; } | |
| sdVerify() { systemd-analyze verify $*;} | |
| sdWants() { $_systemctl show -p "Wants" $1; } | |
| sdShowLogSize() { s_exec "${_journalctl}"" --disk-usage"; } | |
| sdList() { s_list_services "list"; } | |
| sdFilterList() { $_systemctl "list-unit-files" "${1}" | grep -v static } | |
| sdLog() { s_journalctl "$@"; } | |
| sdTail() { $_journalctl -f "$@"; } | |
| sdTree() { s_exec "/usr/bin/systemd-cgls --all"; } | |
| sdTruncateLog() { | |
| s_exec "${_systemctl}"" start systemd-journal-flush.service" | |
| s_exec "/bin/rm /var/log/journal/""$(cat /etc/machine-id)""/system@*" | |
| s_exec "${_systemctl}"" kill --kill-who=main --signal=SIGUSR2 systemd-journald.service" | |
| } | |
| # Function to unify regex matching, so we don't have to duplicate | |
| # the regular expression. It returns the success of failure in matching $1 | |
| # $1: unit name to match | |
| s_match_unit_name() { | |
| # ^(([^@.]*)(@([^.]*))?)(\.(.*))?$ | |
| # ([^@.]*) = matches any starting character that is not a @ and a . | |
| # This is the unit name, per se. | |
| # (@([^.]*))? = matches any template parameter, if present. | |
| # (\.(.*))? = matches the service type, if present. | |
| # The array BASH_REMATCH will be fileed with the following elements, | |
| # if the match happens: | |
| # 0: the whole unit name | |
| # 1: the unit name, with possible template parameter | |
| # 2: the basic unit name, without parameter | |
| # 3: @<template parameter> | |
| # 4: <template parameter> | |
| # 5: .<unit type> | |
| # 6: <unit type> | |
| [[ "$1" =~ ^(([^@.]*)(@([^.]*))?)(\.(.*))?$ ]] | |
| } | |
| # $1 unit name, with possible type | |
| # $2 default unit type, to be returned if not found in $1 | |
| s_get_unit_type() { | |
| local defType=${2:-service} | |
| if s_match_unit_name "$1"; then | |
| echo "${BASH_REMATCH[6]:-$defType}" | |
| fi | |
| } | |
| # $1 unit name, with possible template parameter | |
| s_get_template_parameter() { | |
| if s_match_unit_name "$1"; then | |
| echo "${BASH_REMATCH[4]}" | |
| fi | |
| } | |
| # Returns the pure unit name and optional template parameter | |
| # $1 input unit name, with possible "address" and type | |
| s_get_unit_name() { | |
| if s_match_unit_name "$1"; then | |
| echo "${BASH_REMATCH[1]}" | |
| fi | |
| } | |
| # Returns the unit name, without any template parameter and unit type | |
| s_get_basic_unit_name() { | |
| if s_match_unit_name "$1"; then | |
| echo "${BASH_REMATCH[2]}" | |
| fi | |
| } | |
| s_systemctl() { | |
| # allow full status listing | |
| if [[ "$1"=="status" && -z $2 ]]; then ${_systemctl} status; return; fi | |
| unitType="$(s_get_unit_type $2 $3)" | |
| unitName="$(s_get_unit_name $2)" | |
| daemon="$unitName.$unitType" | |
| if [[ $(s_daemon_exists $daemon $unitType) == 1 ]]; then | |
| echo -e "\e[1;31m:: \e[1;37m ${daemon/.service/} daemon does not exist\e[0m"; return | |
| fi | |
| s_exec "/bin/true" # if sudo then ask for password now to avoid messing up the output later | |
| case $1 in | |
| start|stop|restart|reload) | |
| systemctl -q is-active "${daemon}" >& /dev/null | |
| if [[ $? -eq 0 ]]; then | |
| if [[ "$1" == "start" ]]; then echo -e "\e[1;31m:: \e[1;37m ${daemon/.service/} daemon is already running\e[0m"; return; fi | |
| else | |
| if [[ "$1" != "start" ]]; then | |
| echo -e "\e[1;31m:: \e[1;37m ${daemon/.service/} daemon is not running\e[0m"; | |
| if [[ "$1" != "restart" ]]; then return; fi | |
| fi | |
| fi | |
| if [[ "$1" == "start" ]]; then echo -en "\e[1;34m:: \e[1;37m Starting ${daemon/.service/} daemon\e[0m"; cols=25; fi | |
| if [[ "$1" == "stop" ]]; then echo -en "\e[1;34m:: \e[1;37m Stopping ${daemon/.service/} daemon\e[0m"; cols=25; fi | |
| if [[ "$1" == "restart" ]]; then echo -en "\e[1;34m:: \e[1;37m Restarting ${daemon/.service/} daemon\e[0m"; cols=27; fi | |
| if [[ "$1" == "reload" ]]; then echo -en "\e[1;34m:: \e[1;37m Reloading ${daemon/.service/} daemon\e[0m"; cols=26; fi | |
| s_exec "${_systemctl} -q ${1} ${daemon}" | |
| if [[ $? -eq 0 ]]; then | |
| s_msg ${daemon/.service/} $cols 7 "DONE" | |
| else | |
| s_msg ${daemon/.service/} $cols 1 "FAIL" | |
| s_systemctl "status" $daemon | |
| fi | |
| ;; | |
| enable|disable) | |
| if [[ ! "${daemon}" =~ @ ]]; then # sadly is-enabled does not work as expected for "@" services like dhcpcd@eth0 | |
| if ${_systemctl} -q is-enabled "${daemon}" >& /dev/null; then | |
| if [[ "$1" == "enable" ]]; then echoerror "${daemon/.service/} daemon is already enabled"; return; fi | |
| else | |
| if [[ "$1" == "disable" ]]; then echo -e "\e[1;31m:: \e[1;37m ${daemon/.service/} daemon is not enabled\e[0m"; return; fi | |
| fi | |
| fi | |
| f=${1:0:1} | |
| echo -en "\e[1;34m:: \e[1;37m ""${f^^}""${1:1:${#1}-2}""ing ${daemon/.service/} daemon\e[0m" | |
| if [[ "$1" == "enable" ]]; then cols=25; else cols=26; fi | |
| s_exec "${_systemctl} -q ${1} ${daemon}" | |
| if [[ $? -eq 0 ]]; then s_msg ${daemon/.service/} $cols 7 "DONE"; else s_msg ${daemon/.service/} $cols 1 "FAIL"; fi | |
| ;; | |
| status) | |
| ${_systemctl} status ${daemon} | |
| ;; | |
| esac | |
| } | |
| s_journalctl() { | |
| unitType="$(s_get_unit_type $1)" | |
| unitName="$(s_get_unit_name $1)" | |
| daemon="$unitName.$unitType" | |
| if [[ $(s_daemon_exists "${daemon}" $unitType) == 0 ]]; then | |
| options=""; for ((i=1; i<$#; ++i )) ; do options="${options}""${!i}"" "; done | |
| echo "${_journalctl} --all $options _SYSTEMD_UNIT=${daemon}"; | |
| s_exec "${_journalctl} --all $options _SYSTEMD_UNIT=${daemon}"; | |
| else | |
| echo "${_journalctl} --all $*"; | |
| s_exec "${_journalctl} --all $*"; | |
| fi | |
| } | |
| s_list_services () { $_systemctl --no-legend -t service list-unit-files | grep -v static \ | |
| | { | |
| while read -r daemon daemonstate ; do | |
| # ignore symlinks like crond.service (they dont work anyway, you can start/stop but not enable/disable) | |
| if [[ -h "/usr/lib/systemd/system/$daemon" ]]; then continue; fi | |
| # support for "@" stuff like dhcpcd@eth0 dhcpcd@eth1 ... | |
| if [[ "${daemon:${#daemon}-9}" == "@.service" ]]; then | |
| daemons=$(${_systemctl} --no-legend -t service | grep -o "${daemon/.service/}[A-Za-z0-9_/=:.-]*") | |
| if [[ "${daemons[0]}" == "" ]]; then daemons=($daemon); fi # when no instance of "@" service is started it appears just as dhcpcd@ | |
| else | |
| daemons=($daemon) | |
| fi | |
| for daemon in $daemons; do | |
| if s_hidedaemon "${daemon/.service/}"; then continue; fi; | |
| if [[ "${1}" == "list" ]]; then | |
| echo -en "\e[1;34m["; | |
| elif [[ "${1}" == "enabled" || "${1}" == "disabled" ]]; then | |
| if [[ "${1}" == "${daemonstate}" ]]; then printf "%s\n" "${daemon/.service/}"; fi | |
| continue | |
| fi | |
| ${_systemctl} -q is-active "${daemon}" >& /dev/null | |
| if [[ $? -eq 0 ]]; then | |
| if [[ "${1}" == "list" ]]; then | |
| echo -en "\e[1;37mSTARTED" | |
| else | |
| if [[ "${1}" != "stopped" ]]; then printf "%s\n" "${daemon/.service/}"; fi | |
| fi | |
| else | |
| if [[ "${1}" == "list" ]]; then | |
| echo -en "\e[1;31mSTOPPED" | |
| else | |
| if [[ "${1}" != "started" ]]; then printf "%s\n" "${daemon/.service/}"; fi | |
| fi | |
| fi | |
| if [[ "${1}" != "list" ]]; then continue; fi | |
| echo -en "\e[1;34m][\e[1;37m" | |
| # !!! in the rare case of having two or more "@" instances (dhcpcd@) from the same service having different states (en/disabled) this actually shows wrong results | |
| if [[ "${daemonstate}" == "enabled" ]]; then | |
| echo -n "AUTO" | |
| else | |
| echo -n " " | |
| fi | |
| echo -en "\e[1;34m]\e[0m " | |
| echo "${daemon/.service/}" | |
| done | |
| done; | |
| } | |
| } | |
| # $1: Optional type of unit. The default is service | |
| s_daemon_exists() { | |
| unitType="$(s_get_unit_type $1 ${2:-service})" | |
| baseName="$(s_get_basic_unit_name $1)" | |
| if ${_systemctl} --no-legend -t "$unitType" list-unit-files | grep -v static | (grep -Eq "^$baseName(@.*)?\.$unitType" >& /dev/null); then echo 0; else echo 1; fi | |
| } | |
| s_msg() { | |
| printf "%s%*s%s%s%s%s%s%s\n" "$(tput bold ; tput setaf 4)" $(($(tput cols)-${#1}-${2})) "[" "$(tput bold ; tput setaf $3)" "${4}" "$(tput bold ; tput setaf 4)" "]" "$(tput sgr0)" | |
| } | |
| s_exec() { | |
| if [[ $EUID -ne 0 ]]; then eval "sudo $@"; else eval "$@"; fi | |
| } | |
| s_hidedaemon() { | |
| for hidedaemon in ${HIDEDAEMONS[@]}; do if [[ "$1" == "$hidedaemon" ]]; then return 0; fi; done; return 1; | |
| } | |
| # $1: optional type | |
| s_bashcompletion_list_by_type () { | |
| ${_systemctl} --no-legend -t $1 list-unit-files \ | |
| | { while read -r a b ; do printf "%s\n" "${a}"; done; } | |
| } | |
| s_bashcompletion () { | |
| local cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]} | |
| local verb comps | |
| if [[ "${1}" == "target" ]]; then comps=$( s_bashcompletion_list_by_type "target" ); | |
| else comps=$( s_list_services "${1}" ); fi | |
| COMPREPLY=( $(compgen -W '$comps' -- "$cur") ) | |
| } | |
| _COLORS=${BS_COLORS:-$(tput colors 2>/dev/null || echo 0)} | |
| __detect_color_support() { | |
| if [ $? -eq 0 ] && [ "$_COLORS" -gt 2 ]; then | |
| RC="\033[1;31m" | |
| GC="\033[1;32m" | |
| BC="\033[1;34m" | |
| YC="\033[1;33m" | |
| EC="\033[0m" | |
| else | |
| RC=""; GC=""; BC=""; YC=""; EC="" | |
| fi | |
| } | |
| __detect_color_support | |
| _print(){ | |
| _msg_type=$1 | |
| } | |
| echoinfo() { printf "${GC} :: INFO${EC}: %s\n" "$@"; } | |
| echowarn() { printf "${YC} >> WARN${EC}: %s\n" "$@"; } | |
| echoerror(){ printf "${RC} !! ERROR${EC}: %s\n" "$@" 1>&2; } | |
| echodebug() { [ "$_ECHO_DEBUG" -eq 0 ] && printf "${BC} * DEBUG${EC}: %s\n" "$@"; } | |
| __check_command_exists() { command -v "$1" > /dev/null 2>&1; } | |
| s_bashcompletion_start () { s_bashcompletion "stopped"; return 0; } | |
| s_bashcompletion_stop () { s_bashcompletion "started"; return 0; } | |
| s_bashcompletion_restart () { s_bashcompletion "started"; return 0; } | |
| s_bashcompletion_reload () { s_bashcompletion "started"; return 0; } | |
| s_bashcompletion_enable () { s_bashcompletion "disabled"; return 0; } | |
| s_bashcompletion_disable () { s_bashcompletion "enabled"; return 0; } | |
| s_bashcompletion_status () { s_bashcompletion ""; return 0; } | |
| s_bashcompletion_wants () { s_bashcompletion "target"; return 0; } | |
| s_bashcompletion_log () { s_bashcompletion ""; return 0; } | |
| s_bashcompletion_tail () { s_bashcompletion ""; return 0; } | |
| s_bashcompletion_filterList () { s_bashcompletion ""; return 0; } | |
| complete -F s_bashcompletion_start sdStart | |
| complete -F s_bashcompletion_stop sdStop | |
| complete -F s_bashcompletion_restart sdRestart | |
| complete -F s_bashcompletion_reload sdReload | |
| complete -F s_bashcompletion_enable sdEnable | |
| complete -F s_bashcompletion_disable sdDisable | |
| complete -F s_bashcompletion_status sdStat | |
| complete -F s_bashcompletion_wants sdWants | |
| complete -F s_bashcompletion_log sdLog | |
| complete -F s_bashcompletion_tail sdTail | |
| complete -F s_bashcompletion_filterList sdFilterList | |
| #if [ "$BASH_VERSION" ] && [ -n "$PS1" ] && echo $SHELLOPTS | grep -v posix >>/dev/null; then | |
| # if [ -f /etc/profile.d/systemd-shell-wrapper.bash ]; then | |
| # source /etc/profile.d/systemd-shell-wrapper.bash | |
| # fi | |
| #elif [ "$ZSH_VERSION" ] && [ -n "$PS1" ]; then | |
| # if [ -f /etc/profile.d/ ]; then | |
| # source /etc/profile.d/ | |
| # fi | |
| #fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment