tmux

Table of Contents

1. tmux

1.3. cheatsheet

prefix=C-b
http://manpages.ubuntu.com/manpages/bionic/man1/tmux.1.html

tmux new -s <session_name> # -d to instantly detach
tmux switch-client <session-name>
prefix d # dettach from a session
tmux -S <file> a -t <session_name> # attach to a session
tmux new -s <session_name> -d # -d → daemon mode, start in bg
prefix t # clock, RET to exit
tmux ls # list sessions
tmux new -s <session_name> -n <window_name>

prefix c → create new window (also tmux neww)
prefix , → rename window
prefix $ → rename session
prefix n, prefix p → next, prev window
prefix 0-9 → select Nth window
prefix z → maximize (zoom) current pane
prefix ! → move pane to new window
prefix x →  Kill the current pane.

prefix { Swap the current pane with the previous pane.
prefix } Swap the current pane with the next pane.

prefix N → go to Nth window
prefix w → see sessions and windows in tree view

prefix [ → enter copy mode (scroll)
  Page Up, Page Down     Enter copy mode and scroll one page up, Down.
  C-s → search

prefix %, prefix "  → splits "
prefix o (select next pane), prefix ←↑↓→

prefix : → command mode
prefix ( → go to next session
prefix ) → go to prev session

prefix ↑, ↓ ←, → Change to the pane above, below, to the left, or to the right of the current pane.
prefix C-↑, C-↓ C-←, C-→ Resize the current pane in steps of one cell.
prefix M-↑, M-↓ M-←, M-→ Resize the current pane in steps of five cells.


prefix M-1 to M-5  Arrange panes in one of the five preset layouts: even-horizontal, even- vertical, main-horizontal, main-vertical, or tiled.
prefix Space       Arrange the current window in the next preset layout.

prefix f           Prompt to search for text in open windows.

prefix C-o         Rotate the panes in the current window forwards.
prefix M-o         Rotate the panes in the current window backwards.

           C-z         Suspend the tmux client.
           &           Kill the current window.
           ;           Move to the previously active pane.
           =           Choose which buffer to paste interactively from a list.
           ?           List all key bindings.
           D           Choose a client to detach.
           L           Switch the attached client back to the last session.
           ]           Paste the most recently copied buffer of text.
           i           Display some information about the current window.
           l           Move to the previously selected window.
           o           Select the next pane in the current window.
           m           Mark the current pane (see select-pane -m).
           M           Clear the marked pane.
           s           Select a new session for the attached client interactively.
           w           Choose the current window interactively.
           x           Kill the current pane.
           ~           Show previous messages from tmux, if any.
           M-n         Move to the next window with a bell or activity marker.
           M-p         Move to the previous window with a bell or activity marker.

1.4. Hacer un script start.sh con tmux   project

1.4.1. tmux start script python

  • [ ] Use attach if exists to attach to a faulty session (kinda idempotency)
  • [ ]

    Is there a way to get last executed command in tmux? Or the command passed to tmux?

        cat /proc/$(ps -e -o pid -o ppid | grep "^$$" | awk '{print $2}')/cmdline | tr '\0' ' ' | sed 's/tmux new -s session -n window //'
    
        tmux new -s mytmux -n window "
        cat /proc/\$(ps -e -o pid -o ppid | grep ^\$\$ | awk '{print \$2}')/cmdline | tr '\0' ' ' | sed -z \"s/tmux new -s \$(tmux display -p '#S') -n \$(tmux display -p '#W') \\n//\"
        \$SHELL -l"
    
  • [ ] tmux → poner pwd en la sesión. Seleccionar texto sin que lo copie y haga scroll hacia al final saliendo del modo de editar
  • start.sh → si hay un fallo, quiero que me saque el último comando que funcionó, estuve probando con trap, o poner $SHELL -l
    https://stackoverflow.com/questions/5311583/tmux-how-to-make-new-window-stay-when-start-shell-command-quits
    autoexpect(1) - Linux man page (simulate user input in a terminal)
  • launch-in-session-window → otra función para que dependiendo de $PWD y el comando que le pasas te autonombre las cosas
    attach también que te dependa de $PWD
    ipykernels cruzar con información de zpy?
