From 738d9596a437e79105fd05bb92a689b1dcb9166e Mon Sep 17 00:00:00 2001 From: James Deathe Date: Mon, 10 Jun 2019 17:06:27 +0100 Subject: [PATCH 01/17] #695: Adds feature to self-destruct a container after a (1 hour default) timeout. --- .env.example | 4 +- CHANGELOG.md | 3 + Dockerfile | 6 +- default.mk | 2 + docker-compose.yml | 2 + environment.mk | 2 + src/etc/supervisord.d/01-reaper.conf | 10 ++ src/etc/systemd/system/centos-ssh@.service | 4 + src/opt/scmi/default.sh | 2 + src/opt/scmi/environment.sh | 2 + src/opt/scmi/service-unit.sh | 2 + src/usr/sbin/reaper | 119 +++++++++++++++++++++ 12 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 src/etc/supervisord.d/01-reaper.conf create mode 100755 src/usr/sbin/reaper diff --git a/.env.example b/.env.example index 590a183..f7562b6 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,11 @@ SSH_AUTHORIZED_KEYS= +SSH_AUTOSTART_REAPER=false SSH_AUTOSTART_SSHD=true SSH_AUTOSTART_SSHD_BOOTSTRAP=true SSH_CHROOT_DIRECTORY=%h SSH_INHERIT_ENVIRONMENT=false SSH_PASSWORD_AUTHENTICATION=false +SSH_REAPER_TIMEOUT=3600 SSH_SUDO=ALL=(ALL) ALL SSH_TIMEZONE=UTC SSH_USER=app-admin @@ -13,4 +15,4 @@ SSH_USER_ID=500:500 SSH_USER_PASSWORD= SSH_USER_PASSWORD_HASHED=false SSH_USER_PRIVATE_KEY= -SSH_USER_SHELL=/bin/bash \ No newline at end of file +SSH_USER_SHELL=/bin/bash diff --git a/CHANGELOG.md b/CHANGELOG.md index bd30aba..1131446 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ Summary of release changes for Version 2 - CentOS-7 - Adds `inspect`, `reload` and `top` Makefile targets. - Adds improved lock/state file implementation in bootstrap and wrapper scripts. - Adds improved `clean` Makefile target; includes exited containers and dangling images. +- Adds feature to optionally exit the container after a specified timout period. +- Adds `SSH_AUTOSTART_REAPER` to control startup of `reaper`. +- Adds `SSH_REAPER_TIMEOUT` with a default value of 3600 seconds (i.e 1 hour). - Fixes port incrementation failures when installing systemd units via `scmi`. - Fixes etcd port registration failures when installing systemd units via `scmi` with the `--register` option. - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. diff --git a/Dockerfile b/Dockerfile index bb69eef..64c71d6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,7 @@ RUN rpm --rebuilddb \ openssl-1.0.2k-16.el7 \ python-setuptools-0.9.8-7.el7 \ sudo-1.8.23-3.el7 \ + sysvinit-tools-2.88-14.dsf.el7 \ yum-plugin-versionlock-1.1.31-50.el7 \ && yum versionlock add \ openssh \ @@ -35,6 +36,7 @@ RUN rpm --rebuilddb \ openssh-clients \ python-setuptools \ sudo \ + sysvinit-tools \ yum-plugin-versionlock \ && yum clean all \ && easy_install \ @@ -83,7 +85,7 @@ RUN ln -sf \ && chmod 644 \ /etc/{supervisord.conf,supervisord.d/sshd-{bootstrap,wrapper}.conf} \ && chmod 700 \ - /usr/{bin/healthcheck,sbin/{scmi,sshd-{bootstrap,wrapper}}} + /usr/{bin/healthcheck,sbin/{reaper,scmi,sshd-{bootstrap,wrapper}}} EXPOSE 22 @@ -92,12 +94,14 @@ EXPOSE 22 # ------------------------------------------------------------------------------ ENV \ SSH_AUTHORIZED_KEYS="" \ + SSH_AUTOSTART_REAPER="false" \ SSH_AUTOSTART_SSHD="true" \ SSH_AUTOSTART_SSHD_BOOTSTRAP="true" \ SSH_AUTOSTART_SUPERVISOR_STDOUT="false" \ SSH_CHROOT_DIRECTORY="%h" \ SSH_INHERIT_ENVIRONMENT="false" \ SSH_PASSWORD_AUTHENTICATION="false" \ + SSH_REAPER_TIMEOUT="3600" \ SSH_SUDO="ALL=(ALL) ALL" \ SSH_TIMEZONE="UTC" \ SSH_USER="app-admin" \ diff --git a/default.mk b/default.mk index 380e2c7..499eae3 100644 --- a/default.mk +++ b/default.mk @@ -42,12 +42,14 @@ define DOCKER_CONTAINER_PARAMETERS --name $(DOCKER_NAME) \ --restart $(DOCKER_RESTART_POLICY) \ --env "SSH_AUTHORIZED_KEYS=$(SSH_AUTHORIZED_KEYS)" \ +--env "SSH_AUTOSTART_REAPER=$(SSH_AUTOSTART_REAPER)" \ --env "SSH_AUTOSTART_SSHD=$(SSH_AUTOSTART_SSHD)" \ --env "SSH_AUTOSTART_SSHD_BOOTSTRAP=$(SSH_AUTOSTART_SSHD_BOOTSTRAP)" \ --env "SSH_AUTOSTART_SUPERVISOR_STDOUT=$(SSH_AUTOSTART_SUPERVISOR_STDOUT)" \ --env "SSH_CHROOT_DIRECTORY=$(SSH_CHROOT_DIRECTORY)" \ --env "SSH_INHERIT_ENVIRONMENT=$(SSH_INHERIT_ENVIRONMENT)" \ --env "SSH_PASSWORD_AUTHENTICATION=$(SSH_PASSWORD_AUTHENTICATION)" \ +--env "SSH_REAPER_TIMEOUT=$(SSH_REAPER_TIMEOUT)" \ --env "SSH_SUDO=$(SSH_SUDO)" \ --env "SSH_TIMEZONE=$(SSH_TIMEZONE)" \ --env "SSH_USER=$(SSH_USER)" \ diff --git a/docker-compose.yml b/docker-compose.yml index a95abaa..0bafcae 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,11 +29,13 @@ services: dockerfile: "Dockerfile" environment: SSH_AUTHORIZED_KEYS: "${SSH_AUTHORIZED_KEYS}" + SSH_AUTOSTART_REAPER: "${SSH_AUTOSTART_REAPER}" SSH_AUTOSTART_SSHD: "${SSH_AUTOSTART_SSHD}" SSH_AUTOSTART_SSHD_BOOTSTRAP: "${SSH_AUTOSTART_SSHD_BOOTSTRAP}" SSH_CHROOT_DIRECTORY: "${SSH_CHROOT_DIRECTORY}" SSH_INHERIT_ENVIRONMENT: "${SSH_INHERIT_ENVIRONMENT}" SSH_PASSWORD_AUTHENTICATION: "${SSH_PASSWORD_AUTHENTICATION}" + SSH_REAPER_TIMEOUT: "${SSH_REAPER_TIMEOUT}" SSH_SUDO: "${SSH_SUDO}" SSH_TIMEZONE: "${SSH_TIMEZONE}" SSH_USER: "${SSH_USER}" diff --git a/environment.mk b/environment.mk index c62c8a8..cca4905 100644 --- a/environment.mk +++ b/environment.mk @@ -24,12 +24,14 @@ STARTUP_TIME ?= 2 # Application container configuration # ------------------------------------------------------------------------------ SSH_AUTHORIZED_KEYS ?= +SSH_AUTOSTART_REAPER ?= false SSH_AUTOSTART_SSHD ?= true SSH_AUTOSTART_SSHD_BOOTSTRAP ?= true SSH_AUTOSTART_SUPERVISOR_STDOUT ?= false SSH_CHROOT_DIRECTORY ?= %h SSH_INHERIT_ENVIRONMENT ?= false SSH_PASSWORD_AUTHENTICATION ?= false +SSH_REAPER_TIMEOUT ?= 3600 SSH_SUDO ?= ALL=(ALL) ALL SSH_TIMEZONE ?= UTC SSH_USER ?= app-admin diff --git a/src/etc/supervisord.d/01-reaper.conf b/src/etc/supervisord.d/01-reaper.conf new file mode 100644 index 0000000..7e15cd7 --- /dev/null +++ b/src/etc/supervisord.d/01-reaper.conf @@ -0,0 +1,10 @@ +[program:reaper] +autorestart = false +autostart = %(ENV_SSH_AUTOSTART_REAPER)s +command = /usr/sbin/reaper --verbose +priority = 1 +startsecs = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index c6f54c1..57250cd 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -57,12 +57,14 @@ Environment="DOCKER_IMAGE_TAG={{RELEASE_VERSION}}" Environment="DOCKER_PORT_MAP_TCP_22=2020" Environment="DOCKER_USER=jdeathe" Environment="SSH_AUTHORIZED_KEYS=" +Environment="SSH_AUTOSTART_REAPER=false" Environment="SSH_AUTOSTART_SSHD=true" Environment="SSH_AUTOSTART_SSHD_BOOTSTRAP=true" Environment="SSH_AUTOSTART_SUPERVISOR_STDOUT=false" Environment="SSH_CHROOT_DIRECTORY=%%h" Environment="SSH_INHERIT_ENVIRONMENT=false" Environment="SSH_PASSWORD_AUTHENTICATION=false" +Environment="SSH_REAPER_TIMEOUT=3600" Environment="SSH_SUDO=ALL=(ALL) ALL" Environment="SSH_TIMEZONE=UTC" Environment="SSH_USER=app-admin" @@ -130,12 +132,14 @@ ExecStart=/bin/bash -c \ "exec /usr/bin/docker run \ --name %p.%i \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ + --env \"SSH_AUTOSTART_REAPER=${SSH_AUTOSTART_REAPER}\" \ --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ --env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ --env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ + --env \"SSH_REAPER_TIMEOUT=${SSH_REAPER_TIMEOUT}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ --env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ diff --git a/src/opt/scmi/default.sh b/src/opt/scmi/default.sh index 652b1ce..df2dc93 100644 --- a/src/opt/scmi/default.sh +++ b/src/opt/scmi/default.sh @@ -47,12 +47,14 @@ fi DOCKER_CONTAINER_PARAMETERS="--name ${DOCKER_NAME} \ --restart ${DOCKER_RESTART_POLICY} \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ +--env \"SSH_AUTOSTART_REAPER=${SSH_AUTOSTART_REAPER}\" \ --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ --env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ --env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ +--env \"SSH_REAPER_TIMEOUT=${SSH_REAPER_TIMEOUT}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ --env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index cebeca3..d8e7a9d 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -25,12 +25,14 @@ STARTUP_TIME="${STARTUP_TIME:-2}" # Application container configuration # ------------------------------------------------------------------------------ SSH_AUTHORIZED_KEYS="${SSH_AUTHORIZED_KEYS:-}" +SSH_AUTOSTART_REAPER="${SSH_AUTOSTART_REAPER:-false}" SSH_AUTOSTART_SSHD="${SSH_AUTOSTART_SSHD:-true}" SSH_AUTOSTART_SSHD_BOOTSTRAP="${SSH_AUTOSTART_SSHD_BOOTSTRAP:-true}" SSH_AUTOSTART_SUPERVISOR_STDOUT="${SSH_AUTOSTART_SUPERVISOR_STDOUT:-false}" SSH_CHROOT_DIRECTORY="${SSH_CHROOT_DIRECTORY:-%h}" SSH_INHERIT_ENVIRONMENT="${SSH_INHERIT_ENVIRONMENT:-false}" SSH_PASSWORD_AUTHENTICATION="${SSH_PASSWORD_AUTHENTICATION:-false}" +SSH_REAPER_TIMEOUT="${SSH_REAPER_TIMEOUT:-3600}" SSH_SUDO="${SSH_SUDO:-ALL=(ALL) ALL}" SSH_TIMEZONE="${SSH_TIMEZONE:-UTC}" SSH_USER="${SSH_USER:-app-admin}" diff --git a/src/opt/scmi/service-unit.sh b/src/opt/scmi/service-unit.sh index 6e04daf..9403adb 100644 --- a/src/opt/scmi/service-unit.sh +++ b/src/opt/scmi/service-unit.sh @@ -7,12 +7,14 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" DOCKER_IMAGE_TAG DOCKER_PORT_MAP_TCP_22 SSH_AUTHORIZED_KEYS + SSH_AUTOSTART_REAPER SSH_AUTOSTART_SSHD SSH_AUTOSTART_SSHD_BOOTSTRAP SSH_AUTOSTART_SUPERVISOR_STDOUT SSH_CHROOT_DIRECTORY SSH_INHERIT_ENVIRONMENT SSH_PASSWORD_AUTHENTICATION + SSH_REAPER_TIMEOUT SSH_SUDO SSH_TIMEZONE SSH_USER diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper new file mode 100755 index 0000000..e90a63a --- /dev/null +++ b/src/usr/sbin/reaper @@ -0,0 +1,119 @@ +#!/usr/bin/env bash + +set -e + +function __get_ssh_reaper_timeout () +{ + local -r default_value="${1:-3600}" + + local value="${SSH_REAPER_TIMEOUT}" + + if ! __is_valid_ssh_reaper_timeout "${value}" + then + value="${default_value}" + fi + + printf -- '%s' "${value}" +} + +function __is_valid_positive_integer () +{ + local -r positive_integer='^[0-9]+$' + local -r value="${1}" + + if [[ ${value} =~ ${positive_integer} ]] + then + return 0 + fi + + return 1 +} + +function __is_valid_ssh_reaper_timeout () +{ + __is_valid_positive_integer "${@}" +} + +function __reap () +{ + kill -"${signal:-TERM}" "${pid:-1}" +} + +function main () +{ + local -r warning_timeout="30" + + local pid="1" + local signal="TERM" + local timeout="$( + __get_ssh_reaper_timeout + )" + local verbose="false" + + while [[ "${#}" -gt 0 ]] + do + case "${1}" in + -p) + pid="${2}" + shift 2 || break + ;; + --pid) + pid="${1#*=}" + shift 1 + ;; + -s) + signal="${2}" + shift 2 || break + ;; + --signal) + signal="${1#*=}" + shift 1 + ;; + -v|--verbose) + verbose="true" + shift 1 + ;; + esac + done + + if (( timeout > 0 )) + then + trap __reap \ + EXIT INT TERM + + if (( timeout > warning_timeout )) + then + (( timeout -= warning_timeout )) + else + warning_timeout="0" + fi + + if coproc read -t "${timeout}" + then + wait "${!}" || : + + if (( warning_timeout > 0 )) + then + wall "Session expired - exiting in ${warning_timeout} seconds." + + if coproc read -t "${warning_timeout}" + then + wait "${!}" || : + fi + else + wall "Session expired." + fi + fi + + if [[ ${verbose} == true ]] + then + printf -- \ + 'INFO: %s expiring session.\n' \ + "${0##*/}" + fi + fi + + exit 0 +} + +main "${@}" From 0bd1b43b4267ae62884855142f3f2b31c9901d0c Mon Sep 17 00:00:00 2001 From: James Deathe Date: Wed, 12 Jun 2019 21:27:06 +0100 Subject: [PATCH 02/17] #695: Separate out the reaper env variable names from sshd. --- .env.example | 4 +- CHANGELOG.md | 4 +- Dockerfile | 4 +- default.mk | 2 +- docker-compose.yml | 4 +- environment.mk | 4 +- src/etc/supervisord.d/01-reaper.conf | 2 +- src/etc/systemd/system/centos-ssh@.service | 6 +-- src/opt/scmi/default.sh | 4 +- src/opt/scmi/environment.sh | 4 +- src/opt/scmi/service-unit.sh | 3 +- src/usr/sbin/reaper | 51 +++++++++++++++------- 12 files changed, 57 insertions(+), 35 deletions(-) diff --git a/.env.example b/.env.example index f7562b6..e3089e7 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,11 @@ +ENABLE_REAPER=false +REAPER_TIMEOUT=3600 SSH_AUTHORIZED_KEYS= -SSH_AUTOSTART_REAPER=false SSH_AUTOSTART_SSHD=true SSH_AUTOSTART_SSHD_BOOTSTRAP=true SSH_CHROOT_DIRECTORY=%h SSH_INHERIT_ENVIRONMENT=false SSH_PASSWORD_AUTHENTICATION=false -SSH_REAPER_TIMEOUT=3600 SSH_SUDO=ALL=(ALL) ALL SSH_TIMEZONE=UTC SSH_USER=app-admin diff --git a/CHANGELOG.md b/CHANGELOG.md index 1131446..730225a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,8 @@ Summary of release changes for Version 2 - CentOS-7 - Adds improved lock/state file implementation in bootstrap and wrapper scripts. - Adds improved `clean` Makefile target; includes exited containers and dangling images. - Adds feature to optionally exit the container after a specified timout period. -- Adds `SSH_AUTOSTART_REAPER` to control startup of `reaper`. -- Adds `SSH_REAPER_TIMEOUT` with a default value of 3600 seconds (i.e 1 hour). +- Adds `ENABLE_REAPER` with a default value of `false` to enable the `reaper` service. +- Adds `REAPER_TIMEOUT` with a default value of `3600` seconds (i.e 1 hour). - Fixes port incrementation failures when installing systemd units via `scmi`. - Fixes etcd port registration failures when installing systemd units via `scmi` with the `--register` option. - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. diff --git a/Dockerfile b/Dockerfile index 64c71d6..d79d8f1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -93,15 +93,15 @@ EXPOSE 22 # Set default environment variables # ------------------------------------------------------------------------------ ENV \ + ENABLE_REAPER="false" \ + REAPER_TIMEOUT="3600" \ SSH_AUTHORIZED_KEYS="" \ - SSH_AUTOSTART_REAPER="false" \ SSH_AUTOSTART_SSHD="true" \ SSH_AUTOSTART_SSHD_BOOTSTRAP="true" \ SSH_AUTOSTART_SUPERVISOR_STDOUT="false" \ SSH_CHROOT_DIRECTORY="%h" \ SSH_INHERIT_ENVIRONMENT="false" \ SSH_PASSWORD_AUTHENTICATION="false" \ - SSH_REAPER_TIMEOUT="3600" \ SSH_SUDO="ALL=(ALL) ALL" \ SSH_TIMEZONE="UTC" \ SSH_USER="app-admin" \ diff --git a/default.mk b/default.mk index 499eae3..b0a05a0 100644 --- a/default.mk +++ b/default.mk @@ -41,6 +41,7 @@ DOCKER_PUBLISH := $(shell \ define DOCKER_CONTAINER_PARAMETERS --name $(DOCKER_NAME) \ --restart $(DOCKER_RESTART_POLICY) \ +--env "REAPER_TIMEOUT=$(REAPER_TIMEOUT)" \ --env "SSH_AUTHORIZED_KEYS=$(SSH_AUTHORIZED_KEYS)" \ --env "SSH_AUTOSTART_REAPER=$(SSH_AUTOSTART_REAPER)" \ --env "SSH_AUTOSTART_SSHD=$(SSH_AUTOSTART_SSHD)" \ @@ -49,7 +50,6 @@ define DOCKER_CONTAINER_PARAMETERS --env "SSH_CHROOT_DIRECTORY=$(SSH_CHROOT_DIRECTORY)" \ --env "SSH_INHERIT_ENVIRONMENT=$(SSH_INHERIT_ENVIRONMENT)" \ --env "SSH_PASSWORD_AUTHENTICATION=$(SSH_PASSWORD_AUTHENTICATION)" \ ---env "SSH_REAPER_TIMEOUT=$(SSH_REAPER_TIMEOUT)" \ --env "SSH_SUDO=$(SSH_SUDO)" \ --env "SSH_TIMEZONE=$(SSH_TIMEZONE)" \ --env "SSH_USER=$(SSH_USER)" \ diff --git a/docker-compose.yml b/docker-compose.yml index 0bafcae..7d7052f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,14 +28,14 @@ services: context: "." dockerfile: "Dockerfile" environment: + ENABLE_REAPER: "${ENABLE_REAPER}" + REAPER_TIMEOUT: "${REAPER_TIMEOUT}" SSH_AUTHORIZED_KEYS: "${SSH_AUTHORIZED_KEYS}" - SSH_AUTOSTART_REAPER: "${SSH_AUTOSTART_REAPER}" SSH_AUTOSTART_SSHD: "${SSH_AUTOSTART_SSHD}" SSH_AUTOSTART_SSHD_BOOTSTRAP: "${SSH_AUTOSTART_SSHD_BOOTSTRAP}" SSH_CHROOT_DIRECTORY: "${SSH_CHROOT_DIRECTORY}" SSH_INHERIT_ENVIRONMENT: "${SSH_INHERIT_ENVIRONMENT}" SSH_PASSWORD_AUTHENTICATION: "${SSH_PASSWORD_AUTHENTICATION}" - SSH_REAPER_TIMEOUT: "${SSH_REAPER_TIMEOUT}" SSH_SUDO: "${SSH_SUDO}" SSH_TIMEZONE: "${SSH_TIMEZONE}" SSH_USER: "${SSH_USER}" diff --git a/environment.mk b/environment.mk index cca4905..197b49e 100644 --- a/environment.mk +++ b/environment.mk @@ -23,15 +23,15 @@ STARTUP_TIME ?= 2 # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ +ENABLE_REAPER ?= false +REAPER_TIMEOUT ?= 3600 SSH_AUTHORIZED_KEYS ?= -SSH_AUTOSTART_REAPER ?= false SSH_AUTOSTART_SSHD ?= true SSH_AUTOSTART_SSHD_BOOTSTRAP ?= true SSH_AUTOSTART_SUPERVISOR_STDOUT ?= false SSH_CHROOT_DIRECTORY ?= %h SSH_INHERIT_ENVIRONMENT ?= false SSH_PASSWORD_AUTHENTICATION ?= false -SSH_REAPER_TIMEOUT ?= 3600 SSH_SUDO ?= ALL=(ALL) ALL SSH_TIMEZONE ?= UTC SSH_USER ?= app-admin diff --git a/src/etc/supervisord.d/01-reaper.conf b/src/etc/supervisord.d/01-reaper.conf index 7e15cd7..da42208 100644 --- a/src/etc/supervisord.d/01-reaper.conf +++ b/src/etc/supervisord.d/01-reaper.conf @@ -1,6 +1,6 @@ [program:reaper] autorestart = false -autostart = %(ENV_SSH_AUTOSTART_REAPER)s +autostart = %(ENV_ENABLE_REAPER)s command = /usr/sbin/reaper --verbose priority = 1 startsecs = 0 diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index 57250cd..a4f17bb 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -56,15 +56,15 @@ Environment="DOCKER_IMAGE_PACKAGE_PATH=/var/opt/scmi/packages" Environment="DOCKER_IMAGE_TAG={{RELEASE_VERSION}}" Environment="DOCKER_PORT_MAP_TCP_22=2020" Environment="DOCKER_USER=jdeathe" +Environment="ENABLE_REAPER=false" +Environment="REAPER_TIMEOUT=3600" Environment="SSH_AUTHORIZED_KEYS=" -Environment="SSH_AUTOSTART_REAPER=false" Environment="SSH_AUTOSTART_SSHD=true" Environment="SSH_AUTOSTART_SSHD_BOOTSTRAP=true" Environment="SSH_AUTOSTART_SUPERVISOR_STDOUT=false" Environment="SSH_CHROOT_DIRECTORY=%%h" Environment="SSH_INHERIT_ENVIRONMENT=false" Environment="SSH_PASSWORD_AUTHENTICATION=false" -Environment="SSH_REAPER_TIMEOUT=3600" Environment="SSH_SUDO=ALL=(ALL) ALL" Environment="SSH_TIMEZONE=UTC" Environment="SSH_USER=app-admin" @@ -131,6 +131,7 @@ ExecStartPre=-/bin/bash -c \ ExecStart=/bin/bash -c \ "exec /usr/bin/docker run \ --name %p.%i \ + --env \"REAPER_TIMEOUT=${REAPER_TIMEOUT}\" \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ --env \"SSH_AUTOSTART_REAPER=${SSH_AUTOSTART_REAPER}\" \ --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ @@ -139,7 +140,6 @@ ExecStart=/bin/bash -c \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ - --env \"SSH_REAPER_TIMEOUT=${SSH_REAPER_TIMEOUT}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ --env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ diff --git a/src/opt/scmi/default.sh b/src/opt/scmi/default.sh index df2dc93..1c192ac 100644 --- a/src/opt/scmi/default.sh +++ b/src/opt/scmi/default.sh @@ -46,15 +46,15 @@ fi # Common parameters of create and run targets DOCKER_CONTAINER_PARAMETERS="--name ${DOCKER_NAME} \ --restart ${DOCKER_RESTART_POLICY} \ +--env \"ENABLE_REAPER=${ENABLE_REAPER}\" \ +--env \"REAPER_TIMEOUT=${REAPER_TIMEOUT}\" \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ ---env \"SSH_AUTOSTART_REAPER=${SSH_AUTOSTART_REAPER}\" \ --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ --env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ --env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ --env \"SSH_CHROOT_DIRECTORY=${SSH_CHROOT_DIRECTORY}\" \ --env \"SSH_INHERIT_ENVIRONMENT=${SSH_INHERIT_ENVIRONMENT}\" \ --env \"SSH_PASSWORD_AUTHENTICATION=${SSH_PASSWORD_AUTHENTICATION}\" \ ---env \"SSH_REAPER_TIMEOUT=${SSH_REAPER_TIMEOUT}\" \ --env \"SSH_SUDO=${SSH_SUDO}\" \ --env \"SSH_TIMEZONE=${SSH_TIMEZONE}\" \ --env \"SSH_USER=${SSH_USER}\" \ diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index d8e7a9d..836bf6f 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -24,15 +24,15 @@ STARTUP_TIME="${STARTUP_TIME:-2}" # ------------------------------------------------------------------------------ # Application container configuration # ------------------------------------------------------------------------------ +ENABLE_REAPER="${ENABLE_REAPER:-false}" +REAPER_TIMEOUT="${REAPER_TIMEOUT:-3600}" SSH_AUTHORIZED_KEYS="${SSH_AUTHORIZED_KEYS:-}" -SSH_AUTOSTART_REAPER="${SSH_AUTOSTART_REAPER:-false}" SSH_AUTOSTART_SSHD="${SSH_AUTOSTART_SSHD:-true}" SSH_AUTOSTART_SSHD_BOOTSTRAP="${SSH_AUTOSTART_SSHD_BOOTSTRAP:-true}" SSH_AUTOSTART_SUPERVISOR_STDOUT="${SSH_AUTOSTART_SUPERVISOR_STDOUT:-false}" SSH_CHROOT_DIRECTORY="${SSH_CHROOT_DIRECTORY:-%h}" SSH_INHERIT_ENVIRONMENT="${SSH_INHERIT_ENVIRONMENT:-false}" SSH_PASSWORD_AUTHENTICATION="${SSH_PASSWORD_AUTHENTICATION:-false}" -SSH_REAPER_TIMEOUT="${SSH_REAPER_TIMEOUT:-3600}" SSH_SUDO="${SSH_SUDO:-ALL=(ALL) ALL}" SSH_TIMEZONE="${SSH_TIMEZONE:-UTC}" SSH_USER="${SSH_USER:-app-admin}" diff --git a/src/opt/scmi/service-unit.sh b/src/opt/scmi/service-unit.sh index 9403adb..d8e6494 100644 --- a/src/opt/scmi/service-unit.sh +++ b/src/opt/scmi/service-unit.sh @@ -6,6 +6,8 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" DOCKER_IMAGE_PACKAGE_PATH DOCKER_IMAGE_TAG DOCKER_PORT_MAP_TCP_22 + ENABLE_REAPER + REAPER_TIMEOUT SSH_AUTHORIZED_KEYS SSH_AUTOSTART_REAPER SSH_AUTOSTART_SSHD @@ -14,7 +16,6 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" SSH_CHROOT_DIRECTORY SSH_INHERIT_ENVIRONMENT SSH_PASSWORD_AUTHENTICATION - SSH_REAPER_TIMEOUT SSH_SUDO SSH_TIMEZONE SSH_USER diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index e90a63a..c4abe8c 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -2,13 +2,25 @@ set -e -function __get_ssh_reaper_timeout () +function __create_state () +{ + if [[ -n ${state_file} ]] + then + printf -- \ + '%s %s\n' \ + "${session_start}" \ + "$(( ${session_start} + ${timeout} ))" \ + > "${state_file}" + fi +} + +function __get_reaper_timeout () { local -r default_value="${1:-3600}" - local value="${SSH_REAPER_TIMEOUT}" + local value="${REAPER_TIMEOUT}" - if ! __is_valid_ssh_reaper_timeout "${value}" + if ! __is_valid_reaper_timeout "${value}" then value="${default_value}" fi @@ -29,26 +41,31 @@ function __is_valid_positive_integer () return 1 } -function __is_valid_ssh_reaper_timeout () +function __is_valid_reaper_timeout () { __is_valid_positive_integer "${@}" } function __reap () { - kill -"${signal:-TERM}" "${pid:-1}" + return kill \ + -s "${signal:-TERM}" \ + "${pid:-1}" } function main () { - local -r warning_timeout="30" + local -r state_file="/var/lib/misc/reaper" + local -r timeout="$( + __get_reaper_timeout + )" local pid="1" local signal="TERM" - local timeout="$( - __get_ssh_reaper_timeout - )" + local session_start + local session_end local verbose="false" + local warning_timeout="30" while [[ "${#}" -gt 0 ]] do @@ -81,27 +98,31 @@ function main () trap __reap \ EXIT INT TERM - if (( timeout > warning_timeout )) + if (( timeout <= warning_timeout )) then - (( timeout -= warning_timeout )) - else warning_timeout="0" fi - if coproc read -t "${timeout}" + session_start="$( + date -u +%s + )" + + __create_state + + if coproc read -t "$(( ${timeout} - ${warning_timeout} ))" then wait "${!}" || : if (( warning_timeout > 0 )) then - wall "Session expired - exiting in ${warning_timeout} seconds." + wall "Session expired - exiting in ${warning_timeout} seconds." || : if coproc read -t "${warning_timeout}" then wait "${!}" || : fi else - wall "Session expired." + wall "Session expired." || : fi fi From 6ef33d53a53dfd1098d847a10b7e205ede6ca57f Mon Sep 17 00:00:00 2001 From: James Deathe Date: Wed, 12 Jun 2019 21:35:54 +0100 Subject: [PATCH 03/17] #695: Fixes __reap call and missed variable rename. --- default.mk | 2 +- src/usr/sbin/reaper | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/default.mk b/default.mk index b0a05a0..3665daa 100644 --- a/default.mk +++ b/default.mk @@ -41,9 +41,9 @@ DOCKER_PUBLISH := $(shell \ define DOCKER_CONTAINER_PARAMETERS --name $(DOCKER_NAME) \ --restart $(DOCKER_RESTART_POLICY) \ +--env "ENABLE_REAPER=$(ENABLE_REAPER)" \ --env "REAPER_TIMEOUT=$(REAPER_TIMEOUT)" \ --env "SSH_AUTHORIZED_KEYS=$(SSH_AUTHORIZED_KEYS)" \ ---env "SSH_AUTOSTART_REAPER=$(SSH_AUTOSTART_REAPER)" \ --env "SSH_AUTOSTART_SSHD=$(SSH_AUTOSTART_SSHD)" \ --env "SSH_AUTOSTART_SSHD_BOOTSTRAP=$(SSH_AUTOSTART_SSHD_BOOTSTRAP)" \ --env "SSH_AUTOSTART_SUPERVISOR_STDOUT=$(SSH_AUTOSTART_SUPERVISOR_STDOUT)" \ diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index c4abe8c..4785a95 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -48,7 +48,7 @@ function __is_valid_reaper_timeout () function __reap () { - return kill \ + kill \ -s "${signal:-TERM}" \ "${pid:-1}" } From 6b2eb1975d4e22a45870450e5c33092dd5d065d6 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 13 Jun 2019 08:49:58 +0100 Subject: [PATCH 04/17] #695: Renames reaper autostart variable in systemd template. --- src/etc/systemd/system/centos-ssh@.service | 2 +- src/opt/scmi/service-unit.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index a4f17bb..30d2291 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -131,9 +131,9 @@ ExecStartPre=-/bin/bash -c \ ExecStart=/bin/bash -c \ "exec /usr/bin/docker run \ --name %p.%i \ + --env \"ENABLE_REAPER=${ENABLE_REAPER}\" \ --env \"REAPER_TIMEOUT=${REAPER_TIMEOUT}\" \ --env \"SSH_AUTHORIZED_KEYS=${SSH_AUTHORIZED_KEYS}\" \ - --env \"SSH_AUTOSTART_REAPER=${SSH_AUTOSTART_REAPER}\" \ --env \"SSH_AUTOSTART_SSHD=${SSH_AUTOSTART_SSHD}\" \ --env \"SSH_AUTOSTART_SSHD_BOOTSTRAP=${SSH_AUTOSTART_SSHD_BOOTSTRAP}\" \ --env \"SSH_AUTOSTART_SUPERVISOR_STDOUT=${SSH_AUTOSTART_SUPERVISOR_STDOUT}\" \ diff --git a/src/opt/scmi/service-unit.sh b/src/opt/scmi/service-unit.sh index d8e6494..d6ec453 100644 --- a/src/opt/scmi/service-unit.sh +++ b/src/opt/scmi/service-unit.sh @@ -9,7 +9,6 @@ readonly SERVICE_UNIT_ENVIRONMENT_KEYS=" ENABLE_REAPER REAPER_TIMEOUT SSH_AUTHORIZED_KEYS - SSH_AUTOSTART_REAPER SSH_AUTOSTART_SSHD SSH_AUTOSTART_SSHD_BOOTSTRAP SSH_AUTOSTART_SUPERVISOR_STDOUT From 1358399863611765b16d1a1e5b86efdf76e19baf Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 14 Jun 2019 06:48:42 +0100 Subject: [PATCH 05/17] #695: Adds simplified sessing expiry warnimg message. --- src/usr/sbin/reaper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 4785a95..acffd92 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -115,7 +115,7 @@ function main () if (( warning_timeout > 0 )) then - wall "Session expired - exiting in ${warning_timeout} seconds." || : + wall "Session expires in ${warning_timeout} seconds." || : if coproc read -t "${warning_timeout}" then From b8de2bfe67321b272c05bbd55b4fd0a1c03b6598 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 14 Jun 2019 18:57:20 +0100 Subject: [PATCH 06/17] #695: Adds lock file feature to reaper. --- src/usr/sbin/reaper | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index acffd92..3166208 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -2,6 +2,19 @@ set -e +function __cleanup () +{ + __delete_lock +} + +function __create_lock () +{ + if [[ -n ${lock_file} ]] + then + touch "${lock_file}" + fi +} + function __create_state () { if [[ -n ${state_file} ]] @@ -14,6 +27,14 @@ function __create_state () fi } +function __delete_lock () +{ + if [[ -e ${lock_file} ]] + then + rm -f "${lock_file}" + fi +} + function __get_reaper_timeout () { local -r default_value="${1:-3600}" @@ -51,10 +72,13 @@ function __reap () kill \ -s "${signal:-TERM}" \ "${pid:-1}" + + __cleanup } function main () { + local -r lock_file="/var/lock/subsys/reaper" local -r state_file="/var/lib/misc/reaper" local -r timeout="$( __get_reaper_timeout @@ -93,6 +117,18 @@ function main () esac done + if [[ -e ${lock_file} ]] + then + >&2 printf -- \ + 'ERROR: %s lock detected - aborting\n' \ + "${0##*/}" + exit 1 + fi + + trap __cleanup \ + EXIT INT TERM + __create_lock + if (( timeout > 0 )) then trap __reap \ From ed072a08cf8b6cf1739b007ec61a641a3b3fcca5 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 14 Jun 2019 22:56:26 +0100 Subject: [PATCH 07/17] #695: Adds feature to get reaper start/end timestamp or ttl (remaining seconds). --- src/usr/sbin/reaper | 88 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 3166208..895d1b9 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -49,6 +49,19 @@ function __get_reaper_timeout () printf -- '%s' "${value}" } +function __is_valid_get () +{ + local -r get_options='^(end|start|ttl)$' + local -r value="${1}" + + if [[ ${value} =~ ${get_options} ]] + then + return 0 + fi + + return 1 +} + function __is_valid_positive_integer () { local -r positive_integer='^[0-9]+$' @@ -84,45 +97,100 @@ function main () __get_reaper_timeout )" + local current_time + local get local pid="1" local signal="TERM" local session_start local session_end + local state_value local verbose="false" local warning_timeout="30" while [[ "${#}" -gt 0 ]] do case "${1}" in - -p) - pid="${2}" + --get=*) + get="${1#*=}" + shift 1 + ;; + -g|--get) + get="${2}" shift 2 || break ;; - --pid) + --pid=*) pid="${1#*=}" shift 1 ;; - -s) - signal="${2}" + -p|--pid) + pid="${2}" shift 2 || break ;; - --signal) + --signal=*) signal="${1#*=}" shift 1 ;; + -s|--signal) + signal="${2}" + shift 2 || break + ;; -v|--verbose) verbose="true" shift 1 ;; + *) + >&2 printf -- \ + 'ERROR: Unknown option %s\n' \ + "${1}" + exit 1 + ;; esac done if [[ -e ${lock_file} ]] then - >&2 printf -- \ - 'ERROR: %s lock detected - aborting\n' \ - "${0##*/}" - exit 1 + if [[ -n ${get} ]] + then + state_value="$(< "${state_file}")" + + session_end="${state_value##* }" + session_start="${state_value%% *}" + + case "${get}" in + end) + printf -- \ + '%s\n' \ + "${session_end}" + ;; + start) + printf -- \ + '%s\n' \ + "${session_start}" + ;; + ttl) + current_time="$( + date -u +%s + )" + + printf -- \ + '%s\n' \ + "$(( ${session_end} - ${current_time} ))" + ;; + *) + >&2 printf -- \ + 'ERROR: Unknown get value %s\n' \ + "${get}" + exit 1 + ;; + esac + + exit 0 + else + >&2 printf -- \ + 'ERROR: %s lock detected - aborting\n' \ + "${0##*/}" + exit 1 + fi fi trap __cleanup \ From 86ff3c49a7ed87642c1a05a3d0b44bb47480eaae Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 15 Jun 2019 21:49:51 +0100 Subject: [PATCH 08/17] #695: Adds reaper usage help/error catching. --- src/usr/sbin/reaper | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 895d1b9..b9ae2ad 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -89,6 +89,30 @@ function __reap () __cleanup } +function __usage () +{ + cat <<-EOF + Usage: ${0##*/} [OPTIONS] + ${0##*/} [{-h|--help}] + + Options: + -g, --get KEY Used to get values from a running ${0##*/} + process. The keys and values they return are: + - start : returns session start timestamp. + - end : returns session end timestamp. + - ttl : returns remaining session time to live. + -h, --help Show this help and exit. + -p, --pid PID Send the termination signal to the process with + the pid value PID. + If not specified the default is pid 1. + -s, --signal SIG Send the signal SIG to the process. + If not specified the default is SIGTERM. + -v, --verbose Output informational messages. + If not specified the default is quiet. + EOF + exit 1 +} + function main () { local -r lock_file="/var/lock/subsys/reaper" @@ -118,6 +142,9 @@ function main () get="${2}" shift 2 || break ;; + -h|--help) + __usage + ;; --pid=*) pid="${1#*=}" shift 1 @@ -142,7 +169,7 @@ function main () >&2 printf -- \ 'ERROR: Unknown option %s\n' \ "${1}" - exit 1 + __usage ;; esac done @@ -180,7 +207,7 @@ function main () >&2 printf -- \ 'ERROR: Unknown get value %s\n' \ "${get}" - exit 1 + __usage ;; esac @@ -191,6 +218,12 @@ function main () "${0##*/}" exit 1 fi + elif [[ -n ${get} ]] + then + >&2 printf -- \ + 'ERROR: %s is not running\n' \ + "${0##*/}" + __usage fi trap __cleanup \ From 5447f0c9d7e9643fa50bc35a7ecda71b5020c116 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 15 Jun 2019 23:34:02 +0100 Subject: [PATCH 09/17] #695: Adds parameters for wall and wall timeout to reaper. --- src/etc/supervisord.d/01-reaper.conf | 2 +- src/usr/sbin/reaper | 50 +++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/etc/supervisord.d/01-reaper.conf b/src/etc/supervisord.d/01-reaper.conf index da42208..adaeb25 100644 --- a/src/etc/supervisord.d/01-reaper.conf +++ b/src/etc/supervisord.d/01-reaper.conf @@ -1,7 +1,7 @@ [program:reaper] autorestart = false autostart = %(ENV_ENABLE_REAPER)s -command = /usr/sbin/reaper --verbose +command = /usr/sbin/reaper --verbose --wall-timeout 30 --wall="Session expiring in 30 seconds." priority = 1 startsecs = 0 stderr_logfile = /dev/stderr diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index b9ae2ad..bec4928 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -80,6 +80,11 @@ function __is_valid_reaper_timeout () __is_valid_positive_integer "${@}" } +function __is_valid_wall_timeout () +{ + __is_valid_positive_integer "${@}" +} + function __reap () { kill \ @@ -109,6 +114,10 @@ function __usage () If not specified the default is SIGTERM. -v, --verbose Output informational messages. If not specified the default is quiet. + -w, --wall MESSAGE Set a wall message to send before session end. + -T, --wall-timeout SECONDS Set the time before session end to send the + wall message. The default is 30 seconds. + Set to 0 to disable sending a wall message. EOF exit 1 } @@ -129,7 +138,8 @@ function main () local session_end local state_value local verbose="false" - local warning_timeout="30" + local wall_message + local wall_timeout="30" while [[ "${#}" -gt 0 ]] do @@ -165,6 +175,22 @@ function main () verbose="true" shift 1 ;; + -w|--wall) + wall_message="${2}" + shift 2 || break + ;; + --wall=*) + wall_message="${1#*=}" + shift 1 + ;; + --wall-timeout) + wall_timeout="${2}" + shift 2 || break + ;; + --wall-timeout=*) + wall_timeout="${1#*=}" + shift 1 + ;; *) >&2 printf -- \ 'ERROR: Unknown option %s\n' \ @@ -230,14 +256,22 @@ function main () EXIT INT TERM __create_lock + if ! __is_valid_wall_timeout "${wall_timeout}" + then + >&2 printf -- \ + 'ERROR: Invalid --wall-timeout\n' \ + __usage + fi + if (( timeout > 0 )) then trap __reap \ EXIT INT TERM - if (( timeout <= warning_timeout )) + if [[ -z ${wall_message} ]] \ + || (( timeout <= wall_timeout )) then - warning_timeout="0" + wall_timeout="0" fi session_start="$( @@ -246,20 +280,18 @@ function main () __create_state - if coproc read -t "$(( ${timeout} - ${warning_timeout} ))" + if coproc read -t "$(( ${timeout} - ${wall_timeout} ))" then wait "${!}" || : - if (( warning_timeout > 0 )) + if (( wall_timeout > 0 )) then - wall "Session expires in ${warning_timeout} seconds." || : + wall "${wall_message}" || : - if coproc read -t "${warning_timeout}" + if coproc read -t "${wall_timeout}" then wait "${!}" || : fi - else - wall "Session expired." || : fi fi From 5e6ec088a6f1bb09caa54a086ccc61a9381ce9a5 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Mon, 17 Jun 2019 12:33:44 +0100 Subject: [PATCH 10/17] #695: Adds --timeout parameter to reaper and sets default timeout of 0 (i.e. immediate execution). --- .env.example | 2 +- CHANGELOG.md | 2 +- Dockerfile | 2 +- environment.mk | 2 +- src/etc/supervisord.d/01-reaper.conf | 2 +- src/etc/systemd/system/centos-ssh@.service | 2 +- src/opt/scmi/environment.sh | 2 +- src/usr/sbin/reaper | 74 +++++++++++----------- 8 files changed, 45 insertions(+), 43 deletions(-) diff --git a/.env.example b/.env.example index e3089e7..f2b213e 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ ENABLE_REAPER=false -REAPER_TIMEOUT=3600 +REAPER_TIMEOUT=0 SSH_AUTHORIZED_KEYS= SSH_AUTOSTART_SSHD=true SSH_AUTOSTART_SSHD_BOOTSTRAP=true diff --git a/CHANGELOG.md b/CHANGELOG.md index 730225a..6a22210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ Summary of release changes for Version 2 - CentOS-7 - Adds improved `clean` Makefile target; includes exited containers and dangling images. - Adds feature to optionally exit the container after a specified timout period. - Adds `ENABLE_REAPER` with a default value of `false` to enable the `reaper` service. -- Adds `REAPER_TIMEOUT` with a default value of `3600` seconds (i.e 1 hour). +- Adds `REAPER_TIMEOUT` with a default value of `0` seconds (i.e no timeout delay). - Fixes port incrementation failures when installing systemd units via `scmi`. - Fixes etcd port registration failures when installing systemd units via `scmi` with the `--register` option. - Fixes binary paths in systemd unit files for compatibility with both EL and Ubuntu hosts. diff --git a/Dockerfile b/Dockerfile index d79d8f1..b854df9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -94,7 +94,7 @@ EXPOSE 22 # ------------------------------------------------------------------------------ ENV \ ENABLE_REAPER="false" \ - REAPER_TIMEOUT="3600" \ + REAPER_TIMEOUT="0" \ SSH_AUTHORIZED_KEYS="" \ SSH_AUTOSTART_SSHD="true" \ SSH_AUTOSTART_SSHD_BOOTSTRAP="true" \ diff --git a/environment.mk b/environment.mk index 197b49e..0b59271 100644 --- a/environment.mk +++ b/environment.mk @@ -24,7 +24,7 @@ STARTUP_TIME ?= 2 # Application container configuration # ------------------------------------------------------------------------------ ENABLE_REAPER ?= false -REAPER_TIMEOUT ?= 3600 +REAPER_TIMEOUT ?= 0 SSH_AUTHORIZED_KEYS ?= SSH_AUTOSTART_SSHD ?= true SSH_AUTOSTART_SSHD_BOOTSTRAP ?= true diff --git a/src/etc/supervisord.d/01-reaper.conf b/src/etc/supervisord.d/01-reaper.conf index adaeb25..641262c 100644 --- a/src/etc/supervisord.d/01-reaper.conf +++ b/src/etc/supervisord.d/01-reaper.conf @@ -1,7 +1,7 @@ [program:reaper] autorestart = false autostart = %(ENV_ENABLE_REAPER)s -command = /usr/sbin/reaper --verbose --wall-timeout 30 --wall="Session expiring in 30 seconds." +command = /usr/sbin/reaper --verbose --timeout %(ENV_REAPER_TIMEOUT)s --wall-timeout 30 --wall="Session expiring in 30 seconds." priority = 1 startsecs = 0 stderr_logfile = /dev/stderr diff --git a/src/etc/systemd/system/centos-ssh@.service b/src/etc/systemd/system/centos-ssh@.service index 30d2291..f4554f2 100644 --- a/src/etc/systemd/system/centos-ssh@.service +++ b/src/etc/systemd/system/centos-ssh@.service @@ -57,7 +57,7 @@ Environment="DOCKER_IMAGE_TAG={{RELEASE_VERSION}}" Environment="DOCKER_PORT_MAP_TCP_22=2020" Environment="DOCKER_USER=jdeathe" Environment="ENABLE_REAPER=false" -Environment="REAPER_TIMEOUT=3600" +Environment="REAPER_TIMEOUT=0" Environment="SSH_AUTHORIZED_KEYS=" Environment="SSH_AUTOSTART_SSHD=true" Environment="SSH_AUTOSTART_SSHD_BOOTSTRAP=true" diff --git a/src/opt/scmi/environment.sh b/src/opt/scmi/environment.sh index 836bf6f..93956d0 100644 --- a/src/opt/scmi/environment.sh +++ b/src/opt/scmi/environment.sh @@ -25,7 +25,7 @@ STARTUP_TIME="${STARTUP_TIME:-2}" # Application container configuration # ------------------------------------------------------------------------------ ENABLE_REAPER="${ENABLE_REAPER:-false}" -REAPER_TIMEOUT="${REAPER_TIMEOUT:-3600}" +REAPER_TIMEOUT="${REAPER_TIMEOUT:-0}" SSH_AUTHORIZED_KEYS="${SSH_AUTHORIZED_KEYS:-}" SSH_AUTOSTART_SSHD="${SSH_AUTOSTART_SSHD:-true}" SSH_AUTOSTART_SSHD_BOOTSTRAP="${SSH_AUTOSTART_SSHD_BOOTSTRAP:-true}" diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index bec4928..4d69fd5 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -35,20 +35,6 @@ function __delete_lock () fi } -function __get_reaper_timeout () -{ - local -r default_value="${1:-3600}" - - local value="${REAPER_TIMEOUT}" - - if ! __is_valid_reaper_timeout "${value}" - then - value="${default_value}" - fi - - printf -- '%s' "${value}" -} - function __is_valid_get () { local -r get_options='^(end|start|ttl)$' @@ -75,7 +61,7 @@ function __is_valid_positive_integer () return 1 } -function __is_valid_reaper_timeout () +function __is_valid_timeout () { __is_valid_positive_integer "${@}" } @@ -112,6 +98,9 @@ function __usage () If not specified the default is pid 1. -s, --signal SIG Send the signal SIG to the process. If not specified the default is SIGTERM. + -t, --timeout SECONDS Time in seconds to wait before sending the + signal to the process. The default is 0 seconds + which indicates no delay. -v, --verbose Output informational messages. If not specified the default is quiet. -w, --wall MESSAGE Set a wall message to send before session end. @@ -126,9 +115,6 @@ function main () { local -r lock_file="/var/lock/subsys/reaper" local -r state_file="/var/lib/misc/reaper" - local -r timeout="$( - __get_reaper_timeout - )" local current_time local get @@ -137,6 +123,7 @@ function main () local session_start local session_end local state_value + local timeout="0" local verbose="false" local wall_message local wall_timeout="30" @@ -171,6 +158,14 @@ function main () signal="${2}" shift 2 || break ;; + -t|--timeout) + timeout="${2}" + shift 2 || break + ;; + --timeout=*) + timeout="${1#*=}" + shift 1 + ;; -v|--verbose) verbose="true" shift 1 @@ -256,6 +251,13 @@ function main () EXIT INT TERM __create_lock + if ! __is_valid_timeout "${timeout}" + then + >&2 printf -- \ + 'ERROR: Invalid --timeout\n' \ + __usage + fi + if ! __is_valid_wall_timeout "${wall_timeout}" then >&2 printf -- \ @@ -263,23 +265,23 @@ function main () __usage fi - if (( timeout > 0 )) + if [[ -z ${wall_message} ]] \ + || (( timeout <= wall_timeout )) then - trap __reap \ - EXIT INT TERM + wall_timeout="0" + fi - if [[ -z ${wall_message} ]] \ - || (( timeout <= wall_timeout )) - then - wall_timeout="0" - fi + session_start="$( + date -u +%s + )" - session_start="$( - date -u +%s - )" + trap __reap \ + EXIT INT TERM - __create_state + __create_state + if (( timeout > 0 )) + then if coproc read -t "$(( ${timeout} - ${wall_timeout} ))" then wait "${!}" || : @@ -294,13 +296,13 @@ function main () fi fi fi + fi - if [[ ${verbose} == true ]] - then - printf -- \ - 'INFO: %s expiring session.\n' \ - "${0##*/}" - fi + if [[ ${verbose} == true ]] + then + printf -- \ + 'INFO: %s expiring session.\n' \ + "${0##*/}" fi exit 0 From 3eeb6fccb3407e0f5c9757a40b6f8683b5a09a51 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Thu, 20 Jun 2019 19:00:26 +0100 Subject: [PATCH 11/17] #695: Renames reaper config file to follow existing p1 processes. --- src/etc/supervisord.d/{01-reaper.conf => 00-reaper.conf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/etc/supervisord.d/{01-reaper.conf => 00-reaper.conf} (100%) diff --git a/src/etc/supervisord.d/01-reaper.conf b/src/etc/supervisord.d/00-reaper.conf similarity index 100% rename from src/etc/supervisord.d/01-reaper.conf rename to src/etc/supervisord.d/00-reaper.conf From 49983389f2bbcf34c62fab0c4a1744c8af8bc018 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 20 Sep 2019 09:29:37 +0100 Subject: [PATCH 12/17] #695: Adds improved message output. --- src/etc/supervisord.d/00-reaper.conf | 2 +- src/usr/sbin/reaper | 227 +++++++++++++++++++-------- 2 files changed, 165 insertions(+), 64 deletions(-) diff --git a/src/etc/supervisord.d/00-reaper.conf b/src/etc/supervisord.d/00-reaper.conf index 641262c..6ef9c9e 100644 --- a/src/etc/supervisord.d/00-reaper.conf +++ b/src/etc/supervisord.d/00-reaper.conf @@ -1,7 +1,7 @@ [program:reaper] autorestart = false autostart = %(ENV_ENABLE_REAPER)s -command = /usr/sbin/reaper --verbose --timeout %(ENV_REAPER_TIMEOUT)s --wall-timeout 30 --wall="Session expiring in 30 seconds." +command = /usr/sbin/reaper --monochrome --timeout %(ENV_REAPER_TIMEOUT)s --wall-timeout 30 --wall="Session expiring in 30 seconds." priority = 1 startsecs = 0 stderr_logfile = /dev/stderr diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 4d69fd5..b636ce6 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -29,12 +29,83 @@ function __create_state () function __delete_lock () { - if [[ -e ${lock_file} ]] + if [[ -f ${lock_file} ]] then rm -f "${lock_file}" fi } +function __print_message () +{ + local -r type="${1}" + + local colour_negative='\033[1;31m' + local colour_positive='\033[1;32m' + local colour_reset='\033[0m' + local exit_code="${3:-0}" + local message="${2}" + local prefix="" + local quiet="${quiet:-false}" + local silent="${silent:-false}" + + if [[ ${monochrome} == true ]] + then + unset \ + colour_negative \ + colour_positive \ + colour_reset + fi + + case "${type}" in + error) + prefix="$( + printf -- \ + '%bERROR:%b ' \ + "${colour_negative}" \ + "${colour_reset}" + )" + ;; + info) + prefix="$( + printf -- \ + '%bINFO:%b ' \ + "${colour_positive}" \ + "${colour_reset}" + )" + ;; + *) + message="${type}" + ;; + esac + + if [[ ${quiet} == true ]] \ + || [[ ${silent} == true ]] \ + && [[ ${type} != error ]] + then + return 0 + elif [[ ${silent} == true ]] \ + && [[ ${type} == error ]] + then + return 1 + elif [[ ${type} == error ]] + then + >&2 printf -- \ + '%s%s\n' \ + "${prefix}" \ + "${message}" + else + printf -- \ + '%s%s\n' \ + "${prefix}" \ + "${message}" + fi + + if [[ ${exit_code} -gt 0 ]] + then + exit ${exit_code} + fi +} + function __is_valid_get () { local -r get_options='^(end|start|ttl)$' @@ -82,33 +153,49 @@ function __reap () function __usage () { - cat <<-EOF - Usage: ${0##*/} [OPTIONS] - ${0##*/} [{-h|--help}] - - Options: - -g, --get KEY Used to get values from a running ${0##*/} - process. The keys and values they return are: - - start : returns session start timestamp. - - end : returns session end timestamp. - - ttl : returns remaining session time to live. - -h, --help Show this help and exit. - -p, --pid PID Send the termination signal to the process with - the pid value PID. - If not specified the default is pid 1. - -s, --signal SIG Send the signal SIG to the process. - If not specified the default is SIGTERM. - -t, --timeout SECONDS Time in seconds to wait before sending the - signal to the process. The default is 0 seconds - which indicates no delay. - -v, --verbose Output informational messages. - If not specified the default is quiet. - -w, --wall MESSAGE Set a wall message to send before session end. - -T, --wall-timeout SECONDS Set the time before session end to send the - wall message. The default is 30 seconds. - Set to 0 to disable sending a wall message. - EOF - exit 1 + local help="${help:-false}" + local quiet="${quiet:-false}" + local silent="${silent:-false}" + + if [[ ${silent} != true ]] \ + || [[ ${help} == true ]] + then + cat <<-USAGE + + Usage: ${0##*/} [OPTIONS] + ${0##*/} [{-h|--help}] + + Options: + -g, --get KEY Used to get values from a running ${0##*/} + process. The keys and values they return are: + - start : returns session start timestamp. + - end : returns session end timestamp. + - ttl : returns remaining session time to live. + -h, --help Show this help and exit. + --monochrome Output colour is suppressed. + -p, --pid PID Send the termination signal to the process with + the pid value PID. + If not specified the default is pid 1. + -q, --quiet Do not print information message output. + -qq, --silent Do not print error message output. + -s, --signal SIG Send the signal SIG to the process. + If not specified the default is SIGTERM. + -t, --timeout SECONDS Time in seconds to wait before sending the + signal to the process. The default is 0 seconds + which indicates no delay. + -w, --wall MESSAGE Set a wall message to send before session end. + -T, --wall-timeout SECONDS Set the time before session end to send the + wall message. The default is 30 seconds. + Set to 0 to disable sending a wall message. + USAGE + fi + + if [[ ${help} != true ]] + then + exit 1 + fi + + exit 0 } function main () @@ -118,8 +205,12 @@ function main () local current_time local get + local help + local monochrome="false" local pid="1" + local quiet="false" local signal="TERM" + local silent="false" local session_start local session_end local state_value @@ -128,6 +219,14 @@ function main () local wall_message local wall_timeout="30" + if [[ ${EUID} -ne 0 ]] + then + __print_message \ + "error" \ + "${0##*/} must be run as root" \ + 1 + fi + while [[ "${#}" -gt 0 ]] do case "${1}" in @@ -142,6 +241,10 @@ function main () -h|--help) __usage ;; + --monochrome) + monochrome="true" + shift 1 + ;; --pid=*) pid="${1#*=}" shift 1 @@ -158,49 +261,48 @@ function main () signal="${2}" shift 2 || break ;; - -t|--timeout) - timeout="${2}" - shift 2 || break - ;; --timeout=*) timeout="${1#*=}" shift 1 ;; + -t|--timeout) + timeout="${2}" + shift 2 || break + ;; -v|--verbose) verbose="true" shift 1 ;; - -w|--wall) - wall_message="${2}" - shift 2 || break - ;; --wall=*) wall_message="${1#*=}" shift 1 ;; - --wall-timeout) - wall_timeout="${2}" + -w|--wall) + wall_message="${2}" shift 2 || break ;; --wall-timeout=*) wall_timeout="${1#*=}" shift 1 ;; + --wall-timeout) + wall_timeout="${2}" + shift 2 || break + ;; *) - >&2 printf -- \ - 'ERROR: Unknown option %s\n' \ - "${1}" + __print_message \ + "error" \ + "${0##*/} unknown option ${1}" __usage ;; esac done - if [[ -e ${lock_file} ]] + if [[ -f ${lock_file} ]] then if [[ -n ${get} ]] then state_value="$(< "${state_file}")" - session_end="${state_value##* }" session_start="${state_value%% *}" @@ -225,25 +327,25 @@ function main () "$(( ${session_end} - ${current_time} ))" ;; *) - >&2 printf -- \ - 'ERROR: Unknown get value %s\n' \ - "${get}" + __print_message \ + "error" \ + "${0##*/} unknown get value ${get}" __usage ;; esac exit 0 else - >&2 printf -- \ - 'ERROR: %s lock detected - aborting\n' \ - "${0##*/}" - exit 1 + __print_message \ + "error" \ + "${0##*/} lock detected - aborting" \ + 1 fi elif [[ -n ${get} ]] then - >&2 printf -- \ - 'ERROR: %s is not running\n' \ - "${0##*/}" + __print_message \ + "error" \ + "${0##*/} is not running" __usage fi @@ -253,15 +355,17 @@ function main () if ! __is_valid_timeout "${timeout}" then - >&2 printf -- \ - 'ERROR: Invalid --timeout\n' \ + __print_message \ + "error" \ + "${0##*/} invalid --timeout" __usage fi if ! __is_valid_wall_timeout "${wall_timeout}" then - >&2 printf -- \ - 'ERROR: Invalid --wall-timeout\n' \ + __print_message \ + "error" \ + "${0##*/} invalid --wall-timeout" __usage fi @@ -298,12 +402,9 @@ function main () fi fi - if [[ ${verbose} == true ]] - then - printf -- \ - 'INFO: %s expiring session.\n' \ - "${0##*/}" - fi + __print_message \ + "info" \ + "${0##*/} expiring session" exit 0 } From 4e00ad369cef20f416e2fbff0072b0575968a705 Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 20 Sep 2019 14:22:42 +0100 Subject: [PATCH 13/17] #695: Fixes error return code when requesting help --- src/usr/sbin/reaper | 1 + 1 file changed, 1 insertion(+) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index b636ce6..cae5a53 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -239,6 +239,7 @@ function main () shift 2 || break ;; -h|--help) + help="true" __usage ;; --monochrome) From 8607a707a1e0c3da886ccab7a9916c3f64e3129a Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 20 Sep 2019 16:31:19 +0100 Subject: [PATCH 14/17] #695: Emmit WARN message when expiring session. --- src/usr/sbin/reaper | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index cae5a53..4f4cd3c 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -40,6 +40,7 @@ function __print_message () local -r type="${1}" local colour_negative='\033[1;31m' + local colour_notice='\033[1;33m' local colour_positive='\033[1;32m' local colour_reset='\033[0m' local exit_code="${3:-0}" @@ -52,6 +53,7 @@ function __print_message () then unset \ colour_negative \ + colour_notice \ colour_positive \ colour_reset fi @@ -65,6 +67,14 @@ function __print_message () "${colour_reset}" )" ;; + warn) + prefix="$( + printf -- \ + '%bWARN:%b ' \ + "${colour_notice}" \ + "${colour_reset}" + )" + ;; info) prefix="$( printf -- \ @@ -404,7 +414,7 @@ function main () fi __print_message \ - "info" \ + "warn" \ "${0##*/} expiring session" exit 0 From 414a39bab3fce6d2ed504e067f3398641d8d338d Mon Sep 17 00:00:00 2001 From: James Deathe Date: Fri, 20 Sep 2019 16:52:02 +0100 Subject: [PATCH 15/17] #695: Fixes WARN messages and quite/silent options. --- src/usr/sbin/reaper | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 4f4cd3c..62a9f51 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -89,7 +89,10 @@ function __print_message () esac if [[ ${quiet} == true ]] \ - || [[ ${silent} == true ]] \ + && [[ ! ${type} =~ ^(error|warn)$ ]] + then + return 0 + elif [[ ${silent} == true ]] \ && [[ ${type} != error ]] then return 0 @@ -264,6 +267,15 @@ function main () pid="${2}" shift 2 || break ;; + -q|--quiet) + quiet="true" + shift 1 + ;; + -qq|--silent) + quiet="true" + silent="true" + shift 1 + ;; --signal=*) signal="${1#*=}" shift 1 From a3199c340559f7b7fe5ff4ccbe76ec3d4edef7ef Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 21 Sep 2019 10:48:13 +0100 Subject: [PATCH 16/17] #695: Adds logging output improvements. --- src/etc/supervisord.d/00-reaper.conf | 2 +- src/usr/sbin/reaper | 165 ++++++++++++++++++--------- 2 files changed, 114 insertions(+), 53 deletions(-) diff --git a/src/etc/supervisord.d/00-reaper.conf b/src/etc/supervisord.d/00-reaper.conf index 6ef9c9e..619f44e 100644 --- a/src/etc/supervisord.d/00-reaper.conf +++ b/src/etc/supervisord.d/00-reaper.conf @@ -1,7 +1,7 @@ [program:reaper] autorestart = false autostart = %(ENV_ENABLE_REAPER)s -command = /usr/sbin/reaper --monochrome --timeout %(ENV_REAPER_TIMEOUT)s --wall-timeout 30 --wall="Session expiring in 30 seconds." +command = /usr/sbin/reaper --monochrome --verbose --timeout %(ENV_REAPER_TIMEOUT)s --wall-timeout 30 --wall="Session expiring in 30 seconds." priority = 1 startsecs = 0 stderr_logfile = /dev/stderr diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 62a9f51..7eee0fb 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -39,48 +39,76 @@ function __print_message () { local -r type="${1}" - local colour_negative='\033[1;31m' - local colour_notice='\033[1;33m' - local colour_positive='\033[1;32m' + local colour_err='\033[1;31m' + local colour_warning='\033[1;33m' + local colour_notice='\033[1;32m' + local colour_info='\033[1;37m' + local colour_debug='\033[1;30m' local colour_reset='\033[0m' local exit_code="${3:-0}" local message="${2}" + local output_debug="${output_debug:-false}" + local output_verbose="${output_verbose:-false}" + local output_quiet="${output_quiet:-false}" + local output_silent="${output_silent:-false}" local prefix="" - local quiet="${quiet:-false}" - local silent="${silent:-false}" + if [[ ${monochrome} == true ]] then unset \ - colour_negative \ + colour_err \ + colour_warning \ colour_notice \ - colour_positive \ + colour_info \ + colour_debug \ colour_reset fi case "${type}" in - error) + err|error) + prefix="$( + printf -- \ + '%bERROR%b %s' \ + "${colour_err}" \ + "${colour_reset}" \ + "${0##*/}" + )" + ;; + warning|warn) prefix="$( printf -- \ - '%bERROR:%b ' \ - "${colour_negative}" \ - "${colour_reset}" + '%bWARN%b %s' \ + "${colour_warning}" \ + "${colour_reset}" \ + "${0##*/}" )" ;; - warn) + notice) prefix="$( printf -- \ - '%bWARN:%b ' \ + '%bNOTICE%b %s: ' \ "${colour_notice}" \ - "${colour_reset}" + "${colour_reset}" \ + "${0##*/}" )" ;; info) prefix="$( printf -- \ - '%bINFO:%b ' \ - "${colour_positive}" \ - "${colour_reset}" + '%bINFO%b %s: ' \ + "${colour_info}" \ + "${colour_reset}" \ + "${0##*/}" + )" + ;; + debug) + prefix="$( + printf -- \ + '%bDEBUG%b %s: ' \ + "${colour_debug}" \ + "${colour_reset}" \ + "${0##*/}" )" ;; *) @@ -88,24 +116,42 @@ function __print_message () ;; esac - if [[ ${quiet} == true ]] \ - && [[ ! ${type} =~ ^(error|warn)$ ]] + if [[ ${output_quiet} == true ]] \ + && [[ ! ${type} =~ ^(err|error|warning|warn)$ ]] then return 0 - elif [[ ${silent} == true ]] \ - && [[ ${type} != error ]] + elif [[ ${output_silent} == true ]] \ + && [[ ! ${type} =~ ^(err|error)$ ]] then return 0 - elif [[ ${silent} == true ]] \ - && [[ ${type} == error ]] + elif [[ ${output_silent} == true ]] \ + && [[ ${type} =~ ^(err|error)$ ]] then return 1 - elif [[ ${type} == error ]] + elif [[ ${type} =~ ^(err|error)$ ]] then - >&2 printf -- \ - '%s%s\n' \ - "${prefix}" \ + logger \ + --priority "err" \ + --stderr \ + --tag "${prefix}" \ + -- \ "${message}" + elif [[ ${type} =~ ^(warning|warn)$ ]] + then + logger \ + --priority "warning" \ + --stderr \ + --tag "${prefix}" \ + -- \ + "${message}" + elif [[ ${output_debug} != true ]] \ + && [[ ${type} == debug ]] + then + return 0 + elif [[ ${output_verbose} != true ]] \ + && [[ ${type} == info ]] + then + return 0 else printf -- \ '%s%s\n' \ @@ -167,16 +213,15 @@ function __reap () function __usage () { local help="${help:-false}" - local quiet="${quiet:-false}" - local silent="${silent:-false}" + local output_quiet="${output_quiet:-false}" + local output_silent="${output_silent:-false}" - if [[ ${silent} != true ]] \ + if [[ ${output_silent} != true ]] \ || [[ ${help} == true ]] then cat <<-USAGE Usage: ${0##*/} [OPTIONS] - ${0##*/} [{-h|--help}] Options: -g, --get KEY Used to get values from a running ${0##*/} @@ -184,22 +229,24 @@ function __usage () - start : returns session start timestamp. - end : returns session end timestamp. - ttl : returns remaining session time to live. - -h, --help Show this help and exit. + -h, --help Display help text and exit. --monochrome Output colour is suppressed. -p, --pid PID Send the termination signal to the process with the pid value PID. If not specified the default is pid 1. - -q, --quiet Do not print information message output. - -qq, --silent Do not print error message output. + -q, --quiet Do not output notice, info or debug messages. + -qq, --silent Do not output any messages. -s, --signal SIG Send the signal SIG to the process. If not specified the default is SIGTERM. + -T, --wall-timeout SECONDS Set the time before session end to send the + wall message. The default is 30 seconds. + Set to 0 to disable sending a wall message. -t, --timeout SECONDS Time in seconds to wait before sending the signal to the process. The default is 0 seconds which indicates no delay. + -v, --verbose Output info messages. + -vv, --debug Output debug messages. -w, --wall MESSAGE Set a wall message to send before session end. - -T, --wall-timeout SECONDS Set the time before session end to send the - wall message. The default is 30 seconds. - Set to 0 to disable sending a wall message. USAGE fi @@ -220,15 +267,16 @@ function main () local get local help local monochrome="false" + local output_debug="false" + local output_verbose="false" + local output_quiet="false" + local output_silent="false" local pid="1" - local quiet="false" local signal="TERM" - local silent="false" local session_start local session_end local state_value local timeout="0" - local verbose="false" local wall_message local wall_timeout="30" @@ -236,7 +284,7 @@ function main () then __print_message \ "error" \ - "${0##*/} must be run as root" \ + "must be run as root" \ 1 fi @@ -268,12 +316,12 @@ function main () shift 2 || break ;; -q|--quiet) - quiet="true" + output_quiet="true" shift 1 ;; -qq|--silent) - quiet="true" - silent="true" + output_quiet="true" + output_silent="true" shift 1 ;; --signal=*) @@ -293,7 +341,12 @@ function main () shift 2 || break ;; -v|--verbose) - verbose="true" + output_verbose="true" + shift 1 + ;; + -vv|--debug) + output_debug="true" + output_verbose="true" shift 1 ;; --wall=*) @@ -315,7 +368,7 @@ function main () *) __print_message \ "error" \ - "${0##*/} unknown option ${1}" + "unknown option ${1}" __usage ;; esac @@ -352,7 +405,7 @@ function main () *) __print_message \ "error" \ - "${0##*/} unknown get value ${get}" + "unknown get value ${get}" __usage ;; esac @@ -361,14 +414,14 @@ function main () else __print_message \ "error" \ - "${0##*/} lock detected - aborting" \ + "lock detected - aborting" \ 1 fi elif [[ -n ${get} ]] then __print_message \ "error" \ - "${0##*/} is not running" + "is not running" __usage fi @@ -380,7 +433,7 @@ function main () then __print_message \ "error" \ - "${0##*/} invalid --timeout" + "invalid --timeout" __usage fi @@ -388,7 +441,7 @@ function main () then __print_message \ "error" \ - "${0##*/} invalid --wall-timeout" + "invalid --wall-timeout" __usage fi @@ -409,6 +462,10 @@ function main () if (( timeout > 0 )) then + __print_message \ + "info" \ + "session will expire after ${timeout} seconds" + if coproc read -t "$(( ${timeout} - ${wall_timeout} ))" then wait "${!}" || : @@ -425,9 +482,13 @@ function main () fi fi + __print_message \ + "info" \ + "expiring session after ${timeout} seconds" + __print_message \ "warn" \ - "${0##*/} expiring session" + "expiring session" exit 0 } From 3bcaaa133fa8515788b75f9406f46442e2b06a2a Mon Sep 17 00:00:00 2001 From: James Deathe Date: Sat, 21 Sep 2019 14:26:07 +0100 Subject: [PATCH 17/17] #695: Order variables alphabetically. --- src/usr/sbin/reaper | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/usr/sbin/reaper b/src/usr/sbin/reaper index 7eee0fb..e4299b2 100755 --- a/src/usr/sbin/reaper +++ b/src/usr/sbin/reaper @@ -39,30 +39,29 @@ function __print_message () { local -r type="${1}" + local colour_debug='\033[1;30m' local colour_err='\033[1;31m' - local colour_warning='\033[1;33m' - local colour_notice='\033[1;32m' local colour_info='\033[1;37m' - local colour_debug='\033[1;30m' + local colour_notice='\033[1;32m' local colour_reset='\033[0m' + local colour_warning='\033[1;33m' local exit_code="${3:-0}" local message="${2}" local output_debug="${output_debug:-false}" - local output_verbose="${output_verbose:-false}" local output_quiet="${output_quiet:-false}" local output_silent="${output_silent:-false}" + local output_verbose="${output_verbose:-false}" local prefix="" - if [[ ${monochrome} == true ]] then unset \ + colour_debug \ colour_err \ - colour_warning \ - colour_notice \ colour_info \ - colour_debug \ - colour_reset + colour_notice \ + colour_reset \ + colour_warning fi case "${type}" in @@ -268,13 +267,13 @@ function main () local help local monochrome="false" local output_debug="false" - local output_verbose="false" local output_quiet="false" local output_silent="false" + local output_verbose="false" local pid="1" - local signal="TERM" - local session_start local session_end + local session_start + local signal="TERM" local state_value local timeout="0" local wall_message