hi,
i'm using (as headers show) mutt as my mail client. And i'm not using it
on my computer, but rather on remote server via ssh.

Since ssh connections sometimes die, I tend to run mutt on screen
(previously) or tmux (lately).

To help me with it, I wrote simple script (attached to this mail), which
perhaps you will find useful.

when running:

tmux-auto-reattach mutt
(mutt is only example, it can be used for any other program too, of
course).

script checks first if there is session that is running mutt (based on
name of session).

if such session exists, and is detached, instead of launching new copy
of mutt - it simply attaches to the previously existing session.

if such session doesn't exist, or does, but is already attached - it
creates new session to run another copy of mutt (this is to let me have
multiple copies of mutt running at the same time).

additionally - if there are more than one detached mutt sessions - it
shows "nice" menu with list of these sessions to let me choose which one
to attach to (or start new session altogether).

the only requirements for this script are bash, whiptail (can be
changed easily to use dialog instead), grep and wc.

as additional comment/question.

I noticed that when doing:
tmux new-session "some program"

tmux runs the "some program" via /bin/sh. can it be changed somehow? I
mean - I don't use /bin/sh, and my own $SHELL is /bin/bash, and would
very much prefer if tmux used *my* shell, and not some other. I know I
can "exec bash -c \".....\"" but it just doesn't seem nice.

Best regards,

depesz

-- 
Linkedin: http://www.linkedin.com/in/depesz  /  blog: http://www.depesz.com/
jid/gtalk: dep...@depesz.com / aim:depeszhdl / skype:depesz_hdl / gg:6749007
#!/bin/bash

# This script is used to automatically run programs in tmux environment.
# Upon running it checks if there is previously running, but detached copy
# of given program. If there is such session - it is attached, instead of
# running new copy.
# If there is no detached copy - scripts starts new session for given
# program.
# If there are many detached sessions for given program - user is presented
# with menu to choose which session to attach to.
# Optionally user can pass "-s" option to make the script operate under only
# 1 session all the time - if the session exists, it will be attached, even
# if it's attached somewhere else.

show_help_and_exit () {
    if (( $# > 0 ))
    then
        FORMAT="ERROR:\n$1\n\n"
        printf "$FORMAT" "${@:2:$#}" >&2
    fi
    cat <<_EO_HELP_
Syntax:
    $0 [-s] [-n session-name] program [arg1] [arg2] [arg3]

Where:
    -s - singleton mode - only 1 session of given name is allowed. If it
         exists, even when not detached - it will be attached here.
    -n - name of session to use for this program. If not provided - it will
         be equal to basename of program binary.
    program (with args) - what to run in the tmux session

Example:
    $0 mails mutt
    will start new tmux session named "mails" with executing mutt inside, as
    long as there are no detached sessions with this name
    if there is single detached session with "mails" name - it will attach
    to it
    if there are multiple detaches sessions - you will be presented with
    menu of sessions to choose the one you want to attach to (or create new
    one)

    $0 -s news slrn
    will start new session only if there is no "news" session already
    existing (it's attached/detached state doesn't matter).
    if such session exists - tmux will attach to it.

Since tmux doesn't let you to have multiple sessions with the same name - if
such case would be needed (like starting two copies of "$0 mails mutt")
subsequent sessions will be named "[session-name]-x", where x will be
integer incrementing from 0.

Because of above, if you'll have multiple "mails" sessions, their names can
be "mails" and "mails-0", but can be even "mails-14" and "mails-60" if you
started 62 mails sessions, and then closed all except those two.
_EO_HELP_
    exit
}

singleton=0
session_name=

while getopts ':hsn:' opt
do
    case "$opt" in
        s)
            singleton=1
            ;;
        n)
            session_name="$OPTARG"
            ;;
        h)
            show_help_and_exit
            ;;
        :)
            show_help_and_exit "Option -%s requires argument!" "$OPTARG"
            ;;
        \?)
            if [[ "$OPTARG" == "?" ]]
            then
                show_help_and_exit
            fi
            show_help_and_exit "Unknown option -%s" "$OPTARG"
            ;;
    esac
done

shift $(( $OPTIND - 1 ))
if [[ "$1" = -- ]]
then
    shift
fi

if [[ -z "$1" ]]
then
    show_help_and_exit "You didn't provide name of the program to run"
fi

if [[ -z "$session_name" ]]
then
    session_name="${1##*/}"
fi

stringified_command_for_tmux="$( printf '%q ' "$@" )"

if (( "$singleton" == 1 ))
then
    if tmux has -t "$session_name" > /dev/null 2>&1
    then
        exec tmux attach-session -t "$session_name"
    fi
    # In event one would need it to work with arguments containing special
    # characters like tab or enter (not space!), the line should be:
    # exec tmux new-session -s "$session_name" "exec bash -c \"exec 
$stringified_command_for_tmux\""
    # but since I don't care about such characters in arguments to normal
    # tmuxable programs:
    exec tmux new-session -s "$session_name" "exec 
$stringified_command_for_tmux"
fi

interesting_sessions_list="$( LC_ALL=C tmux list-sessions 2> /dev/null | grep 
-E "^${session_name}(-[0-9]+)?:" )"

if [[ -z "$interesting_sessions_list" ]]
then
    exec tmux new-session -s "$session_name" "exec 
$stringified_command_for_tmux"
fi

potential_new_session_number=0
matching_regex='-[0-9]+$'
while read -r session_line
do
    just_name="${session_line%%:*}"
    [[ "$just_name" =~ $matching_regex ]] || continue
    number_in_name="${just_name##*-}"
    if (( $number_in_name >= $potential_new_session_number ))
    then
        potential_new_session_number=$(( $number_in_name + 1 ))
    fi
done <<< "$interesting_sessions_list"

detached_sessions="$( echo "$interesting_sessions_list" | grep -vE ' 
\(attached\)$' )"

if [[ -z "$detached_sessions" ]]
then
    exec tmux new-session -s "${session_name}-${potential_new_session_number}" 
"exec $stringified_command_for_tmux"
fi

detached_sessions_count="$( echo "$detached_sessions" | wc -l )"

if (( "$detached_sessions_count" == 1 ))
then
    exec tmux attach-session -t "${detached_sessions%%:*}"
fi

session_names=( "new" )
whiptail_options=( 0. "New session" )

i=0
while read line
do
    (( i++ ))
    this_session_name="${line%%:*}"
    session_names[$i]="$this_session_name"

    suffix_removed="${line%)*}"
    session_text="${suffix_removed##*(}"
    whiptail_options[$(( $i * 2 ))]="$i."
    whiptail_options[$(( $i * 2 + 1))]="$session_text"
done <<< "$detached_sessions"

whiptail_output="$( mktemp )"
trap "rm -f $whiptail_output" EXIT
whiptail --title "Choose session to connect to:" --menu "" 17 41 10 
"${whiptail_options[@]}" 2> "$whiptail_output"
user_choice=$( < "$whiptail_output" )
rm -f "$whiptail_output"

if [[ -z $user_choice ]]
then
    exit
fi

if [[ $user_choice == "0." ]]
then
    exec tmux new-session -s "${session_name}-${potential_new_session_number}" 
"exec $stringified_command_for_tmux"
fi

session_index="${user_choice%.}"

exec tmux attach-session -t "${session_names[$session_index]}"
------------------------------------------------------------------------------
Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)!
Finally, a world-class log management solution at an even better price-free!
Download using promo code Free_Logger_4_Dev2Dev. Offer expires 
February 28th, so secure your free ArcSight Logger TODAY! 
http://p.sf.net/sfu/arcsight-sfd2d
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to