]> ruderich.org/simon Gitweb - config/dotfiles.git/commitdiff
add wrapper for systemctl with shorter commands
authorSimon Ruderich <simon@ruderich.org>
Fri, 25 Sep 2015 14:31:51 +0000 (16:31 +0200)
committerSimon Ruderich <simon@ruderich.org>
Fri, 25 Sep 2015 14:31:51 +0000 (16:31 +0200)
bin/sc [new file with mode: 0755]
shell/aliases.in
zsh/functions/_systemctl [new file with mode: 0644]
zsh/rc

diff --git a/bin/sc b/bin/sc
new file mode 100755 (executable)
index 0000000..506e90a
--- /dev/null
+++ b/bin/sc
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Small wrapper for systemctl which provides some shortcuts.
+
+# Copyright (C) 2015  Simon Ruderich
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+set -eu
+
+
+args=( )
+found=
+for arg; do
+    # This heuristic replaces the first occurrence of a shortcut with its
+    # expansion. This is not perfect (e.g. `systemctl status s` would result
+    # in `systemctl status status`) but works even when options are used and
+    # doesn't require us to duplicate systemctl's parsing of command line
+    # arguments.
+    if [[ -z $found ]]; then
+        found=1
+        case "$arg" in
+            c)  arg=cat     ;;
+            d)  arg=disable ;;
+            e)  arg=enable  ;;
+            k)  arg=kill    ;;
+            m)  arg=mask    ;;
+            r)  arg=restart ;;
+            rl) arg=reload  ;;
+            s)  arg=status  ;;
+            sa) arg=start   ;;
+            so) arg=stop    ;;
+            u)  arg=unmask  ;;
+            # No match, try it again for the next parameter.
+            *)  found=      ;;
+        esac
+    fi
+    args+=( "$arg" )
+done
+
+set +u # empty $args causes an error, I think this is a bug in bash
+exec systemctl "${args[@]}"
index ef3b19fa21a73bdd3be7e742299b858a6ec01bff..06d7277bc0e4627c7197747e5da1c8507cb2beed 100644 (file)
@@ -40,10 +40,9 @@ alias mj='make -j'
 alias mu=mutt
 alias sa='ssh-add -t 1h'
 alias te=tree
-# systemd ...
+# systemd ... (sc is provided as shell script for better completoin)
 alias jc=journalctl
 alias lc=loginctl
-alias sc=systemctl
 
 
 unalias mv cp 2>/dev/null
