Подтвердить что ты не робот

Bash скрипты с tmux для запуска 4-оконного окна

Может кто-нибудь объяснить, что происходит с tmux, bash и exec? Я пытаюсь настроить сеанс tmux с 4-оконным окном. В идеале, я хочу запустить команду в 3 из панелей: например. сервер Ruby Thin и несколько демонов Ruby. Это то, что у меня есть до сих пор:

~/.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

Все работает... но когда я ctlr-c в первой панели, на которой запущен тонкий сервер, он останавливает тонкий сервер и возвращается в оболочку. Однако команда не находится в истории; то есть, если я нажимаю клавишу "вверх", я не получаю команду bundle exec thin start... Я получаю другую команду из моей истории bash. Мне интересно, есть ли способ организовать эти сценарии, чтобы получить команды в истории bash.

Также... Я пробовал много комбинаций exec, exec $SHELL -s ... и exec $SHELL -s ... -I, и я не совсем уверен, что происходит...

Может кто-нибудь объяснить общую идею того, что происходит с tmux и bash и exec здесь?

4b9b3361

Ответ 1

Как уже упоминалось, ваши команды запускаются оболочкой script перед запуском $SHELL; нет общего способа, чтобы экземпляр $SHELL мог знать, что его родитель запускал, прежде чем запускать его.

Чтобы получить "начальную команду" в истории оболочки, вам нужно напрямую подать команды на экземпляр $SHELL (после того, как он был запущен, конечно). В других контекстах я мог бы предложить использовать небольшую программу Expect для создания экземпляра $SHELL, передать его нажатиями клавиш, а затем использовать interact, чтобы связать tty с ожидаемым-порожденным $SHELL.

Но в контексте tmux мы можем просто использовать send-keys:

#!/bin/sh

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

Ответ 2

tmuxinator позволяет указать это с помощью хорошего файла yaml. Для вашего случая вы могли бы:

# ~/.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

Конечно, у вас могут быть дополнительные окна и т.д.

Ответ 3

Вы выполняете команду, а затем вводите интерактивную оболочку; команда, запущенная из script, не находящаяся в интерактивной оболочке, не записывается в историю. Вы действительно хотите использовать материал (это технический термин:), когда-то он был TIOCSTI для ввода "terminal ioctl(): stuff input" ) для оболочки в окно.

С tmux, похоже, для этого вы используете буферы. Что-то вдоль линий (непроверенных)

#! /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}