From 4d3636e77a770016dbda5b32b7d61876340967d5 Mon Sep 17 00:00:00 2001 From: Michael Krayer Date: Fri, 26 Mar 2021 14:39:14 +0100 Subject: [PATCH] now uses 'script' to provide a scrollback buffer at reattaching. Otherwise all screen output while not attached gets lost --- session | 101 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/session b/session index 47eb76f..4484e8b 100755 --- a/session +++ b/session @@ -8,8 +8,9 @@ typeset -A config config=( [socket_dir]="/tmp/" [socket_base]="session-$UID" - [shell]="/bin/bash" - [redraw]="winch" + [log_session]="yes" + [scrollback]="50" + [detach_char]="" ) # Source from configuration file if available if [ -f "$CONFIG_FILE" ]; then @@ -23,18 +24,19 @@ if [ -f "$CONFIG_FILE" ]; then done < $CONFIG_FILE fi -## Set some variables +# Set some variables SOCKET_PREFIX="${config[socket_dir]}/${config[socket_base]}-" SOCKET_SUFFIX=".socket" +LOG_SUFFIX=".log" # Exit codes EXIT_SUCCESS=0 EXIT_INVALID_MODE=1 -EXIT_SESSION_EXISTS=2 -EXIT_SESSION_NOT_EXIST=3 -EXIT_ALREADY_IN_SESSION=4 -EXIT_INVALID_CONFIG=5 -EXIT_CONFIG_EXISTS=6 +EXIT_INVALID_SUBMODE=2 +EXIT_SESSION_EXISTS=3 +EXIT_SESSION_NOT_EXIST=4 +EXIT_ALREADY_IN_SESSION=5 +EXIT_CONFIG_NOT_GENERATED=6 EXIT_INVALID_CHOICE=7 ## Functions @@ -51,7 +53,7 @@ print_help() { echo >&2 " help | | h display this help message" echo >&2 "" echo >&2 "$(basename $0) attach [name]" - echo >&2 " Attach to specified session. If no session name is provided, an interactive" + echo >&2 " Attach to specified session. If no session name is provided, an interactive " echo >&2 " selection menu is provided. Use to detach." echo >&2 "" echo >&2 "$(basename $0) new [name]" @@ -78,6 +80,9 @@ print_help() { echo >&2 "" echo >&2 "$(basename $0) is configured using the file '$CONFIG_FILE', which, if" echo >&2 "non-existent, can be initialized with '$(basename $0) config generate'." + echo >&2 "All sessions are logged by default in order to provide a scrollback" + echo >&2 "buffer at attaching. The logs are located in '${config[socket_dir]}'" + echo >&2 "and logs of terminated sessions may be cleared using '$(basename $0) log clear'." } get_available_sessions() { @@ -91,10 +96,25 @@ get_available_sessions() { echo ${socket_names[@]} } +get_available_logs() { + local log_paths=(${SOCKET_PREFIX}*${LOG_SUFFIX}) + local socket_names=() + for spath in ${log_paths[@]}; do + sname=${spath##${SOCKET_PREFIX}} + sname=${sname%%${LOG_SUFFIX}} + socket_names+=("${sname}") + done + echo ${socket_names[@]} +} + get_session_path() { echo "${SOCKET_PREFIX}${1}${SOCKET_SUFFIX}" } +get_log_path() { + echo "${SOCKET_PREFIX}${1}${LOG_SUFFIX}" +} + is_existing_session_path() { if [ -S $1 ]; then true @@ -123,8 +143,8 @@ exit_if_in_session() { } exit_if_existing_session() { - if ! is_existing_session_name $session_name; then - echo >&2 "Session '$session_name' does not exist." + if is_existing_session_name $session_name; then + echo >&2 "Session '$session_name' already exists." exit $EXIT_SESSION_NOT_EXIST fi } @@ -143,6 +163,13 @@ print_session_info() { printf "%-24s %-20s %s\n" "$session_name" "$session_time" "$session_path" } +print_scrollback() { + local session_name=$1 + local log_path=$(get_log_path $session_name) + printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' - + tail -n ${config[scrollback]} $log_path +} + ## Parse first argument (= mode argument) if [[ "$#" -lt 1 ]]; then print_help @@ -175,8 +202,12 @@ case $mode in exit_if_nonexisting_session $session_name fi session_path=$(get_session_path $session_name) - CMD="dtach -a $session_path -r ${config[redraw]}" - exec $CMD + CMD="dtach -a $session_path -e ${config[detach_char]} -r winch " + #echo $CMD + echo "[attached to $session_name]" + [[ "${config[log_session]}" == "yes" ]] && print_scrollback $session_name + eval $CMD + exit $EXITSUCCESS ;; "new"|"n") exit_if_in_session @@ -191,9 +222,18 @@ case $mode in fi session_path=$(get_session_path $session_name) CMD="env DTACH_SOCKET_PATH=$session_path DTACH_SESSION_NAME=$session_name " - CMD+="dtach -c $session_path -r ${config[redraw]} ${config[shell]}" - echo $CMD - exec $CMD + CMD+="dtach -c $session_path -e ${config[detach_char]} -r winch " + if [[ "${config[log_session]}" == "yes" ]]; then + log_path=$(get_log_path $session_name) + touch $log_path && chmod 600 $log_path + CMD+="/bin/script -q -f $log_path" + else + CMD+="/bin/bash" + fi + #echo $CMD + echo "[new session $session_name]" + eval $CMD + exit $EXITSUCCESS ;; "terminate"|"term"|"t"|"kill"|"k") # Check if we are in terminate/kill mode @@ -222,13 +262,15 @@ case $mode in fi for sname in ${session_name[@]}; do spath=$(get_session_path $sname) + logpath=$(get_log_path $sname) PID=$(fuser $spath 2> /dev/null) - CMD="kill $SIGNAL $PID" - exec $CMD - if [[ "$CLEANUP" -eq 1 ]]; then - CMD="rm $spath" - exec $CMD + if [ ! -z "$PID" ]; then + CMD="kill $SIGNAL $PID" + eval $CMD + else # this seems to be an orphan + CLEANUP=1 fi + [[ "$CLEANUP" -eq 1 ]] && rm $spath done exit $EXIT_SUCCESS ;; @@ -263,11 +305,11 @@ case $mode in "config") if [[ "$1" != "generate" ]]; then echo >&2 "Use '$(basename $0) config generate' to generate default configuration file." - exit $EXIT_INVALID_CONFIG + exit $EXIT_INVALID_SUBMODE fi if [ -f "$CONFIG_FILE" ]; then echo >&2 "Configuration file '$CONFIG_FILE' already exists. Please remove it first." - exit $EXIT_CONFIG_EXISTS + exit $EXIT_CONFIG_NOT_GENERATED fi printf "" > $CONFIG_FILE for key in ${!config[@]}; do @@ -275,6 +317,19 @@ case $mode in done exit $EXIT_SUCCESS ;; + "log") + if [[ "$1" != "clear" ]]; then + echo >&2 "Use '$(basename $0) log clear' to clear all unused log files." + exit $EXIT_INVALID_SUBMODE + fi + logs_avail=($(get_available_logs)) + for sname in ${logs_avail[@]}; do + if ! is_existing_session_name $sname; then + rm $(get_log_path $sname) + fi + done + exit $EXIT_SUCCESS + ;; *) echo >&2 "Invalid mode: ${mode}" print_help