initial bits for boxctl
This commit is contained in:
commit
8ba54c36eb
15
LICENSE
Normal file
15
LICENSE
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Aaron Bieber <aaron@bolddaemon.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
27
Makefile
Normal file
27
Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# $OpenBSD$
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
SCRIPT = boxctl.sh
|
||||
MAN = man/boxctl.8
|
||||
MANDIR ?= ${PREFIX}/man/man
|
||||
BINDIR ?= ${PREFIX}/bin
|
||||
|
||||
README.md: man/boxctl.8
|
||||
mandoc -T lint man/boxctl.8
|
||||
mandoc -T markdown man/boxctl.8 >$@
|
||||
|
||||
sign:
|
||||
@sha256 boxctl.sh > SHA256
|
||||
@signify -S -s ~/signify/boxctl.sec -m SHA256 -x SHA256.sig
|
||||
@cat SHA256 >> SHA256.sig
|
||||
|
||||
verify:
|
||||
@signify -C -p /etc/signify/boxctl.pub -x SHA256.sig boxctl.sh
|
||||
|
||||
realinstall:
|
||||
${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
|
||||
${.CURDIR}/${SCRIPT} ${DESTDIR}${BINDIR}/boxctl
|
||||
|
||||
.PHONY: verify sign
|
||||
|
||||
.include <bsd.prog.mk>
|
117
README.md
Normal file
117
README.md
Normal file
@ -0,0 +1,117 @@
|
||||
BOXCTL(8) - System Manager's Manual
|
||||
|
||||
# NAME
|
||||
|
||||
**boxctl** - tool to manage remote
|
||||
OpenBSD
|
||||
machines
|
||||
|
||||
# SYNOPSIS
|
||||
|
||||
**boxctl**
|
||||
\[**-mnv**]
|
||||
\[**-h** *host*]
|
||||
\[**-u** *user*]
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
**boxctl**
|
||||
is a
|
||||
ksh(1)
|
||||
script designed to help manage
|
||||
OpenBSD
|
||||
machines.
|
||||
It uses only tools contained in
|
||||
OpenBSD
|
||||
base.
|
||||
|
||||
The options are as follows:
|
||||
|
||||
**-h** *host*
|
||||
|
||||
> Remote host to be managed.
|
||||
|
||||
**-u** *user*
|
||||
|
||||
> User to connect to
|
||||
> *host*
|
||||
> with.
|
||||
> Defaults to
|
||||
> *root*.
|
||||
|
||||
**-m**
|
||||
|
||||
> Run maintenance tasks.
|
||||
> This includes deleting unused dependencies using
|
||||
> pkg\_delete(1).
|
||||
> And installing / updating firmware using
|
||||
> fw\_update(1).
|
||||
|
||||
**-n**
|
||||
|
||||
> Dry run.
|
||||
> This will only print the commands that will be run.
|
||||
|
||||
**-v**
|
||||
|
||||
> Increase verbosity.
|
||||
> More v's can be specified to increase information output.
|
||||
> The number of v's are passed to tools used by
|
||||
> **boxctl**.
|
||||
|
||||
# FILES
|
||||
|
||||
*$CWD/files*
|
||||
|
||||
> Is a ":" delimited index of source file, owner, group, mode and destination.
|
||||
> Each source will be copied to the specified destination, then chown/chmod will
|
||||
> be run with the values specified.
|
||||
> If this file does not exist, no files are copied.
|
||||
|
||||
*$CWD/services*
|
||||
|
||||
> An optional file that contains a list of services to enable on the remote
|
||||
> host.
|
||||
> If a service is already enabled, it will be restarted each run of
|
||||
> **boxctl**.
|
||||
|
||||
*$CWD/packages*
|
||||
|
||||
> When this file exists,
|
||||
> **boxctl**
|
||||
> will install the packages contained therewithin on the remote host.
|
||||
> A list is cached on the remote host under /etc/packages.
|
||||
> This list (if it exists) will be compared using
|
||||
> diff(1)
|
||||
> and only missing packages will be installed.
|
||||
> Package names should be listed by their fuzzy names.
|
||||
> See
|
||||
> pkg\_info(1)
|
||||
> for more information on fuzzy names.
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
chmod(1),
|
||||
diff(1),
|
||||
fw\_update(1),
|
||||
pkg\_add(1),
|
||||
pkg\_delete(1),
|
||||
pkg\_info(1),
|
||||
scp(1),
|
||||
ssh(1),
|
||||
chown(8),
|
||||
rcctl(8)
|
||||
|
||||
# HISTORY
|
||||
|
||||
The first version of
|
||||
**boxctl**
|
||||
was released in September of 2019.
|
||||
|
||||
# AUTHORS
|
||||
|
||||
**boxctl**
|
||||
was written by
|
||||
Aaron Bieber <[aaron@bolddaemon.com](mailto:aaron@bolddaemon.com)>.
|
||||
|
||||
OpenBSD 6.6 - September 23, 2019
|
198
boxctl.sh
Executable file
198
boxctl.sh
Executable file
@ -0,0 +1,198 @@
|
||||
#!/bin/ksh
|
||||
|
||||
# /*
|
||||
# * Copyright (c) 2019 Aaron Bieber <aaron@bolddaemon.com>
|
||||
# *
|
||||
# * Permission to use, copy, modify, and distribute this software for any
|
||||
# * purpose with or without fee is hereby granted, provided that the above
|
||||
# * copyright notice and this permission notice appear in all copies.
|
||||
# *
|
||||
# * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
# */
|
||||
|
||||
set -au
|
||||
|
||||
SERVER=""
|
||||
RUN_USER="root"
|
||||
VERBOSITY=0
|
||||
DRY=0
|
||||
MAINTENANCE=0
|
||||
SSH_CTL_PATH="/tmp/boxctl-%r@%h:%p"
|
||||
SSH_OPTS="-o ControlMaster=auto -o ControlPersist=60s -o ControlPath=${SSH_CTL_PATH}"
|
||||
SERVICE_START_RESTART=$(cat <<EOF
|
||||
/usr/sbin/rcctl enable %s; \
|
||||
/usr/sbin/rcctl check %s && \
|
||||
/usr/sbin/rcctl restart %s || \
|
||||
/usr/sbin/rcctl start %s
|
||||
EOF
|
||||
)
|
||||
|
||||
PKG_DIFF_INSTALL=$(cat <<EOF
|
||||
if [ -f /etc/packages ]; then
|
||||
# Already ran a full install, so only install new packages
|
||||
diff -u /etc/packages /etc/packages.tmp | grep -e ^+[a-z0-9] | \
|
||||
sed 's/^+//' > /tmp/new_packages
|
||||
/usr/sbin/pkg_add %s -z -l /tmp/new_packages
|
||||
else
|
||||
/usr/sbin/pkg_add %s -z -l /etc/packages.tmp
|
||||
fi
|
||||
mv /etc/packages.tmp /etc/packages
|
||||
EOF
|
||||
)
|
||||
|
||||
while getopts "h:u:nv" arg; do
|
||||
case $arg in
|
||||
h)
|
||||
SERVER=$OPTARG
|
||||
;;
|
||||
v)
|
||||
VERBOSITY=$((VERBOSITY+1))
|
||||
;;
|
||||
n)
|
||||
DRY=1
|
||||
;;
|
||||
u)
|
||||
RUN_USER=$OPTARG
|
||||
;;
|
||||
m)
|
||||
MAINTENANCE=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
msg() {
|
||||
local _level _msg
|
||||
_level=$1
|
||||
_msg=$2
|
||||
if [ $VERBOSITY -ge $_level ] && [ $DRY == 0 ]; then
|
||||
echo "==> $_msg"
|
||||
fi
|
||||
}
|
||||
|
||||
expand_v() {
|
||||
V=""
|
||||
if [ $VERBOSITY -gt 0 ]; then
|
||||
for v in $(jot $VERBOSITY); do
|
||||
V="${V}v"
|
||||
done
|
||||
fi
|
||||
if [ "${V}" == "" ]; then
|
||||
echo "${V}"
|
||||
else
|
||||
echo "-${V}"
|
||||
fi
|
||||
}
|
||||
|
||||
ssh_verbose() {
|
||||
local _opt=""
|
||||
if [ $VERBOSITY -ge 4 ]; then
|
||||
_opt="$V"
|
||||
fi
|
||||
|
||||
if [ $DRY == 1 ]; then
|
||||
echo ssh ${SSH_OPTS} $_opt "$1" "${2}"
|
||||
else
|
||||
ssh ${SSH_OPTS} $_opt "$1" "${2}"
|
||||
fi
|
||||
}
|
||||
|
||||
ssh_quiet() {
|
||||
if [ $DRY == 1 ]; then
|
||||
echo "ssh ${SSH_OPTS} '$1' '${2}' >/dev/null"
|
||||
else
|
||||
ssh ${SSH_OPTS} "$1" "${2}" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
scp_verbose() {
|
||||
local _opt=""
|
||||
if [ $VERBOSITY -ge 4 ]; then
|
||||
_opt="$V"
|
||||
fi
|
||||
|
||||
if [ $DRY == 1 ]; then
|
||||
echo scp ${SSH_OPTS} $_opt "$1" "${2}"
|
||||
else
|
||||
scp ${SSH_OPTS} $_opt "$1" "${2}"
|
||||
fi
|
||||
}
|
||||
|
||||
scp_quiet() {
|
||||
if [ $DRY == 1 ]; then
|
||||
echo "scp ${SSH_OPTS} '$1' '${2}' >/dev/null"
|
||||
else
|
||||
scp ${SSH_OPTS} "$1" "${2}" >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
_scp() {
|
||||
local _src _dest
|
||||
_src=$1
|
||||
_dest=$2
|
||||
|
||||
if [ $VERBOSITY -gt 2 ]; then
|
||||
scp_verbose "$_src" "$_dest"
|
||||
else
|
||||
scp_quiet "$_src" "$_dest"
|
||||
fi
|
||||
}
|
||||
|
||||
_ssh() {
|
||||
local _server _cmd
|
||||
_server=$1
|
||||
_cmd=$2
|
||||
|
||||
if [ $VERBOSITY -gt 2 ]; then
|
||||
ssh_verbose "$_server" "$_cmd"
|
||||
else
|
||||
ssh_quiet "$_server" "$_cmd"
|
||||
fi
|
||||
}
|
||||
|
||||
V=$(expand_v)
|
||||
|
||||
if [ -f ./files ]; then
|
||||
msg 0 "Installing files"
|
||||
for file in $(cat files); do
|
||||
local _src _dest _mode _owner _group
|
||||
read _src _owner _group _mode _dest <<EOF
|
||||
$(echo $file | sed 's/:/ /g')
|
||||
EOF
|
||||
msg 1 "\t${_src} -> ${_dest}"
|
||||
msg 2 "\t\tchown ${_owner}:${_group} $_dest"
|
||||
msg 2 "\t\tchmod ${_mode} $_dest"
|
||||
|
||||
_scp $_src "${RUN_USER}@${SERVER}:$_dest"
|
||||
_ssh ${RUN_USER}@${SERVER} "/sbin/chown ${_owner}:${_group} $_dest; \
|
||||
/bin/chmod ${_mode} $_dest"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f ./services ]; then
|
||||
msg 0 "Enabling services"
|
||||
for service in $(cat services); do
|
||||
msg 1 "\tenabling/restarting ${service}"
|
||||
cmd="$(printf "$SERVICE_START_RESTART" \
|
||||
$service $service $service $service)"
|
||||
_ssh ${RUN_USER}@${SERVER} "${cmd}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f ./packages ]; then
|
||||
msg 0 "Installing $(wc -l packages | awk '{print $1 " " $2}') on ${SERVER}"
|
||||
cmd=$(printf "${PKG_DIFF_INSTALL}" $V $V)
|
||||
_scp packages "${RUN_USER}@${SERVER}:/etc/packages.tmp"
|
||||
_ssh ${RUN_USER}@${SERVER} "${cmd}"
|
||||
fi
|
||||
|
||||
if [ $MAINTENANCE == 1 ]; then
|
||||
msg 0 "Cleaning up unused packages"
|
||||
_ssh ${RUN_USER}@${SERVER} "/usr/sbin/pkg_delete -a"
|
||||
fi
|
110
man/boxctl.8
Normal file
110
man/boxctl.8
Normal file
@ -0,0 +1,110 @@
|
||||
.\" $OpenBSD$
|
||||
.\"
|
||||
.\" Copyright (c) 2019 Aaron Bieber <aaron@bolddaemon.com>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: September 23 2019 $
|
||||
.Dt BOXCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm boxctl
|
||||
.Nd tool to manage remote
|
||||
.Ox
|
||||
machines
|
||||
.Sh SYNOPSIS
|
||||
.Nm boxctl
|
||||
.Op Fl mnv
|
||||
.Op Fl h Ar host
|
||||
.Op Fl u Ar user
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a
|
||||
.Xr ksh 1
|
||||
script designed to help manage
|
||||
.Ox
|
||||
machines.
|
||||
It uses only tools contained in
|
||||
.Ox
|
||||
base.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl h Ar host
|
||||
Remote host to be managed.
|
||||
.It Fl u Ar user
|
||||
User to connect to
|
||||
.Pa host
|
||||
with.
|
||||
Defaults to
|
||||
.Pa root .
|
||||
.It Fl m
|
||||
Run maintenance tasks.
|
||||
This includes deleting unused dependencies using
|
||||
.Xr pkg_delete 1 .
|
||||
And installing / updating firmware using
|
||||
.Xr fw_update 1 .
|
||||
.It Fl n
|
||||
Dry run.
|
||||
This will only print the commands that will be run.
|
||||
.It Fl v
|
||||
Increase verbosity.
|
||||
More v's can be specified to increase information output.
|
||||
The number of v's are passed to tools used by
|
||||
.Nm .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width $CWD/packages
|
||||
.It Pa $CWD/files
|
||||
Is a ":" delimited index of source file, owner, group, mode and destination.
|
||||
Each source will be copied to the specified destination, then chown/chmod will
|
||||
be run with the values specified.
|
||||
If this file does not exist, no files are copied.
|
||||
.It Pa $CWD/services
|
||||
An optional file that contains a list of services to enable on the remote
|
||||
host.
|
||||
If a service is already enabled, it will be restarted each run of
|
||||
.Nm .
|
||||
.It Pa $CWD/packages
|
||||
When this file exists,
|
||||
.Nm
|
||||
will install the packages contained therewithin on the remote host.
|
||||
A list is cached on the remote host under /etc/packages.
|
||||
This list (if it exists) will be compared using
|
||||
.Xr diff 1
|
||||
and only missing packages will be installed.
|
||||
Package names should be listed by their fuzzy names.
|
||||
See
|
||||
.Xr pkg_info 1
|
||||
for more information on fuzzy names.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chmod 1 ,
|
||||
.Xr diff 1 ,
|
||||
.Xr fw_update 1 ,
|
||||
.Xr pkg_add 1 ,
|
||||
.Xr pkg_delete 1 ,
|
||||
.Xr pkg_info 1 ,
|
||||
.Xr scp 1 ,
|
||||
.Xr ssh 1 ,
|
||||
.Xr chown 8 ,
|
||||
.Xr rcctl 8
|
||||
.Sh HISTORY
|
||||
The first version of
|
||||
.Nm
|
||||
was released in September of 2019.
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
.Nm
|
||||
was written by
|
||||
.An Aaron Bieber Aq Mt aaron@bolddaemon.com .
|
Loading…
Reference in New Issue
Block a user