You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Vim调用脚本启动Zathura显示空文件的问题排查

问题描述

我编写了名为md的shell脚本:

#!/bin/sh
if [ -z $1 ]; then
    echo "Error: No argument supplied"
else
    (pandoc -t pdf $1 | zathura - &)
fi

该脚本在终端运行正常,执行md foo.md可通过Zathura打开生成的PDF。但在Vim的init.vim中添加自定义命令command Md ! md %:p后,执行:Md时Zathura虽启动却显示空文件(底部标注"[No name]")。直接复制Vim输出的命令到终端执行,Zathura却能正常显示文件。请问该问题的原因是什么?


原因分析

核心问题出在Vim对外部命令I/O流的管理逻辑:
当你在Vim里执行:Md时,Vim会启动md脚本作为自己的子进程,并且会接管这个子进程的所有I/O资源。你的脚本里用了(pandoc -t pdf $1 | zathura - &),把pandoc的输出通过管道传给后台运行的zathura,但脚本本身执行完就会立即退出——此时Vim会直接关闭该子进程关联的所有文件描述符,包括pandoc输出到zathura的管道。

zathura还没来得及完整读取pandoc生成的PDF数据,管道就被切断了,自然只能显示空文件。而在终端直接执行脚本时,后台进程的I/O流和终端会话绑定,脚本退出后管道不会被立即关闭,pandoc可以把完整的PDF数据传给zathura,所以能正常显示。


解决方案

方案1:用临时文件替代管道

避开管道被提前关闭的问题,先让pandoc生成临时PDF文件,再用zathura打开:

#!/bin/sh
if [ -z "$1" ]; then
    echo "Error: No argument supplied" >&2
else
    temp_pdf=$(mktemp --suffix=.pdf)
    pandoc -t pdf "$1" -o "$temp_pdf" && zathura "$temp_pdf" &
    # 可选:zathura退出后自动删除临时文件
    trap 'rm -f "$temp_pdf"' EXIT
fi

方案2:让进程脱离Vim的I/O控制

用nohup让zathura完全脱离当前会话的I/O绑定,避免Vim关闭管道:

#!/bin/sh
if [ -z "$1" ]; then
    echo "Error: No argument supplied" >&2
else
    nohup sh -c 'pandoc -t pdf "$1" | zathura -' "$0" "$1" >/dev/null 2>&1 &
fi

方案3:修改Vim命令

让Vim把外部命令放到后台执行,不等待其结束,这样不会过早关闭I/O流:

command Md ! md %:p &

内容的提问来源于stack exchange,提问作者Peatherfed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 09:45:03