1.4.1.1. Code
#!/bin/bash
PROJECT_ROOT='/home/julian/code/foobar'
ENV_FILE="$PROJECT_ROOT/.env"
VENV_ACTIVATE="/home/julian/.local/share/venvs/$(md5sum <<< "$PWD" | awk '{print $1}')/venv/bin/activate"

function launch_script_in_session_window() {
    session=$1
    window=$2
    shift 2
    if tmux list-windows -t "$session"; then
        tmux neww -t "$session": -n "$window" -d "$@; $SHELL -l"
    else
        tmux new -s "$session" -n "$window" -d "$@; $SHELL -l"
    fi
}


# Only valid for zsh, $((  )) supports floating point arithmetic
launch_script_in_session_window chatgpt jupyter "
cd $PROJECT_ROOT
set -a
source $ENV_FILE
set +a
jupyter lab --NotebookApp.ResourceUseDisplay.mem_limit=$(( 3.0 *1024*1024*1024)) --NotebookApp.ResourceUseDisplay.track_cpu_percent=True
"


launch_script_in_session_window chatgpt django "
cd $PROJECT_ROOT
source $VENV_ACTIVATE
cd django-server
set -a
source $ENV_FILE
set +a
for port in {8000..8010}; do
    python manage.py runserver 0.0.0.0:"'$port'"
done
"

launch_script_in_session_window asuma postgis docker run \
                -v $HOME/.local/share/dbname:/var/lib/postgresql/data \
                -e POSTGRES_PASSWORD='myinsecurepassword' \
                -p 5432:5432 \
                --label utils-start-postgres \
                postgis/postgis:14-3.3
1.4.1.2. Launch only one service with -l
while getopts ":l:" opt; do
  case ${opt} in
    l)
      command_to_launch=$OPTARG
      ;;
    *)
      ;;
  esac
done

command_to_launch=${command_to_launch:-jupyter,django}

if echo $command_to_launch | grep jupyter; then
    launch_script_in_session_window chatgpt jupyter "
    cd $PROJECT_ROOT
    set -a
    source $ENV_FILE
    set +a
    jupyter lab --NotebookApp.ResourceUseDisplay.mem_limit=$(( 3.0 *1024*1024*1024 )) --NotebookApp.ResourceUseDisplay.track_cpu_percent=True"
fi

if echo $command_to_launch | grep django; then
    launch_script_in_session_window chatgpt django "
    cd $PROJECT_ROOT
    source $VENV_ACTIVATE
    cd django_app
    set -a
    source $ENV_FILE
    set +a
    for port in {8000..8010}; do
        python manage.py runserver 0.0.0.0:"'$port'"
    done
    "
fi
1.4.1.3. Hacer

1.4.2. Comandos interesantes de tmux

# Attach si ya está ejecutándose esa sesión
function launch_attach_if_exists() {
    session=$1
    window=$2
    shift 2
    tmux new -A -s "$session" -n "$window" -d "$@"
}

# Se puede conbinar con la de arriba para que abra la terminal si ya existe
function launch_script_in_session_window() {
    session=$1
    window=$2
    shift 2
    if tmux list-windows -t "$session"; then
        tmux neww -t "$session": -n "$window" -d "$@; $SHELL -l"
    else
        tmux new -s "$session" -n "$window" -d "$@; $SHELL -l"
    fi
}


1.4.3. Lanzar en panes en vez de en windows / cambiar de una a otra

1.4.4. Dependencias entre distintos comandos

tmux puede sacar el comando que se está ejecutando:

tmux list-panes -t caldav -F '#{pane_start_command}'
ps -H --no-headers -o pid,args -g $(tmux list-panes -F '#{pane_pid}')

