问题场景还原
在Linux终端开发时经常遇到这种情况:
# 1. 在项目目录工作
cd ~/projects/myapp
vim src/main.py
# 2. 按Ctrl+z挂起vim
# 3. 临时切换到其他目录
cd /tmp
# 4. 尝试恢复之前的vim作业
fg
此时虽然vim恢复了,但当前工作目录仍停留在/tmp,需要手动cd
回原目录,这在频繁切换时非常影响效率。
Shell作业控制原理
Linux的作业控制(job control)通过以下机制实现:
jobs
命令显示后台作业列表- 每个作业会记录启动时的进程组ID(PGID)
- 但默认不保存工作目录上下文
Zsh的解决方案
对于使用Zsh的用户,内置的dirpersist
插件可以完美解决:
# 在.zshrc中添加
plugins=(... dirpersist)
# 使用示例
% cd ~/projects
% vim test.txt
% Ctrl+z
% cd /tmp
% fg # 自动切换回~/projects
Bash的实现方案
通过重写cd
命令和作业控制命令实现:
# 在.bashrc中添加
function cd {
builtin cd "$@" && echo "$PWD" > ~/.last_dir
}
function fg {
if [ -f ~/.last_dir ]; then
builtin cd "$(cat ~/.last_dir)" 2>/dev/null
fi
builtin fg "$@"
}
function bg {
if [ -f ~/.last_dir ]; then
builtin cd "$(cat ~/.last_dir)" 2>/dev/null
fi
builtin bg "$@"
}
进阶方案:完整目录堆栈
更完善的方案可以维护目录堆栈:
# 记录所有目录历史
function _persist_dir {
echo "$PWD" >> ~/.dir_stack
tail -n 100 ~/.dir_stack > ~/.dir_stack.tmp
mv ~/.dir_stack.tmp ~/.dir_stack
}
function fg {
local last_dir=$(tail -n 1 ~/.dir_stack)
if [ -d "$last_dir" ]; then
builtin cd "$last_dir"
fi
builtin fg "$@"
}
# 在PS1提示符前自动记录
PROMPT_COMMAND="_persist_dir;$PROMPT_COMMAND"
注意事项
- 多终端会话时可能产生冲突
- 远程SSH会话需要额外处理
- 建议配合
screen
或tmux
使用效果更佳