【问题标题】:Emacs workflow to edit Bash scripts while they run运行时编辑 Bash 脚本的 Emacs 工作流程
【发布时间】:2012-01-10 06:25:18
【问题描述】:

Bash 可以给unexpected results if one edits a script while the script is running。但是,能够编辑我在 shell 中运行的脚本的临时副本通常非常方便,但在再次运行之前确保它回到原始位置。有人对 Emacs 的工作流程或自定义有什么建议吗?

【问题讨论】:

    标签: bash emacs


    【解决方案1】:

    我已经有了重命名当前缓冲区文件的功能。是对一个函数的短暂跳转,它可以轻松切换到文件的临时版本,然后再返回。基本上,如果您在访问普通文件“foo.txt”时运行此函数,它将将该文件复制到同一目录中名为“tmp.foo.txt”的新文件中。根据需要进行编辑。当准备好切换回来时,再次运行该函数,它将把临时文件移回原始文件。我使用了前缀“tmp”。而不是后缀,因为 emacs 中的大多数模式识别都是基于后缀的(您可能会做一些更有趣的事情来记住所有缓冲区模式并重新应用......)。

    (defun toggle-temp-file ()
      (interactive)
      (let* ((cur-buf (current-buffer))
             (cur-file (buffer-file-name cur-buf))
             (cur-file-dir (file-name-directory cur-file))
             (cur-file-name (file-name-nondirectory cur-file))
             new-file)
        (if (string-match "^tmp\\.\\(.+\\)\\'" cur-file-name)
            ;; temp file -> orig file
            (progn
              (setq new-file
                    (concat cur-file-dir (match-string 1 cur-file-name)))
              (rename-file cur-file new-file t))
          ;; orig file -> temp file
          (setq new-file (concat cur-file-dir "tmp." cur-file-name))
          (copy-file cur-file new-file nil nil t))
        (kill-buffer cur-buf)
        (find-file new-file)))
    

    【讨论】:

      【解决方案2】:

      M-x delete-file,按down插入获取正在编辑的文件的路径,按RET删除文件。当您下次保存缓冲区时,这将创建一个新文件。 Bash 将继续执行旧的、已删除的文件。

      顺便说一句,在大多数情况下,您甚至不需要采取这种预防措施。 Emacs 通常会保存到一个临时文件,然后将该临时文件重命名为正确的文件名(这会删除旧文件,除非它被保存为备份)。只有当 Emacs 检测到它不能正确地重新创建文件时,Emacs 才会覆盖原地文件:如果文件有硬链接,或者如果您对目录没有写权限。 (我简化了一点;详细信息在files.el 中的basic-save-buffer-2 函数中。)只要文件有一个目录条目并且您对包含脚本的目录具有写权限,只需按C-x C-s .

      【讨论】:

      • 听起来很简单。我需要仔细检查这是否真的有效。如果是这样,这是否意味着 Emacs 现有的保存和重命名行为会阻止这个问题的出现?
      • @MichaelHoffman 是的,如果 Emacs 正在执行保存和重命名(这是大多数情况下的默认行为),那么您根本不会遇到这个问题。请注意,我在这里假设一个真正的 unix,如果您在 Cygwin 之类的东西上运行 bash,您可能无法删除该文件(我不确定)。
      • 您能否编辑您的答案以包含此内容?似乎整个问题都是不必要的,因为 Emacs 开箱即用地做了正确的事情。
      • 如果 Emacs 的默认行为的描述在 2011 年是真的,那么它似乎变得更糟了(至少就这个问题而言,除非我错过了什么,这肯定是可能的)。 file-precious-flag 默认为 nil(但如果启用,可能会破坏硬链接)。仅当break-hardlink-on-save 不是nil(默认情况下不是)时才考虑数量 的硬链接。我没有看到任何意味着“永远不要破坏硬链接,但如果可能的话,写临时文件和重命名”的配置......
      • ...这可能会部分通过默认的backup-by-copying 设置 (nil) 得到缓解,因为 Emacs 会将原始文件重命名为备份,然后为原始文件名创建一个新文件;但是,这仅适用于实际发生备份的情况。
      【解决方案3】:

      [edit] best workaround 是在 shell 脚本端完成的,不是 在 Emacs 中。简而言之,_put all 在一个大括号中,并在右大括号之前放置“exit”。 仔细阅读链接的答案以避免陷阱。

      在这个回复中,我用理论补充了 Gilles 的回答。

      删除安全但修改不安全的原因是,在 Unix 中,已删除的文件无法从文件系统访问,但打开文件的进程(此处为 /bin/bash)仍然可以读取它,如解释here。这并不是说 bash 做了什么特别的事情,比如缓冲整个文件,但它只是读取。 (即使删除后,您也可以在脚本运行时恢复它,as explained here。在 bash 中,脚本似乎总是以 255 打开,/proc/<pid>/fd/255。)

      [编辑] 根据 OP 的要求,我的 old answer 包括 Emacs 解决方案和合作伙伴。但是经过多年的经验,我确信上面的指针是最好的,比任何其他尝试都好得多。)

      【讨论】:

        【解决方案4】:

        只需将此解决方案添加为保护正在运行的 BASH 脚本不被更改的简单而干净的方法:

        #! /bin/bash
        {
        your_code;
        exit;
        }
        

        【讨论】:

        • 在 teika kazura 的回答末尾也提到过,但我认为仍然可以方便地突出显示它。
        猜你喜欢
        • 2011-03-27
        • 2023-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-26
        • 1970-01-01
        • 2012-12-15
        • 2014-12-19
        相关资源
        最近更新 更多