diff --git a/zsh/functions/_systemctl b/zsh/functions/_systemctl
new file mode 100644 (file)
index 0000000..c440dd7
--- /dev/null
@@ -0,0 +1,418 @@
+#compdef systemctl
+
+(( $+functions[_systemctl_command] )) || _systemctl_command()
+{
+  local -a _systemctl_cmds
+  _systemctl_cmds=(
+    "list-sockets:List sockets"
+    "list-timers:List timers"
+    "list-units:List units"
+    "start:Start (activate) one or more units"
+    "stop:Stop (deactivate) one or more units"
+    "reload:Reload one or more units"
+    "restart:Start or restart one or more units"
+    "condrestart:Restart one or more units if active"
+    "try-restart:Restart one or more units if active"
+    "reload-or-restart:Reload one or more units if possible, otherwise start or restart"
+    "force-reload:Reload one or more units if possible, otherwise restart if active"
+    "hibernate:Hibernate the system"
+    "hybrid-sleep:Hibernate and suspend the system"
+    "reload-or-try-restart:Reload one or more units if possible, otherwise restart if active"
+    "isolate:Start one unit and stop all others"
+    "kill:Send signal to processes of a unit"
+    "is-active:Check whether units are active"
+    "is-failed:Check whether units are failed"
+    "status:Show runtime status of one or more units"
+    "show:Show properties of one or more units/jobs or the manager"
+    "cat:Show the source unit files and drop-ins"
+    "reset-failed:Reset failed state for all, one, or more units"
+    "list-unit-files:List installed unit files"
+    "enable:Enable one or more unit files"
+    "disable:Disable one or more unit files"
+    "reenable:Reenable one or more unit files"
+    "preset:Enable/disable one or more unit files based on preset configuration"
+    "set-default:Set the default target"
+    "get-default:Query the default target"
+    "edit:Edit one or more unit files"
+    "is-system-running:Query overall status of the system"
+    "help:Show documentation for specified units"
+    "list-dependencies:Show unit dependency tree"
+    "mask:Mask one or more units"
+    "unmask:Unmask one or more units"
+    "link:Link one or more units files into the search path"
+    "is-enabled:Check whether unit files are enabled"
+    "list-jobs:List jobs"
+    "cancel:Cancel all, one, or more jobs"
+    "snapshot:Create a snapshot"
+    "delete:Remove one or more snapshots"
+    "show-environment:Dump environment"
+    "set-environment:Set one or more environment variables"
+    "unset-environment:Unset one or more environment variables"
+    "daemon-reload:Reload systemd manager configuration"
+    "daemon-reexec:Reexecute systemd manager"
+    "default:Enter system default mode"
+    "rescue:Enter system rescue mode"
+    "emergency:Enter system emergency mode"
+    "halt:Shut down and halt the system"
+    "suspend:Suspend the system"
+    "poweroff:Shut down and power-off the system"
+    "reboot:Shut down and reboot the system"
+    "kexec:Shut down and reboot the system with kexec"
+    "exit:Ask for user instance termination"
+    "switch-root:Change root directory"
+  )
+
+  if (( CURRENT == 1 )); then
+    _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
+  else
+    local curcontext="$curcontext" expl
+
+    cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
+    # Deal with any aliases
+    case $cmd in
+      condrestart) cmd="try-restart";;
+      force-reload) cmd="reload-or-try-restart";;
+    esac
+
+    # CHANGED: my aliases
+    case $words[1] in
+      c)  cmd=cat     ;;
+      d)  cmd=disable ;;
+      e)  cmd=enable  ;;
+      k)  cmd=kill    ;;
+      m)  cmd=mask    ;;
+      r)  cmd=restart ;;
+      rl) cmd=reload  ;;
+      s)  cmd=status  ;;
+      sa) cmd=start   ;;
+      so) cmd=stop    ;;
+      u)  cmd=unmask  ;;
+    esac
+
+    if (( $#cmd )); then
+      curcontext="${curcontext%:*:*}:systemctl-${cmd}:"
+
+      local update_policy
+      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+      if [[ -z "$update_policy" ]]; then
+        zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy
+      fi
+
+      _call_function ret _systemctl_$cmd || _message 'no more arguments'
+    else
+      _message "unknown systemctl command: $words[1]"
+    fi
+    return ret
+  fi
+}
+
+__systemctl()
+{
+  systemctl $_sys_service_mgr --full --no-legend --no-pager "$@"
+}
+
+
+# Fills the unit list
+_systemctl_all_units()
+{
+  if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) &&
+    ! _retrieve_cache SYS_ALL_UNITS;
+  then
+    _sys_all_units=( ${${(f)"$(__systemctl list-units --all)"}%% *} )
+    _store_cache SYS_ALL_UNITS _sys_all_units
+  fi
+}
+
+# Fills the unit list including all file units
+_systemctl_really_all_units()
+{
+  local -a all_unit_files;
+  local -a really_all_units;
+  if ( [[ ${+_sys_really_all_units} -eq 0 ]] || _cache_invalid SYS_REALLY_ALL_UNITS ) &&
+    ! _retrieve_cache SYS_REALLY_ALL_UNITS;
+  then
+    all_unit_files=( ${${(f)"$(__systemctl list-unit-files)"}%% *} )
+    _systemctl_all_units
+    really_all_units=($_sys_all_units $all_unit_files)
+    _sys_really_all_units=(${(u)really_all_units})
+    _store_cache SYS_REALLY_ALL_UNITS _sys_really_all_units
+  fi
+}
+
+_filter_units_by_property() {
+  local property=$1 value=$2 ; shift ; shift
+  local -a units ; units=($*)
+  local props
+  for props in ${(ps:\n\n:)"$(_call_program units "$service show --no-pager --property="Id,$property" -- ${units} 2>/dev/null")"}; do
+    props=(${(f)props})
+    if [[ "${props[2]}" = "$property=$value" ]]; then
+      echo -E - " ${props[1]#Id=}"
+    fi
+  done
+}
+
+_systemctl_get_template_names() { echo -E - ${^${(M)${(f)"$(__systemctl list-unit-files)"}##*@.[^[:space:]]##}%%@.*}\@ }
+
+
+_systemctl_active_units()  {_sys_active_units=(  ${${(f)"$(__systemctl list-units)"}%% *} )}
+
+_systemctl_startable_units(){
+    _sys_startable_units=( $( _filter_units_by_property ActiveState inactive $(
+                          _filter_units_by_property CanStart yes $(
+                          __systemctl $mode list-unit-files --state enabled,disabled,static | \
+                               { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; }
+                          __systemctl $mode list-units --state inactive,failed | \
+                               { while read -r a b; do echo -E - " $a"; done; } )) ) )
+}
+
+_systemctl_restartable_units(){
+    _sys_restartable_units=( $(_filter_units_by_property CanStart yes $(
+                          __systemctl $mode list-unit-files --state enabled,disabled,static | \
+                               { while read -r a b; do [[ $a =~ @\. ]] || echo -E - " $a"; done; }
+                          __systemctl $mode list-units | \
+                               { while read -r a b; do echo -E - " $a"; done; } )) )
+}
+
+_systemctl_failed_units()  {_sys_failed_units=( ${${(f)"$(__systemctl list-units --failed)"}%% *} ) }
+_systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files) ) }
+
+local fun
+# Completion functions for ALL_UNITS
+for fun in is-active is-failed is-enabled status show cat mask preset help list-dependencies edit ; do
+  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+  {
+    _systemctl_really_all_units
+    _wanted systemd-units expl unit \
+      compadd "$@" -a - _sys_really_all_units
+  }
+done
+
+# Completion functions for ENABLED_UNITS
+(( $+functions[_systemctl_disable] )) || _systemctl_disable()
+{
+    local _sys_unit_state; _systemctl_unit_state
+    _wanted systemd-units expl 'enabled unit' \
+      compadd "$@" - ${(k)_sys_unit_state[(R)enabled]}
+}
+
+(( $+functions[_systemctl_reenable] )) || _systemctl_reenable()
+{
+    local _sys_unit_state; _systemctl_unit_state
+    _wanted systemd-units expl 'enabled/disabled unit' \
+      compadd "$@" - ${(k)_sys_unit_state[(R)(enabled|disabled)]} $(_systemctl_get_template_names)
+}
+
+# Completion functions for DISABLED_UNITS
+(( $+functions[_systemctl_enable] )) || _systemctl_enable()
+{
+  local _sys_unit_state; _systemctl_unit_state
+  _wanted systemd-units expl 'disabled unit' \
+    compadd "$@" - ${(k)_sys_unit_state[(R)disabled]} $(_systemctl_get_template_names)
+}
+
+# Completion functions for FAILED_UNITS
+(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed()
+{
+  local _sys_failed_units; _systemctl_failed_units
+  _wanted systemd-units expl 'failed unit' \
+    compadd "$@" -a - _sys_failed_units || _message "no failed unit found"
+}
+
+# Completion functions for STARTABLE_UNITS
+(( $+functions[_systemctl_start] )) || _systemctl_start()
+{
+   local _sys_startable_units; _systemctl_startable_units
+   _wanted systemd-units expl 'startable unit' \
+     compadd "$@" - ${_sys_startable_units[*]} $(_systemctl_get_template_names)
+}
+
+# Completion functions for STOPPABLE_UNITS
+for fun in stop kill try-restart condrestart ; do
+  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+  {
+    local _sys_active_units; _systemctl_active_units
+    _wanted systemd-units expl 'stoppable unit' \
+      compadd "$@" - $( _filter_units_by_property CanStop yes \
+        ${_sys_active_units[*]} )
+  }
+done
+
+# Completion functions for ISOLATABLE_UNITS
+(( $+functions[_systemctl_isolate] )) || _systemctl_isolate()
+{
+  _systemctl_all_units
+  _wanted systemd-units expl 'isolatable unit' \
+    compadd "$@" - $( _filter_units_by_property AllowIsolate yes \
+      ${_sys_all_units[*]} )
+}
+
+# Completion functions for RELOADABLE_UNITS
+for fun in reload reload-or-try-restart force-reload ; do
+  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+  {
+    local _sys_active_units; _systemctl_active_units
+    _wanted systemd-units expl 'reloadable unit' \
+      compadd "$@" - $( _filter_units_by_property CanReload yes \
+        ${_sys_active_units[*]} )
+  }
+done
+
+# Completion functions for RESTARTABLE_UNITS
+for fun in restart reload-or-restart ; do
+  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+  {
+    local _sys_restartable_units; _systemctl_restartable_units
+    _wanted systemd-units expl 'restartable unit' \
+      compadd "$@" - ${_sys_restartable_units[*]} $(_systemctl_get_template_names)
+  }
+done
+
+# Completion functions for MASKED_UNITS
+(( $+functions[_systemctl_unmask] )) || _systemctl_unmask()
+{
+  local _sys_unit_state; _systemctl_unit_state
+  _wanted systemd-units expl 'masked unit' \
+    compadd "$@" - ${(k)_sys_unit_state[(R)masked]} || _message "no masked units found"
+}
+
+# Completion functions for JOBS
+(( $+functions[_systemctl_cancel] )) || _systemctl_cancel()
+{
+  _wanted systemd-jobs expl job \
+    compadd "$@" - ${${(f)"$(__systemctl list-jobs)"}%% *} ||
+      _message "no jobs found"
+}
+
+# Completion functions for SNAPSHOTS
+(( $+functions[_systemctl_delete] )) || _systemctl_delete()
+{
+  _wanted systemd-snapshots expl snapshot \
+    compadd "$@" - ${${(f)"$(__systemctl list-units --type snapshot --all)"}%% *} ||
+      _message "no snapshots found"
+}
+
+# Completion functions for TARGETS
+(( $+functions[_systemctl_set-default] )) || _systemctl_set-default()
+{
+  _wanted systemd-targets expl target \
+    compadd "$@" - ${${(f)"$(__systemctl list-unit-files --type target --all)"}%% *} ||
+      _message "no targets found"
+}
+
+# Completion functions for ENVS
+for fun in set-environment unset-environment ; do
+  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
+  {
+    local fun=$0 ; fun=${fun##_systemctl_}
+    local suf
+    if [[ "${fun}" = "set-environment" ]]; then
+      suf='-S='
+    fi
+    _wanted systemd-environment expl 'environment variable' \
+      compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*}
+  }
+done
+
+(( $+functions[_systemctl_link] )) || _systemctl_link() {
+   _sd_unit_files
+}
+
+(( $+functions[_systemctl_switch-root] )) || _systemctl_switch-root() {
+   _files
+}
+
+# no systemctl completion for:
+#    [STANDALONE]='daemon-reexec daemon-reload default
+#                  emergency exit halt kexec list-jobs list-units
+#                  list-unit-files poweroff reboot rescue show-environment'
+#         [NAME]='snapshot'
+
+_systemctl_caching_policy()
+{
+  local _sysunits
+  local -a oldcache
+
+  # rebuild if cache is more than a day old
+  oldcache=( "$1"(mh+1) )
+  (( $#oldcache )) && return 0
+
+  _sysunits=(${${(f)"$(__systemctl --all)"}%% *})
+
+  if (( $#_sysunits )); then
+    for unit in $_sysunits; do
+      [[ "$unit" -nt "$1" ]] && return 0
+    done
+  fi
+
+  return 1
+}
+
+_unit_states() {
+    local -a _states
+    _states=(loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked)
+    _values -s , "${_states[@]}"
+}
+
+_unit_types() {
+    local -a _types
+    _types=(automount busname device mount path service snapshot socket swap target timer)
+    _values -s , "${_types[@]}"
+}
+
+_unit_properties() {
+  if ( [[ ${+_sys_all_properties} -eq 0 ]] || _cache_invalid SYS_ALL_PROPERTIES ) &&
+    ! _retrieve_cache SYS_ALL_PROPERTIES;
+  then
+    _sys_all_properties=( ${${(M)${(f)"$(__systemctl show --all;
+    /lib/systemd/systemd --dump-configuration-items)"}##[[:alnum:]]##=*}%%=*}
+    )
+    _store_cache SYS_ALL_PROPRTIES _sys_all_properties
+  fi
+  _values -s , "${_sys_all_properties[@]}"
+}
+
+_job_modes() {
+    local -a _modes
+    _modes=(fail replace replace-irreversibly isolate ignore-dependencies ignore-requirements flush)
+    _values -s , "${_modes[@]}"
+}
+
+local -a _modes; _modes=("--user" "--system")
+local _sys_service_mgr=${${words:*_modes}[(R)(${(j.|.)_modes})]:---system}
+_arguments -s \
+    {-h,--help}'[Show help]' \
+    '--version[Show package version]' \
+    {-t+,--type=}'[List only units of a particular type]:unit type:_unit_types' \
+    '--state=[Display units in the specified state]:unit state:_unit_states' \
+    '--job-mode=[Specify how to deal with other jobs]:mode:_job_modes' \
+    {-p+,--property=}'[Show only properties by specific name]:unit property:_unit_properties' \
+    {-a,--all}'[Show all units/properties, including dead/empty ones]' \
+    '--reverse[Show reverse dependencies]' \
+    '--after[Show units ordered after]' \
+    '--before[Show units ordered before]' \
+    '--failed[Show only failed units]' \
+    {-l,--full}"[Don't ellipsize unit names on output]" \
+    '--show-types[When showing sockets, show socket type]' \
+    {-i,--ignore-inhibitors}'[When executing a job, ignore jobs dependencies]' \
+    {-q,--quiet}'[Suppress output]' \
+    '--no-block[Do not wait until operation finished]' \
+    '--no-legend[Do not print a legend, i.e. the column headers and the footer with hints]' \
+    '--no-pager[Do not pipe output into a pager]' \
+    '--system[Connect to system manager]' \
+    '--user[Connect to user service manager]' \
+    "--no-wall[Don't send wall message before halt/power-off/reboot]" \
+    '--global[Enable/disable unit files globally]' \
+    "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
+    '--no-ask-password[Do not ask for system passwords]' \
+    '--kill-who=[Who to send signal to]:killwho:(main control all)' \
+    {-s+,--signal=}'[Which signal to send]:signal:_signals' \
+    {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
+    '--root=[Enable unit files in the specified root directory]:directory:_directories' \
+    '--runtime[Enable unit files only temporarily until next reboot]' \
+    {-H+,--host=}'[Operate on remote host]:userathost:_sd_hosts_or_user_at_host' \
+    {-P,--privileged}'[Acquire privileges before execution]' \
+    {-n+,--lines=}'[Journal entries to show]:number of entries' \
+    {-o+,--output=}'[Change journal output mode]:modes:_sd_outputmodes' \
+    '--firmware-setup[Tell the firmware to show the setup menu on next boot]' \
+    '--plain[When used with list-dependencies, print output as a list]' \
+    '*::systemctl command:_systemctl_command'
diff --git a/zsh/rc b/zsh/rc
index 6bc2d3b9e3d65e564ab45cd657f7d56cc31c999e..ff59f86b59d30010062d43b6b720c847bda4c621 100644 (file)
--- a/zsh/rc
+++ b/zsh/rc
@@ -790,6 +790,7 @@ compdef slocate=locate
 compdef srsync=rsync
 compdef srsync-incremental=rsync
 compdef svalgrind=valgrind
+compdef sc=systemctl
 
 
 # CUSTOM ALIASES AND FUNCTIONS