summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kreutz <mail@skreutz.com>2022-05-18 22:12:39 +0200
committerStefan Kreutz <mail@skreutz.com>2022-05-18 22:12:39 +0200
commite4537936f674d71afe96ee2f8a86dad6c3294409 (patch)
treed70456be236d9c0f7c7552a825cd0ea93e1166c4
downloadssh-tmux-e4537936f674d71afe96ee2f8a86dad6c3294409.tar
Add initial implementation
-rw-r--r--Makefile9
-rw-r--r--README.md22
-rw-r--r--ssh-tmux.186
-rwxr-xr-xssh-tmux.sh48
4 files changed, 165 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..7736f8b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,9 @@
+MAN= ssh-tmux.1
+BINDIR= /usr/local/bin
+MANDIR= /usr/local/man/man
+
+beforeinstall:
+ ${INSTALL} ${INSTALL_COPY} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+ ${.CURDIR}/ssh-tmux.sh ${DESTDIR}${BINDIR}/ssh-tmux
+
+.include <bsd.prog.mk>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a9c9f21
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# ssh-tmux
+
+The `ssh-tmux` utility executes a given command via `ssh` in a new `tmux`
+session on a specified host.
+
+The intended purpose is to execute long-running interactive remote commands
+with the ability to re-connect. See [this](https://www.skreutz.com/posts/TODO/)
+blog post for an introduction, and refer to the man page for details.
+
+## Install
+
+Run `make install` as root to install the `ssh-tmux` utility and man page.
+
+## Release
+
+Create an annotated tag, and an archive as follows, replacing `0.1.0` with the
+current version.
+
+ $ git tag --annotate --message "Version 0.1.0" 0.1.0
+ $ git archive --format=tar.gz --prefix=ssh-tmux-0.1.0/ \
+ --output ssh-tmux-0.1.0.tar.gz 0.1.0
+
diff --git a/ssh-tmux.1 b/ssh-tmux.1
new file mode 100644
index 0000000..ec62371
--- /dev/null
+++ b/ssh-tmux.1
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2022 Stefan Kreutz <mail@skreutz.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: May 18 2022 $
+.Dt SSH-TMUX 1
+.Os
+.Sh NAME
+.Nm ssh-tmux
+.Nd execute commands in remote tmux sessions
+.Sh SYNOPSIS
+.Nm ssh-tmux
+.Op Fl d
+.Op Fl s Ar session
+.Op Fl n Ar window
+.Ar host
+.Ar command
+.Op Ar argument ...
+.Sh DESCRIPTION
+The
+.Nm
+utility executes the given
+.Ar command
+via
+.Xr ssh 1
+in a new
+.Xr tmux 1
+session on the specified
+.Ar host .
+The
+.Ar command
+may have additional arguments.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d
+Detach from the
+.Xr tmux 1
+session.
+.It Fl s Ar session
+The name of the
+.Xr tmux 1
+session.
+.It Fl n Ar window
+The name of the
+.Xr tmux 1
+window.
+.El
+.Sh EXIT STATUS
+.Ex -std ssh-tmux
+.Sh EXAMPLES
+Execute a possibly long-running interactive remote command:
+.Bd -literal -offset indent
+$ ssh-tmux example.com "cd project && make && doas make install"
+.Ed
+.Pp
+A command with local and remote shell expansion:
+.Bd -literal -offset indent
+$ ssh-tmux example.com echo $HOST \e$HOST
+.Ed
+.Pp
+Detach and re-attach session:
+.Bd -literal -offset indent
+$ ssh-tmux -d -s monitor example.com top
+$ ssh -t example.com tmux attach-session -t monitor
+.Ed
+.Pp
+Move window to another session:
+.Bd -literal -offset indent
+$ ssh-tmux -d -s monitor -n top example.com top
+$ ssh -t example.com "tmux new-session -A -s mysession \e; move-window -s monitor:top"
+.Ed
+.Sh SEE ALSO
+.Xr ssh 1 ,
+.Xr tmux 1
+.Sh AUTHORS
+.An Stefan Kreutz Aq Mt mail@skreutz.com
diff --git a/ssh-tmux.sh b/ssh-tmux.sh
new file mode 100755
index 0000000..a7a7bac
--- /dev/null
+++ b/ssh-tmux.sh
@@ -0,0 +1,48 @@
+#! /bin/sh
+
+# Copyright (c) 2022 Stefan Kreutz <mail@skreutz.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 -o errexit
+set -o nounset
+
+err_exit() {
+ print -u2 -- "$*"
+ exit 1
+}
+
+while getopts :hds:n: option; do
+ case "$option" in
+ d) detach=true ;;
+ s) session="$OPTARG" ;;
+ n) window="$OPTARG" ;;
+ :) err_exit "missing argument for option -$OPTARG" ;;
+ ?) err_exit "illegal option: -$OPTARG" ;;
+ esac
+done
+shift $((OPTIND-1))
+
+if [ $# -eq 0 ]; then
+ err_exit "missing host argument"
+fi
+host="$1"
+shift
+
+if [ $# -eq 0 ]; then
+ err_exit "missing command argument"
+fi
+
+cmd="\"\$SHELL\" -ilc 'trap '\''ret=\$? ; [ \$ret -eq 0 ] || print -u2 -- \"[exited with status \$ret]\" ; exec \"\$SHELL\"'\'' EXIT INT ; $*'"
+
+exec ssh -t "$host" -- tmux new-session ${detach:+-d} ${session:+-s \"$session\"} ${window:+-n \"$window\"} "$cmd"
Generated by cgit. See skreutz.com for my tech blog and contact information.