Featured image of post 『 Tmux 』在脚本中运行 Tmux

『 Tmux 』在脚本中运行 Tmux

问题描述

在 shell 脚本中编写了含有 tmux 的指令,希望规定的指令能在独立的某个会话中运行,防止特殊任务阻塞脚本的运行。然而在脚本执行!到“开启 tmux 窗口”时,后续指令并不会按照原意灌入指定的窗格,而是弥散到原面板或 tmux 窗口中。

解决思路

已验证的不可靠思路

认为错误原因是窗口的创建“来不及加载”导致后续打算在该窗口中运行的指令乱飞,故使用 sleep 穿插在代码中尝试解决问题。实际上,这种思路是不可靠的,因为运行在脚本中的tmux命令会在指令尾默认加上一条“分离指令 (detach)”,这会导致 tmux 无法理解紧接着执行的原生 sh 脚本指令 (no client found)[3,4]。换言之,tmux 不知道后续的指令是否需要在当前的窗口中运行,包括上文说到的 sleep 指令。

可靠的解决方案

引用tmux中的send参数按照规定的写法指定会话,指定窗口(窗格)执行指定的命令实现“指哪打哪”。参考代码如下所示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# -*- coding: utf-8 -*-
# Time       : 2021/8/5 23:40
# Author     : QIN2DIM
# Github     : https://github.com/QIN2DIM
# Description: Tmux 脚本编程
import os


def systemctl_create_v2raycs():
    # 创建一个后台运行的名为v2raycs的session会话,其默认窗口名为system
    # [-s sessionName] [-n windowName] [-d daemon]
    os.system(f"tmux new -s v2raycs -n system -d")

    # 水平切割 v2raycs:system 使窗口分为上下屏(窗格),光标随splicer切换至下分屏
    # 使用标识符指定后台运行的操作目标 [-t targetPane]
    # os.system(f"tmux split-window -t 'v2raycs:system'")

    # 向指定会话的指定窗格发出指令
    # 使用标识符指定后台运行的操作目标 [-t targetPane]
    os.system(f"tmux send -t 'v2raycs:system' "
              f"'cd /qinse/V2RaycSpider1325/;python main.py deploy' Enter")


def systemctl_create_bot():
    os.system(f"tmux new -s bot -n core -d")
    os.system(f"tmux new -s go-cqhttp -n core -d")

    os.system(f"tmux send -t 'bot:core' "
              f"'cd /qinse/cqbot/bbot;python bot.py' Enter")
    os.system(f"tmux send -t 'go-cqhttp:core' "
              f"'cd /qinse/cqbot/go-cqhttp;./go-cqhttp ./device.json' Enter")


if __name__ == '__main__':
    systemctl_create_v2raycs()
    systemctl_create_bot()

参考资料

[1] Louis Tumux使用手册

[2] Tmux: Productive Mouse-Free Development 中文版

[3] FAQ · tmux/tmux Wiki

[4] bash - How to write a shell script that starts tmux session, and then runs a ruby script - Stack Overflow

You will to enjoy grander sight / By climing to a greater height.