epipe 的实现原理是什么?

发布于 2023-01-27 03:27:10 字数 2177 浏览 133 评论 0

最近发现一个好玩的脚本,可以在管道中调用外部编辑器来编辑内容:https://github.com/cute-jumper/epipe5

它的实现方式只有寥寥数行:

#$!/usr/bin/env bash  -*- mode: sh; -*-
tty="/dev/$(ps -o tty= -p $$)"
temp_file=$(mktemp)
default_editor="emacs"
[ ! -t 0 ] && cat > $temp_file
${EDITOR:-${VISUAL:-$default_editor}} $temp_file <$tty >$tty && cat $temp_file
rm $temp_file

然而就这么几行的脚本,我却发现看不懂!

主要有三点:

  1.  [ ! -t 0 ] 是什么意思
  2. 用编辑器来编辑临时文件时为什么要重定向 stdio 呢?
  3. 为什么重定向的时候不直接重定向到 /dev/tty 而要显示的获取编辑器实际的 tty 呢?

在经过与大伙的讨论后,最终引来原作者的解释,才最终恍然大悟,现在把讨论的结果整理如下(其中大量引用了讨论时的原文):

首先第一个问题其实很简单,-t fd 用来检查 fd 是否是是表示tty设备的文件描述符,所以这句话就是确保只有在该脚本的stdin被管道连接后才用cat从管道中读出内容放到临时文件中。

第二个问题,为什么要重定向编辑器的 stdio 呢?这个问题可以通过几个实验来解答。

  1. Vim 要求 stdout 必须是 terminal

     ~ $ ( vim tmp && cat tmp ) | nl 
    Vim: Warning: Output is not to a terminal
    

    解决方案是将stdout重定向到terminal

    ~ $ tty=`tty`
    ~ $ ( 1>$tty vim tmp && cat tmp ) | nl
    
  2. Vim 要求 stdin 也必须是 terminal

    ~ $ pwd | ( vim tmp && cat tmp )
    Vim: Warning: Input is not from a terminal
    

    解决方案是将stdin重定向到terminal

    ~ $ pwd | ( 0<$tty vim tmp && cat tmp )
    

也就是说,至少对于某些编辑器而言,是要求 stdio 必须为 terminal 的。

那么为什么不能直接重定向到 /dev/tty 呢? 毕竟即使 stdin 和 stdout 被重定向过了,/dev/tty 仍然还是指向原来的 terminal (严格地说,/dev/tty 是当前 process 的 terminal),这也是 找回 原有的标准输入输出的一种很普遍的做法啊。

对于大部分情况来说,这样是没问题的,比如 Vim,Emacs。但是对于 emacsclient,这样却行不通,这实际上与 emacsclient 的实现有关.

查看 emacsclient.c,能看见里面会根据当前的 stdout 来获取 ttyname:

ttyname(fileno(stdout))

emacsclient 将当前的 ttyname 发送给 server后。如果此时 stdout 是 /dev/tty 的话 ,这时候发送的就是 /dev/tty,然而 /dev/tty 对于 client 和 server 来说,含义是不一样的(他们不在同一个 terminal)。发送到 server 后,server 会以为是 server 本身的 process 所在的 tty,而这个 tty 和 client 所在的 tty 不一样,这就会导致无法创建 client 的 frame。

解决方案是:显式获得 emacsclient 实际的 tty,然后将 stdout 设成该 tty,而不是发送类似别名一样的 /dev/tty,这也就是第一行的作用。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

慕烟庭风

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文