

How To Start Tmux as Systemd User Service
source link: https://ttys3.dev/post/how-to-start-tmux-as-systemd-user-service/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

How To Start Tmux as Systemd User Service
2021-03-30
:: 荒野無燈
:: Mod 2021-03-31(a7d6a6f)
March 31, 2021
tmux 启动一下能有多慢?答案是,挺快的。
那为什么要有这种需求?
原因是布局恢复。
老灯目前使用的是一个tpm插件,名叫 tmux-resurrect
, prefix + ctrl + r 即可自动恢复所有panel.
但是有个小问题,panel比较多,比如有10多个的情况下,启动tmux还是会小闪一下的,整个过程肉眼可见,
会造成操作上的停顿。比如你打开 Gnome terminal 马上就能执行命令了,但是你刚开机启动tmux,你得等几秒才能操作,就因为这个panel恢复。
怎么样加快这个过程?答案当然是,用户登录的时候就马上运行tmux呗。
这个比较简单,直接看 ArchLinux 的 wiki 整个 systemd unit 文件就好了。
不过 Arch 的 wiki 有个小错误。
/etc/systemd/system/[email protected]
[Unit]
Description=Start tmux in detached session
[Service]
Type=forking
User=%I
# 这里 Arch wiki 原来写的是 %u, 应该修正为 %i
ExecStart=/usr/bin/tmux new-session -s %i -d
ExecStop=/usr/bin/tmux kill-session -t %i
[Install]
WantedBy=multi-user.target
要使用 %i
(表示 instance, 即 tmux@xxx
.service 里的 xxx
) 而不是%u
的原因是: %u
的值并不会被 User=
配置所影响,它表示的是 the name of the user running the service manager instance , 由于 Arch wiki 里用的是system级的unit文件,因此实际上用户名是 root
SpecifierMeaningDetails
“%u
”User nameThis is the name of the user running the service manager instance. In case of the system manager this resolves to “root
”. Note that this setting is not influenced by the User=
setting configurable in the [Service] section of the service unit.
“%i
”Instance nameFor instantiated units this is the string between the first “@
” character and the type suffix. Empty for non-instantiated units.
“%I
”Unescaped instance nameSame as “%i
”, but with escaping undone.
老灯还是觉得 user service 在这种场景下更为合适,因此没有采用 system 级别的 service方案。
我的 mytmux.service
内容如下:
# put this file to ~/.config/systemd/user/mytmux.service
# enable the service: systemctl --user enable mytmux
# ref https://wiki.archlinux.org/index.php/Tmux#Autostart_with_systemd
[Unit]
Description=Start tmux in detached session
[Service]
Type=forking
# comment here, use zsh preexec instead
# below must changed per host/user
# Environment=DISPLAY=:1
# Environment=XAUTHORITY=/run/user/1000/gdm/Xauthority
ExecStart=/usr/bin/tmux new-session -s %u -d
ExecStop=/usr/bin/tmux kill-session -t %u
Restart=on-failure
RestartSec=3s
[Install]
WantedBy=default.target
为方便安装,整了个 Makefile
:
install:
-systemctl --user stop mytmux 2>/dev/null
install -vD -m 755 ./mytmux.service ~/.config/systemd/user/mytmux.service
systemctl --user daemon-reload
systemctl --user enable --now mytmux
systemctl --user status mytmux
journalctl --user -a -f -u mytmux
.PHONY: install
troubleshooting⚓
1. DISPLAY 环境变量没有被设置⚓
这里指的是从 tmux-resurrect
自动恢复的panel里的zsh进程没有获取到 DISPLAY 环境变量,但是如果你在那个panel使用tmux showenv
查看,却发现tmux本身是获取到了这个变量的,只是 zsh 没有获取到。
猜测应该是 user service 启动的时候,x11 其实并没有完成启动。而 tmux 自身之所以能获取到 DISPLAY 的值,是因为它会自动刷新。(如果不刷新,可以通过设置 set -g update-environment 'DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY TERM'
修复 )
几经折腾后,在
这里找到了答案。在.zshrc
中加上 preexec
hook 即可:
if [ -n "$TMUX" ]; then
function refresh_env_var_from_systemd_started_tmux {
export $(tmux show-environment | grep "^DISPLAY")
export $(tmux show-environment | grep "^XAUTHORITY")
}
else
function refresh_env_var_from_systemd_started_tmux { }
fi
function preexec {
refresh_env_var_from_systemd_started_tmux
}
注意这里一定要用 preexec
hook,直接执行 refresh_env_var_from_systemd_started_tmux
是没有效果的,
因为执行的时候,DISPLAY 还是空的呢。
另外有一点不要误解的就是,set-option -g update-environment
这里的update是针对 tmux 进程自身的,
而不是通过 tmux 启动的 shell (比如 zsh).
还有一种比较笨的方法就是直接在 systemd unit 文件中指定这些环境变量的值,比如:
Environment=DISPLAY=:1
Environment=XAUTHORITY=/run/user/1000/gdm/Xauthority
为什么需要这个?有些程序(一般是x11 client)的运行是要依赖DISPLAY
这个环境变量的,比如 https://github.com/suxpert/vimcaps
这个vim插件, 里面有个c lib, 初始化的时候就会调用 XOpenDisplay
2. tmux.service user service 重启后被奇怪地禁用了⚓
这个其实是老灯装了一个叫 tmux-continuum
的tpm插件的锅。这个问题确实坑了我很久。
我怎么想到这一点的?我刚开始并没想到,并且重启了n次,折腾了好久,被这货害惨了。
后面我把 tmux.service
改成了 mytmux.service
发现问题神奇的消失了。
症状就是: systemctl --user enable tmux
后,明明服务成功运行了,检查 ~/.config/systemd/user/default.target.wants/tmux.service
也是存在的,说明确实成功enable
了。
一重启,发现~/.config/systemd/user/default.target.wants/tmux.service
已经消失了。服务自动是被禁用状态了。
tmux-continuum/scripts/variables.sh
中有定义: systemd_service_name="tmux.service"
然后这货在tmux启动时会执行 systemctl --user disable ${systemd_service_name}
见 tmux-continuum/scripts/handle_tmux_automatic_start.sh
is_tmux_automatic_start_enabled() {
local auto_start_value="$(get_tmux_option "$auto_start_option" "$auto_start_default")"
[ "$auto_start_value" == "on" ]
}
is_osx() {
[ $(uname) == "Darwin" ]
}
is_systemd() {
[ $(ps -o comm= -p1) == 'systemd' ]
}
main() {
if is_tmux_automatic_start_enabled; then
if is_osx; then
"$CURRENT_DIR/handle_tmux_automatic_start/osx_enable.sh"
elif is_systemd; then
"$CURRENT_DIR/handle_tmux_automatic_start/systemd_enable.sh"
fi
else
if is_osx; then
"$CURRENT_DIR/handle_tmux_automatic_start/osx_disable.sh"
elif is_systemd; then
"$CURRENT_DIR/handle_tmux_automatic_start/systemd_disable.sh"
fi
fi
}
main
默认配置是这样的:
auto_start_option="@continuum-boot"
auto_start_default="off"
所以每次重启后就执行了"$CURRENT_DIR/handle_tmux_automatic_start/systemd_disable.sh"
即 systemctl --user disable tmux.service
Refs⚓
https://github.com/tmux-plugins/tmux-resurrect
https://github.com/tmux-plugins/tmux-continuum
https://wiki.archlinux.org/index.php/tmux#Autostart_with_systemd
https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Specifiers
https://babushk.in/posts/renew-environment-tmux.html
https://goosebearingbashshell.github.io/2017/12/07/reset-display-variable-in-tmux.html
Recommend
-
149
Files Permalink Latest commit message
-
88
systemd can bring two features to a Go service: a readiness signal for other services and a watchdog timer.
-
58
Using systemd's socket activation, you can achieve zero-downtime deployment for your Go service with a few lines of code.
-
15
I ran into an issue while trying to setup a simple test system for myself to move from CentOS 6 to 7. When I was about to start a standby slave systemd reported PostgreSQL startup timeout and stopped it. Although it was running perfectly fine...
-
11
Aug 1, 2017 User=0day Considered Harmful In Systemd https://lwn.net/Articles/727490/ 在长期的安全实践中, 得到结论, 验证用户输入是很好的方法, 但是当验证失败的时候该做什么又有很多不同的意见. 最近在systemd上报的一个b...
-
8
正文 原文链接:https://www.cnblogs.com/yaohong/p/16046670.html,转载需经同意。 1.问题由来 近期发现堡垒机环境有如下问题,systemd占用大量cpu:
-
7
Systemd Service Not Starting (status=217/USER) A systemd service may fail to start with the error: Main process exited, code=exited, status=217/USER The status=217/US...
-
3
Example Systemd file for starting cloud sql proxy at system start · GitHub Instantly share code, notes, and snippets....
-
7
Configure a container to start automatically as a systemd service Use Podman and systemd integration to automatically start a co...
-
6
Instantly share code, notes, and snippets.
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK