Bash可以給unexpected results if one edits a script while the script is running。但能夠編輯我在shell中運行的腳本的臨時副本通常會非常方便,但在我再次運行它之前,請確保它已回到原始位置。有沒有人對Emacs的工作流程或定製有任何建議以促進這一點?Emacs工作流程在運行時編輯Bash腳本
回答
M-x delete-file
,按down
插入獲得的路徑,你正在編輯的文件,並RET
刪除該文件。當你下一次保存你的緩衝區時,這將創建一個新文件。 Bash將繼續執行舊的已刪除文件。
順便說一句,在大多數情況下,你甚至不需要採取這種預防措施。 Emacs通常保存到一個臨時文件,然後將該臨時文件重命名爲正確的文件名(刪除舊文件,除非它保留爲備份)。如果Emacs檢測到文件無法正確重新創建文件:如果該文件具有硬鏈接,或者您沒有該目錄的寫入權限,則Emacs只會覆蓋該文件。 (我正在簡化一些;細節位於files.el
的basic-save-buffer-2
函數中。)只要文件具有單個目錄條目,並且您對包含該腳本的目錄具有寫入權限,只需按C-x C-s
即可。
我已經有了重命名當前緩衝區文件的功能。是一個短暫的跳轉到一個功能,它可以很容易地切換到臨時版本的文件,然後再回來。基本上,如果您在訪問普通文件「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)))
在這個答覆,我
- 補充由吉爾漂亮的答案與理論。
- 提示emacs使用方面的改進。
- 純粹通過shell腳本來建議替代方案。
警告:我不是一個專業程序員。
1理論
缺失的原因是安全的,但改變並非是在Unix中,已刪除的文件變得不可訪問從文件系統,但已經打開的文件的過程(在這裏,/斌/慶典)仍然可以讀取它,如解釋here。並不是說bash做了一些特殊的事情,比如緩衝整個文件,但它只是讀取。 (即使刪除後,你可以在它的運行恢復腳本,as explained here在bash,腳本似乎總是被開闢爲255,/proc/<pid>/fd/255
。)
2個Emacs的解決方案
現在emacs的;爲了安全起見,你可以自動化所有;添加到before-save-hook
一個函數來檢查它是否是SH-模式,如果腳本是打開自動刪除,用lsof
檢查:
(defvar delete-open-sh-flag nil
"Used by `delete-open-sh.` If nil, deletion didn't happen.
Otherwise, the mode is saved.")
(defun delete-open-sh()
(setq delete-open-sh-flag nil)
(when (and (eq major-mode 'sh-mode)
(buffer-file-name)
(file-exists-p (buffer-file-name)))
(let ((buf (generate-new-buffer " *foo*")))
(call-process "lsof" nil; infile
buf ; dest
nil ; display
(buffer-file-name))
(unless (eq 0 (buffer-size buf))
(setq delete-open-sh-flag (file-modes (buffer-file-name)))
(delete-file (buffer-file-name)))
(kill-buffer buf))))
(defun delete-open-sh-after()
(when delete-open-sh-flag
(set-file-modes (buffer-file-name) delete-open-sh-flag)))
(add-hook 'before-save-hook 'delete-open-sh)
(add-hook 'after-save-hook 'delete-open-sh-after)
但這是不完美的。它保存了文件模式,但僅此而已。
3純bash的解決方案
或者,你可以讓bash腳本本身做刪除。使用此:
# Usage: . /path/to/this-script (Always use abs path)
# Restart the caller script itself in a temporary file; this allows
# editing of the caller script file while it's run.
# Temporary file is soon deleted.
#
if [[ ! "`dirname $0`" =~ ^/tmp/.sh-tmp ]]; then
mkdir -p /tmp/.sh-tmp/
DIST="/tmp/.sh-tmp/$(basename $0)"
install -m 700 "$0" $DIST
exec $DIST "[email protected]"
else
rm "$0"
fi
用例:保存/home/foo/a.sh此文件:如果你調用上面的腳本爲./a.sh 1 2 3
#!/bin/sh
echo "$0 [email protected]"
. /home/foo/the-above-code.sh
echo "Again, $0 [email protected]"
,結果是:
/home/foo/a.sh 1 2 3
/tmp/.sh-tmp/a.sh 1 2 3
Again, /tmp/.sh-tmp/a.sh 1 2 3
這可能是最好的,但使用風險自負。
這也是衆所周知的,把所有的大括號,最後exit
做的工作,如解釋here。
剛剛添加該解決方案,以保護被更改運行BASH腳本一個簡單而乾淨的方式:
#! /bin/bash
{
your_code;
exit;
}
在teika kazura的回答結束時也提到了,但仍然很方便地突出它我認爲。 – phils
- 1. npm運行腳本流程不工作
- 2. 工作流程4運行時編譯
- 3. 當在終端外運行時,Bash腳本不工作
- 4. 如何在工作時間持續運行bash腳本?
- 5. 編輯工作流程
- 6. 在運行時顯示工作流程
- 7. Bash腳本:按行編輯.txt
- 8. bash腳本和編輯CSV
- 9. 如何在運行不同程序時運行bash腳本?
- 10. 自動運行時Bash腳本無法正常工作
- 11. 主動設置 - 腳本編輯文件沒有運行/工作
- 12. 在Python中運行遠程Bash腳本
- 13. 在bash腳本上做一個完整的工作流程
- 14. CurrentWorkItem.ID在工作流腳本編輯器中是否正確?
- 15. 在bash中運行腳本
- 16. bash腳本來編譯和運行C++
- 17. 在bash腳本中編輯html/css
- 18. ASP.NET中的運行時工作流程
- 19. 並行運行bash腳本?
- 20. 並行運行bash腳本
- 21. 在Heroku中以編程方式運行bash腳本文件
- 22. 運行bash腳本時出現邏輯錯誤
- 23. 當我在腳本運行時編輯腳本時會發生什麼?
- 24. 編寫運行cygwin bash並執行程序的shell腳本
- 25. 什麼是有效的C工作流程? - Makefile + bash腳本
- 26. cron作業沒有運行bash腳本
- 27. 運行bash腳本作爲守護
- 28. python結構運行遠程bash腳本
- 29. Ubuntu:sshpass運行遠程bash腳本
- 30. bash腳本來檢查運行進程
這聽起來很簡單。我需要仔細檢查一下,確實有效。如果是這樣,這是否意味着Emacs現有的保存和重命名行爲會阻止此問題出現? –
@MichaelHoffman是的,如果Emacs正在進行保存和重命名(這是大多數情況下的默認行爲),那麼您根本就不會有這個問題。請注意,我假設這裏是一個真正的unix,如果你正在對Cygwin這樣的東西運行bash,那麼你可能無法刪除這個文件(我對此不確定)。 – Gilles
你可以編輯你的答案,包括這個?看起來整個問題是不必要的,因爲Emacs開箱即可做出正確的事情。 –