Bash può dare unexpected results if one edits a script while the script is running. Ma sarebbe spesso molto comodo poter modificare una copia temporanea di uno script che eseguo all'interno di una shell, ma assicurati che sia tornato nella posizione originale prima di eseguirlo di nuovo. Qualcuno ha suggerimenti per un flusso di lavoro o personalizzazioni per Emacs per facilitare questo?Flusso di lavoro di Emacs per modificare gli script di Bash mentre vengono eseguiti
risposta
M-x delete-file
, premere per inserire down
ottenere il percorso del file che si sta modificando, e RET
per eliminare il file. Al prossimo salvataggio del buffer, verrà creato un nuovo file. Bash manterrà in esecuzione il vecchio file cancellato.
A proposito, nella maggior parte dei casi, non è nemmeno necessario prendere questa precauzione. Emacs di solito salva in un file temporaneo, quindi rinomina quel file temporaneo con il nome file corretto (che cancella il vecchio file, a meno che non venga tenuto come backup). Emacs sovrascrive il file solo se rileva che non è in grado di ricreare correttamente il file: se il file ha collegamenti fisici o se non si dispone dell'autorizzazione alla scrittura nella directory. (Sto semplificando un po ', i dettagli sono nella funzione basic-save-buffer-2
in files.el
.) Finché il file ha una singola voce di directory e si dispone delle autorizzazioni di scrittura nella directory contenente lo script, è sufficiente premere C-x C-s
.
ho già avuto una funzione per rinominare il file del buffer corrente. era un breve salto a una funzione che rendeva facile passare a una versione temporanea di un file e quindi tornare di nuovo. in sostanza, se si esegue questa funzione quando si visita un file normale "foo.txt", verrà copiato il file in un nuovo file nella stessa dir con il nome "tmp.foo.txt". modifica come desiderato. quando sei pronto a tornare indietro, esegui di nuovo la funzione e il file temporaneo si sposterà sul file originale. ho usato il prefisso "tmp". invece di un suffisso perché la maggior parte del riconoscimento di modalità in emacs si basa sul suffisso (probabilmente potresti fare qualcosa di più divertente ricordando tutte le modalità del buffer e applicando nuovamente ...).
(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)))
In questa risposta, ho
- supplemento la bella risposta di Gilles con la teoria.
- suggeriscono un miglioramento nell'utilizzo di emacs.
- suggerire alternative, esclusivamente tramite script di shell.
Attenzione: non sono un programmatore professionista.
1 Teoria
Il motivo eliminazione è sicuro, ma la modifica non è che in Unix, un file cancellato ottiene inaccessibili dal file system, ma i processi che avevano aperto il file (qui,/bin/bash) può ancora leggerlo, come spiegato here. Non è che bash faccia qualcosa di speciale, come il buffering dell'intero file, ma semplicemente legge. (Anche dopo l'eliminazione, è possibile recuperare lo script mentre è in esecuzione, as explained here In bash, lo script sembra essere sempre aperto come 255, /proc/<pid>/fd/255
..) Soluzione
2 Emacs
Ora emacs; per sicurezza, puoi automatizzare tutto; aggiungi ai before-save-hook
una funzione per controllare se è sh-mode, ed eliminare automaticamente se lo script è aperta, controllando con 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)
Ma questo non è perfetto. Salva la modalità file, ma questo è tutto.
3 soluzione bash pura
In alternativa, è possibile lasciare che lo script bash per sé fare l'eliminazione. Utilizzare questa:
# 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
Esempio di utilizzo: salvare il file in /home/foo/a.sh:
#!/bin/sh
echo "$0 [email protected]"
. /home/foo/the-above-code.sh
echo "Again, $0 [email protected]"
Se si richiama lo script di cui sopra come ./a.sh 1 2 3
, il risultato è:
/home/foo/a.sh 1 2 3
/tmp/.sh-tmp/a.sh 1 2 3
Again, /tmp/.sh-tmp/a.sh 1 2 3
Questo potrebbe essere il migliore, ma utilizzare a proprio rischio.
È anche noto che mettere tutto in una parentesi, concludendo con exit
fa il lavoro, come spiegato here.
Solo l'aggiunta di questa soluzione come un modo semplice e pulito per proteggere l'esecuzione di script BASH venga modificata:
#! /bin/bash
{
your_code;
exit;
}
Menzionato anche alla fine della risposta di teika kazura, ma comunque utile per evidenziarlo, penso. – phils
- 1. Gli script 'prebuild' in project.json non vengono eseguiti
- 2. Traccia di programmi eseguiti chiamati da script bash
- 3. Gli elementi di lavoro OpenCL sono eseguiti in parallelo?
- 4. Gli script di shell in Mac OS X vengono eseguiti dalla home directory?
- 5. Flusso di lavoro Sharepoint vs Flusso di lavoro Windows
- 6. Motivo di progettazione per flusso di lavoro
- 7. script bash per modificare file xml
- 8. Perché gli script della fase di compilazione non vengono eseguiti durante la creazione di un IPA dalla riga di comando?
- 9. pitone: Modificare gli script directory di lavoro alla propria directory dello script
- 10. Flusso di lavoro con Symfony2?
- 11. Flusso di lavoro di sviluppo Docker
- 12. Miglior flusso di lavoro PHP
- 13. Come creare una GUI per gli script di bash?
- 14. Flusso di lavoro mercuriale per piccola squadra
- 15. Flusso di lavoro Github per singolo sviluppatore
- 16. Flusso di lavoro DDL transazionale per MySQL
- 17. Flusso di lavoro di sviluppo Scala (IDE)
- 18. Java: creazione di un flusso di lavoro in quarzo
- 19. Flusso di lavoro NodeJS + CoffeeScript
- 20. Flusso di lavoro Git + Drupal
- 21. Gli script non vengono chiamati
- 22. Flusso di lavoro sottomoduli Git
- 23. F # Flusso di lavoro asincrono
- 24. Creazione di lavori in corso e lavoro modificato per rilevare quando gli elementi vengono modificati
- 25. Flusso di lavoro XAML Intellisense VS 2010
- 26. Flusso di lavoro mercuriale per gli sviluppatori ~ 15 - Dovremmo utilizzare le filiali denominate?
- 27. compilatori per gli script di shell
- 28. Controllo flusso di lavoro scheda per repository Mercurial
- 29. Flusso di lavoro ottimale per l'aggiornamento dell'applicazione playframework in produzione
- 30. Gli script vengono eliminati con jQuery .load
Che suona davvero semplice. Devo controllare che funzioni effettivamente. In tal caso, vuol dire che l'attuale comportamento di salvataggio e ridenominazione di Emacs manterrà questo problema fuoriuscito? –
@MichaelHoffman Sì, se Emacs sta facendo save-and-rename (che è il comportamento predefinito nella maggior parte dei casi), allora non avrai affatto questo problema. Nota che sto assumendo un vero unix qui, se stai usando bash su qualcosa come Cygwin potresti non essere in grado di rimuovere il file (non ne sono sicuro). – Gilles
Puoi modificare la tua risposta per includerla? Sembra che l'intera domanda non sia necessaria, perché Emacs fa la cosa giusta fuori dagli schemi. –