bash sale con así si es una login shell: -bash
https://serverfault.com/questions/345802/what-does-the-leading-dash-in-process-cmdline-mean
https://stackoverflow.com/questions/46134090/getting-command-running-in-a-tmux-pane
Lo suyo sería pillarlos bien por tmux, docker ps o bien por ps normal, al menos que exista el proceso, o esperar cada cierto tiempo con un comando que comprueba la conexión (esto incluso lo puedes poner antes del propio programa que vas a lanzar y después pasa el control al programa dependiente)
Que sea idempotente también

1.4.5. Forzar volver a lanzar un comando

Algunas veces te interesa que no lance dos instancias, otras veces sí
Debería ser un flag estilo -f para forzar lanzar el comando

1.4.6. Se puede lanzar un comando otra vez?

# Más simple, pero complicado de modificar
tmux run-shell -C 'send-keys echo -e #{pane_start_command} Enter'
# para imprimirlo por pantalla
echo -e $(tmux display-message -p '#{pane_start_command}')

# Este sí se puede modificar:
tmux list-panes -t mytmux -F 'echo -e #{pane_start_command}' | $SHELL | xargs -I _ tmux send-keys -t mytmux _ Enter
# Por ejemplo para que no vuelva a lanzar una shell:
tmux list-panes -t mytmux -F 'echo -e #{pane_start_command}' | $SHELL | sed 's/\$SHELL -l//' | xargs -I _ tmux send-keys -t mytmux _ Enter

1.4.7. Utilizar plantillas de chezmoi para dependencias comunes

Quiero tener un único .env y start.sh aunque utilice plantillas para generarlos. Así tengo claro qué se está ejecutando y con qué variables de entorno
Si me cambio a un setup de git con wip, squash, worktree y zsh, + lazygit, me puede fastidiar un poco con worktree

  • Implementado con un nuevo repo de chezmoi con su configuración aparte (me puedo crear un nuevo alias en zsh que utilize una configuración distinta). Tengo que cambiar:
Flags:
  -c, --config path                                    Set config file (default /home/julian/.config/chezmoi/chezmoi.toml)
  -D, --destination path                               Set destination directory (default /home/julian)
      --persistent-state path                          Set persistent state file (default /home/julian/.config/chezmoi/chezmoistate.boltdb)
  -S, --source path                                    Set source directory (default /home/julian/.local/share/chezmoi)
  -W, --working-tree path                              Set working tree directory

1.4.8. Script que recrea todos los proyectos, o una lista dada

En Python(?), o que recrea los proyectos si no existen
Tiene que tener un sitio seguro del que bajarse las variables de entorno

1.5. Config tmux sobre la marcha   onthefly

1.6. tmux kubernetes (tk9s)

  • Ahora mismo te abre tmux en cada terminal que ejecutes
  • Reconocer el comando que se está ejecutando actualmente (en la ventana) y lanzar el mismo (por ejemplo si es una shell lanzar otra shell, si son logs sacar logs de otro pod relacionado seleccionando con fzf). Puede que necesite integración con plugins de k9s de algún tipo
  • [X] Sacar el host antes de lanzar k9s para darle el nombre a la sesión (una sesión por host) y en vez de k9s con la configuración que sea, crear una carpeta en /tmp con la configuración que se utilizó para lanzar el primer k9s y que las siguientes utilizen esa misma
  • Script start.sh con vistas ya predeterminadas
  • Poder guardar una vista o varias en concreto (un comando con unos argumentos al final) para luego poder volver a lanzarlas de nuevo, como poder congelarlas, o guardar sesiones de tmux. Idealmente que sean compartidas entre distintos clusters
  • tmuxbernetes → t10s
  • Poner otra shell que no sea k9s, para lanzar cualquier comando
    Por ejemplo uno de kubectl con refrescado automático

      tmux set-option -t $(cat /tmp/tmux-k9s_1727765296) default-shell /bin/zsh
      tmux set-option -t $(cat /tmp/tmux-k9s_1727765296) default-shell /tmp/k9s_context_1727765296
    

