自启tmux
橘子冒出来一个奇怪的需求……
有一个脚本,我希望它能在开机时启动。但是我出于一些原因,希望能使用tmux启动它。
tmux
贴一个菜鸟教程的参考链接。
tmux(Terminal Multiplexer)是一个终端复用工具,它允许你在单个终端窗口中创建多个虚拟终端会话,并能保持这些会话在后台运行。与直接使用终端相比,tmux 提供了更强大的会话管理功能。
常用命令如下:
# 新建一个session并且给它命名
tmux new -s <name>
# 列出所有会话
tmux ls
# 重新连接到指定会话
tmux attach -t <name>
# (在tmux会话中使用)分离出会话
tmux detach
此外,tmux提供了很多命令的快捷键。最常用的是分离会话。处于一个tmux会话中时,使用Ctrl+b d能分离当前会话。说的更详细一些就是:
- 你开启了一个tmux会话,从你自己的终端(例如bash)切换到了tmux终端。
- 你现在在一个tmux会话中,使用的是tmux的终端。
- 按下Ctrl+b,现在tmux在等待你输入下一个指令,再按下b。
- 然后你就会发现你退出了tmux会话,回到了原来的终端。tmux终端还在后台继续运行着。
定时任务
以前写过一篇文章,介绍如何使用crontab启动定时任务:使用crontab设置服务器定时任务 – 软软橘子
那么,我能不能定时让任务运行在tmux中呢……比起使用服务或者直接让它在后台运行,这样做的好处是:
- 你可以随时回到这个会话查看它的状态。
- 你可以提前配置好这个会话的环境,当需求改变时,在这个会话中停止原指令,运行新的指令。
使用cron运行tmux
当你尝试写一个脚本,其中只包含tmux new
,然后运行这个脚本时,你会发现这个脚本给你打开了一个新的会话,而这个指令是阻塞的,脚本后续的命令被阻断了。例子如下:
#!/bin/bash
tmux new -s my-session
# 此时新建了一个tmux会话,后续的命令不会被执行
cd ~/task/
bash ./task.sh
所以,原本人类逻辑上的命令输入不能直接写给脚本。
现在逻辑应该转变为:
- 新建一个tmux会话,但是不进入。然而要实现这点,需要使用
-d
,他表示分离,也就是detach
。 - 向现有的会话输入指令。使用命令
send
,示例:tmux send -t my-session "echo hello world"
.
此外,tmux默认使用的终端可能不是bash
,而是sh
。所以,如果有需求,还需要做终端的切换和环境变量的载入。
所以,以启动一个python虚拟环境,并且运行脚本为例,脚本代码如下:
#!/bin/bash
. /etc/profile
. ~/.bash_profile
echo "sleeping 5 seconds..."
sleep 5
echo "wake up! running tmux..."
tmux new -s my-session -d
tmux send -t my-session "bash" ENTER
tmux send -t my-session "source $HOME/python_env/bin/activate" ENTER
tmux send -t my-session "cd $HOME/service" ENTER
tmux send -t my-session "python3 ./main.py" ENTER
这里有几个要点。
- 开头的注释表示了需要使用哪个终端运行脚本,并且随后读入了配置文件。
- 有一段sleep指令。这是因为这段指令是为开机自启设计的,有可能环境未来得及配置,这里做一些等待。
- 在命令后加了一个
ENTER
,表示命令传入之后还要紧接着一个回车。 - 首先传入的命令是
bash
。这是因为,你仅仅告诉系统,用什么运行这个脚本还不够;你还要告诉被这个运行的tmux,tmux应该使用什么运行接下来传入的指令。比较绕,理解一下吧。 - 无法预期程序的目录,最好指定绝对路径。
然后使用crontab -e
打开定时任务编辑器添加如下指令来开机自动运行。
@reboot /path/to/your/script.sh
Comments NOTHING