Vim: Warning: input is not from a terminal 后退出 vim 终端异常

Vim: Warning: input is not from a terminal 后退出 vim 终端异常

今天执行了如下命令调用 vi 来打开 find 搜索到的文件:

longyu@longyu-pc:~$ find ./ -name 'linux-kernel-ixgbe-commit-log'  | xargs vi 

执行了上述命令之后,Vim 打印了下面的警告信息:

Vim: Warning: Input is not from a terminal

没理会这个警告,退出 vim 后,发现终端异常,输入的字符不能正常显示,按 enter 换行也不正确。
具体的现象如下:

longyu@longyu-pc:~$ longyu@longyu-pc:~$ longyu@longyu-pc:~$ longyu@longyu-pc:~$ 

问题分析

出了问题之后,之前提到的那个警告需要重视一下。在网上搜索,发现了如下链接:

invoking vi through find xargs breaks my terminal Why

通过阅读上述链接上的问题,我发现这个问题是 xargs 将 stdin 映射为 /dev/null 导致的。按照上述链接中的回答,我在终端中执行如下命令:

	true | xargs filan -s 

执行后报 filan 命令找不到的错误。直接 sudo apt-get install filan没有找到相关包,搜索发现 filan 是在 socat 包中包含的命令。执行 sudo apt-get install socat命令之后,filan 命令可以使用了。

filan -h了解到 filan 命令是用来分析进程的文件描述符信息的程序。再次执行 true | xargs filan -s
命令,有如下输出信息:

longyu@longyu-pc:~$ true | xargs filan -s
    0 chrdev /dev/null
    1 tty /dev/pts/3
    2 tty /dev/pts/3
    3 unixdatagram <anon>
    4 unixdatagram <anon>

从上面的输出中可以确定 xargs 程序将 stdin 映射到了 /dev/null 上。进一步的了解发现 xargs 支持 -o 选项,可以在执行子进程命令之前重新将 stdin 映射到 /dev/tty 上,这个功能可以用在使用 xargs 调用交互式程序的情况下。

man xargs 中相关的内容如下:

  -o, --open-tty
              Reopen  stdin as /dev/tty in the child process before executing the command.  This is useful if you want xargs to run an interactive appli‐
              cation.

指定 -o 参数再次执行 filan -s 命令,有如下输出:

longyu@longyu-pc:~$ true | xargs -o filan -s
    0 tty /dev/tty
    1 tty /dev/pts/3
    2 tty /dev/pts/3
    3 unixdatagram <anon>
    4 unixdatagram <anon>

从上面的输出中可以确定,stdin 被映射到了 /dev/tty 上。

如何将终端恢复正常

最开始,我直接关闭终端,然后重新开了一个新的终端就解决了问题。其实我可以通过执行 stty sane命令来将终端恢复正常。(注意输入命令并不回显)

man stty 发现 sane 选项会将所有特殊字符恢复默认值,这与正常工作过程中终端的特殊字符配置可能不相同。在我系统中,正常的终端特殊字符配置如下:

longyu@longyu-pc:~$ stty
speed 38400 baud; line = 0;
-brkint -imaxbel

直接使用 xargs 调用一次 vi 然后通过执行 stty sane 来恢复默认终端配置,这之后的特殊字符配置信息如下:

longyu@longyu-pc:~$ stty
speed 0 baud; line = 0;

通过对比可以发现,调用 stty sane 之后,一些终端配置失效了。

最终的解决方案

不要通过 xargs 直接调用交互式程序。非要通过 xargs 来调用交互式程序的话,指定 xargs 的 -o 参数在调用交互式命令执行前将 stdin 重新映射为 /dev/tty。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值