1.7. Share screen in a remote server

https://unix.stackexchange.com/questions/2523/what-are-other-ways-to-share-a-tmux-session-between-two-users

# Me
tmux -S /tmp/pair
chmod 777 /tmp/pair

# Another user
tmux -S /tmp/pair attach

# By default, sessions are created in
echo "/tmp/tmux-$(id -u)/default"

1.9. Implementar un sistema para tmux/ssh   project

La idea es poder conectarse a terminales en cualquier máquina de manera unificada y saber siempre qué sesiones tienes abiertas para que no se te queden perdidas por allí
También poder utilizar la misma configuración en todas las máquinas para no tener que andar instalando manualmente configuraciones por ejemplo de vim

dvtm no soporta colores, igual que tmux. Abduco es mejor en este sentido

1.9.1. martanne/abduco: abduco provides session management i.e. it allows programs to be run independently from its controlling terminal

https://danmackinlay.name/notebook/terminal_session_management.html
martanne/abduco: abduco provides session management i.e. it allows programs to be run independently from its controlling terminal. That is programs can be detached - run in the background - and then later reattached. Together with dvtm it provides a simpler and cleaner alternative to tmux or screen.

1.9.3. CANCELLED Hacer en abduco una terminal con socat que comparta estado

1.9.3.2. Pasos
# Servidor
mkdir /tmp/abduco
export ABDUCO_CMD=bash; abduco -c /tmp/abduco/test
socat unix-connect:/tmp/abduco/test TCP-LISTEN:5778,reuseaddr &
# Cliente
socat TCP:raspberrypi:5778 STDOUT
# Falta redireccionar STDIN/STDERR de alguna manera

http://www.dest-unreach.org/socat/doc/socat-ttyovertcp.txt

  • [ ] Redireccionar STDIN/STDERR en abduco+socat

1.9.5.

Es un comando de terminal que permite copiar texto al portapapeles del sitema operativo anfitrión cuando estás conectado por ssh
echo -e "\033]52;c;$(echo -n "test string" | base64)\a"

1.9.6. https://github.com/peikk0/tmux-cssh

Spawns multiple synchronized SSH sessions inside a tmux session.

1.9.7. Sobre cómo utilizar neomux

https://www.reddit.com/r/neovim/comments/c1yhpv/introducing_neomux_a_neovim_terminal_integration/
Aún así, la PR sobre utilizar neovim detachable necesita instalar neovim en un servidor remoto, y puede ser complicado

1.9.8. nvim vs tmux

  • nvim for linting, building, things that have to do more with the code itself
  • tmux for configuration
  • nvim for Dev, tmux for Ops
  • tmux is much simpler to install. sudo apt-get install tmux && cd ~ && wget https://raw.githubusercontent.com/lytex/tmux/master/tmux.conf
  • keep your hard-to-install, complex config in vim, and use tmux without plugins, only config file
  • downside of remote tmux, local nvim → conflicting keybindings? → tmux-suspend solves it
1.9.8.1. https://www.reddit.com/r/vim/comments/b083k8/tmux_vs_vim_terminal/

I’m a big, big fan of (neo)vim’s terminal as well. Two issue’s really bug me about it.

  1. visible terminal content gets clipped by the window bounds when resizing. This one is less of an issue as you can usually request the current session to redraw (<C-L> in terminal mode)
  2. Long lines that wrap are hard-wrapped, so yanking multi-lines always includes a newline token in them.
    https://github.com/neovim/neovim/pull/11014

