【问题标题】:Bash scripts with tmux to launch a 4-paned window使用 tmux 启动 4 窗格窗口的 Bash 脚本
【发布时间】:2011-07-23 18:25:26
【问题描述】:

谁能帮忙解释一下tmuxbashexec 的情况?我正在尝试使用 4 窗格窗口设置 tmux 会话。理想情况下,我想在 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 历史记录中的命令。

另外...我尝试了execexec $SHELL -s ...exec $SHELL -s ... -I 的多种组合,但我不太确定发生了什么...

谁能在这里帮忙解释一下tmuxbashexec发生了什么?

【问题讨论】:

标签: bash exec tmux


【解决方案1】:

正如其他人所提到的,您的命令正在由 shell 脚本运行之前启动您的$SHELL; $SHELL 的实例在启动之前无法知道其父级运行了什么。

要将“初始命令”输入到 shell 历史记录中,您需要将命令击键直接提供给 $SHELL 实例本身(当然是在它启动之后)。在其他情况下,我可能会建议使用小型 Expect 程序来生成 $SHELL 的实例,将击键输入它,然后使用 interact 将 tty 绑定到 expect-spawned $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

【讨论】:

  • 如果 tmux 是后端,这也可以通过 Byobu 工作。
  • 请问,'exec pfoo' 应该做什么?我尝试在我的实例上运行该行,但它没有创建会话(它似乎在尝试创建会话后立即退出,然后添加了一些字符)。想知道它是否与我的 PuTTy 设置有关。
  • 'exec pfoo' 是您实际想要执行的任何命令的占位符。
  • 'exec pfoo' 正在执行您的 pfoo 脚本之一,该脚本保存在您的 $PATH 目录之一中。
【解决方案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

你当然可以有额外的窗户等等。

【讨论】:

  • 很高兴了解 tmuxinator,谢谢!
【解决方案3】:

将以下内容放入命令提示符[全部为一行],它将自动打开 4 个 tmux 面板(我知道这不是问题,但这看起来比我看到的要容易一些):

    tmux new-session \; \split-window -v \; \split-window -h \; \select-pane -t 0 \; \split-window -h

现在您可以使用该命令并将其与您喜欢的任何脚本语言一起使用 [如果使用 perl...和可能的其他语言,您需要将转义字符 {反斜杠字符} 加倍]。

这会在较新的 tmux 面板中运行后续命令,恢复到第一个并在最后拆分它。

【讨论】:

    【解决方案4】:

    您正在运行命令,然后进入交互式 shell;从脚本运行的命令(不在交互式 shell 中)不会记录在历史记录中。你真的想要一种方法来填充(这是一个技术术语:) 曾几何时它是 TIOCSTI for "terminal ioctl(): stuff input")将 shell 输入到窗口中。

    对于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}
    

    【讨论】:

    • 嗯,很有趣......它不太好用,但我明白你的意思。我会试着玩弄这个想法。谢谢!
    • 在(较新的?)ksh 中,有一个环境变量设置,它是 HIST* 变量之一,如果设置正确,它将捕获从 . profile 文件到当前(非交互式)shell 的历史记录中。由于新的 ksh 和 bash 都符合 Posix,因此 bash 很可能也可以做到这一点。 (对不起,关于为什么我不能挖掘出来并给你关于如何做到这一点的确切语法,这是一个很长的故事;-()
    猜你喜欢
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多