Linux后台作业恢复时如何自动切换回原工作目录


阅读 12 次

问题场景还原

在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会话需要额外处理
  • 建议配合screentmux使用效果更佳