Patiently waiting for these issues to be addressed but they seem like fundamental issues that will take a long time to be solved. However the liberty of using normal mode in a terminal buffer and incorporating terminal buffers into your preferred buffer management workflow is incredibly useful.

  1. No se puede editar el buffer de la terminal
  2. Relacionado con 1., a veces no ocupa toda la pantalla la terminal de nvim y tengo que hacer C-; i i i (esto es cosa de Neomux)
  • One TMUX use case: I can use it to easily SSH into another machine’s TMUX state. I even do this when I move to my bed with my laptop and leave my working session on my PC. I don’t expect this task from [Neo]Vim alone at all, since sometimes I’m running an IRC client and what not remotely, various task specific sessions, and I want to capture all that state. Another thing besides that is that using TMUX enriches my terminal experience as a whole in a portable manner, I use a bunch of TMUX plugins for session restore, matching/opening URLs, commit hashes, paths, fuzzy find words, and other functionality, which will work for any terminal, on any platform, so I don’t need that kind of feature itself from specific terminal emulator support, this really makes a smooth experience transitioning between Linux, macOS, Windows, etc.
  • One [Neo]Vim terminal use case: Sometimes you may be SSH into some bare-bones random machine you have to do maintenance, your [Neo]Vim/TMUX setup is not there, it even lacks TMUX, but there’s Vim. Do you wanna go clone your setup, install TMUX, etc? You may simply just open bare-bones Vim, use Vim tabs, windows and terminal to your advantage, and use Vim sessions to save/restore state if you need it.

The tools are there, just simply grab them for their appropriate job, if you think it’s worth.

  • Another TMUX use case: detach from window (only makes sense while connecting via ssh)
  • Con la terminal en vim puedes hacer global marks entre la terminal y un archivo que estés editando con nvr
  • Suplir todas estas cosas con gestor de ventanas (i3) y emulador de terminal (alacritty) e incluso con KDE Plasma
    • La falta de detach se puede suplir con mandarlos a un escritorio de i3 con nombre (no accesible, como si fuese un scratchpad), y luego hacer un comando ls para que me muestre las terminales detached
    • Para poder copiar cosas de múltiples líneas se puede utilizar la selección de alacritty
      • ↓ Esto no funciona con splits
    • Otra opción es usar el portapapeles de KDE, para que te matchee las líneas que justo tienen X líneas juntas y luego un salto de línea y te quite los saltos de línea
      X es lo que ocupan tus líneas en los distintos monitores
1.9.8.2. Investigar opción para que no haya hard wrap

En el ordenador personal tengo una longitud de línea de 150, que es más que la que tiene la pantalla.
Se puede poner un atajo de teclado que modifique eso para que al menos pueda copiar los contenidos ??
Para editar quizás no está tan bien porque te vas demasiado a la derecha para escribir un comando largo

1.9.8.3. Tmux and Vim — configurations to be better together

bash snippet to detect if tmux is running inside vim, allows to define overlapping shortcuts in tmux and vim:

is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

Detect if vim is running inside tmux is easy using $TMUX

1.9.8.5. Mantener tu config de zsh en remoto

Hacer un comando zssh que se hace un sshfs de los archivos que utiliza zsh y manda los comandos por ssh
Luego también todos los archivos de autocompletado y demás (para tener fzf local para que te autocomplete los comandos en remoto)
Para todo esto hay que estandarizar de alguna manera todos los terminales, o que tome un bash_history y se alimente de el o algo así, y ejecute los comandos uno a uno

1.9.9. Conectarse a una terminal remota que ya existe

ssh -J jump-machine dest-machine -t "tmux a -t 0"
ssh -J jump-machine dest-machine "tmux ls" # Para sacar una lista de todas las sesiones que tienes abiertas en todos los sitios
ssh -J jump-machine dest-machine "command; bash -l" # Para ejecutar un comando y abrir una shell

1.9.10. Hacer un script ssh que se conecta e instala abduco + dtvm si no está instalado   project maybe_20230330

La idea es que sea idempotente, si no está instalado lo instala y lo lanza y si ya está instalado lo lanza

