Bash scripts avec tmux pour lancer une fenêtre à 4 volets

Quelqu’un peut-il aider à expliquer ce qui se passe avec tmux , bash et exec ? J’essaie de configurer une session tmux avec une fenêtre à 4 volets. Idéalement, je veux exécuter une commande dans 3 des volets: par exemple, un serveur Ruby Thin et quelques démons Ruby. C’est ce que j’ai jusqu’à présent:

~/.bin/tmux-foo :

 #!/bin/sh tmux new-session -d -s foo 'exec pfoo "bundle exec thin start"' tmux rename-window 'Foo' tmux select-window -t foo:0 tmux split-window -h 'exec pfoo "bundle exec compass watch"' tmux split-window -v -t 0 'exec pfoo "rake ts:start"' tmux split-window -v -t 1 'exec pfoo' tmux -2 attach-session -t foo 

~/.bin/pfoo :

 #!/bin/bash cd ~/projects/foo rvm use ree # here I want to execute command1 2 3 or 4... exec $SHELL 

Tout fonctionne … mais quand je ctlr-c dans le premier volet qui exécute le serveur léger, il arrête le serveur léger et retourne au shell. Cependant, la commande n’est pas dans l’histoire; c’est-à-dire que si je touche la touche Haut, je ne reçois pas la commande Execut Je me demande s’il existe un moyen d’arranger ces scripts pour obtenir les commandes de l’historique de bash.

Aussi … J’ai essayé plusieurs combinaisons de exec , exec $SHELL -s ... , et exec $SHELL -s ... -I et je ne suis pas sûr de ce qui se passe …

Quelqu’un peut-il aider à expliquer l’idée générale de ce qui se passe avec tmux et bash et exec ici?

Comme d’autres l’ont mentionné, vos commandes sont exécutées par le script shell avant de lancer votre $SHELL ; il n’y a pas de manière générale que l’instance de $SHELL puisse savoir ce que son parent a exécuté avant de le démarrer.

Pour obtenir la «commande initiale» dans l’historique du shell, vous devez envoyer les frappes de commandes directement à l’instance de $SHELL elle-même (après le démarrage, bien sûr). Dans d’autres contextes, je pourrais suggérer d’utiliser un petit programme Expect pour générer une instance de $SHELL , l’alimenter en séquences de touches, puis utiliser interact pour lier le tty à la variable $SHELL .

Mais dans le contexte de tmux , nous pouvons simplement utiliser send-keys :

 #!/bin/sh tmux new-session -d -s foo 'exec pfoo' tmux send-keys 'bundle exec thin start' 'Cm' tmux rename-window 'Foo' tmux select-window -t foo:0 tmux split-window -h 'exec pfoo' tmux send-keys 'bundle exec compass watch' 'Cm' tmux split-window -v -t 0 'exec pfoo' tmux send-keys 'rake ts:start' 'Cm' tmux split-window -v -t 1 'exec pfoo' tmux -2 attach-session -t foo 

tmuxinator vous permet de spécifier ceci avec un bon fichier yaml. Pour votre cas, vous pourriez avoir:

 # ~/.tmuxinator/foo.yml # you can make as many tabs as you wish... project_name: foo project_root: ~/projects/foo rvm: ree tabs: - main: layout: tiled panes: - bundle exec thin start - bundle exec compass watch - #empty, will just run plain bash - rake ts:start 

Vous pouvez bien sûr avoir des fenêtres supplémentaires, etc.

Vous exécutez la commande, puis vous entrez dans le shell interactif; la commande exécutée à partir du script, ne faisant pas partie d’un shell interactif, n’est pas enregistrée dans l’historique. Vous voulez vraiment un moyen de farcir (c’est un terme technique 🙂 il était une fois TIOCSTI pour “terminal ioctl (): input input”) pour le shell dans la fenêtre.

Avec tmux , il semble que vous tmux tampons pour cela. Quelque chose dans le sens de (non testé)

 #! /bin/bash cd ~/projects/foo rvm use ree if [[ $# != 0 ]]; then tmux set-buffer "$(printf '%s\n' "$*")" \; paste-buffer -d fi exec ${SHELL:-/bin/sh}