1.9.11. distant + distant.nvim → remote nvim with all your plugins

1.9.11.1. Por qué utilizar distant.nvim ?
  1. Reducir la duplicación de dotfiles en distintas máquinas
  2. eliminar el lag para que sólo sea mientras estás guardando no mientras estás editando
  3. más integración con el lenguaje de programación
1.9.11.2. chipsenkbeil/distant.nvim: 🚧 (Alpha stage software) Edit files, run programs, and work with LSP on a remote machine from the comfort of your local environment 🚧
1.9.11.3. chipsenkbeil/distant: 🚧 (Alpha stage software) Library and tooling that supports remote filesystem and process operations. 🚧

1.9.14. abduco

1.9.14.2. DVTM: Have You Considered A Standalone Terminal Multiplexer - YouTube

No funciona bien con colores de terminal, como tmux

1.9.15. Enviar variables de entorno

SendEnv
SetEnv

1.10. terminal multiplexers are a horrible hack · kovidgoyal/kitty

https://github.com/kovidgoyal/kitty/issues/391#issuecomment-638320745

In summary: multiplexers add unnecessary overhead, suffer from a complexity cascade, because they actually have to translate escape codes, modifying them in hackish ways to get them to work with their concepts of windows/sessions.

Energy/performance wise they are poison, every byte has to be parsed twice, once by the middleman and once by the terminal. And they act as a drag on the ecosystem as a whole, making it very hard to get any new features.
Designing features becomes harder because you have to design for compatibility with a horrible hack and the diffusion into the ecosystem tends to get gated by basically a handful of individuals with, let’s say, very limited vision.

1.14. commandos y abreviaciones

1.14.1. clients and sessions

attach attach-session
detach detach-client
has has-session
lockc lock-client
locks lock-session
lsc list-clients
lscm list-commands
ls list-sessions
new new-session
refresh refresh-client
rename rename-session
showmsgs show-messages
source source-file
start start-server
suspendc suspend-client
switchc switch-client

1.14.2. windows and panes

breakp break-pane
capturep capture-pane
displayp display-panes
findw find-window
joinp join-pane
killp kill-pane
killw kill-window
last last-window
lastp last-pane
linkw link-window
lsp list-panes
lsw list-windows
movep move-pane
movew move-window
neww new-window
nextl next-layout
next next-window
pipep pipe-pane
prev previous-window
prevl previous-layout
renamew rename-window
resizep resize-pane
resizew resize-window
respawnp respawn-pane
respawnw respawn-window
rotatew rotate-window
selectl select-layout
selectp select-pane
selectw select-window
splitw split-window
swapp swap-pane
swapw swap-window
unlinkw unlink-window

1.14.3. key bindings

bind bind-key
lsk list-keys
send send-keys
unbind unbind-key

1.14.4. options

set set-option
setw set-window-option
show show-options
showw show-window-options

1.14.5. environment

setenv set-environment
showenv show-environment

1.14.6. status line

confirm confirm-before
menu display-menu
display display-message

1.14.7. buffers

clearhist clear-history
deleteb delete-buffer
lsb list-buffers
loadb load-buffer
pasteb paste-buffer
saveb save-buffer
setb set-buffer
showb show-buffer

1.14.8. miscellaneous

if if-shell
lock lock-server
run run-shell
info server-info
wait wait-for

1.16. autoexpect(1) - Linux man page (simulate user input in a terminal)

https://linux.die.net/man/1/autoexpect
autoexpect watches you interacting with another program and creates an Expect script that reproduces your interactions. For straightline scripts, autoexpect saves substantial time over writing scripts by hand

1.17. DONE No funciona con zsh el autocompletado (se ve del mismo color)

1.19. Sesiones tmux como tareas abiertas en cada servidor   idea

Lo menciona en el tao de tmux

1.20. Server, session, window, pane

Author: Julian Lopez Carballal

Created: 2024-10-21 Mon 08:27