В этом ответе я
- дополняю хороший ответ Жиля теорией.
- предлагаю улучшение в использовании emacs.
- предлагаю альтернативы, чистос помощью сценариев оболочки.
Предупреждение: я не профессиональный программист.
1 Теория
Причина удаления безопасна, но модификация заключается не в том, что в Unixудаленный файл становится недоступным из файловой системы, но процессы, открывшие файл (здесь / bin / bash), все равно могут его прочитать, как объяснено здесь .Дело не в том, что bash делает что-то особенное, например, буферизацию всего файла, а просто читает.(Даже после удаления вы можете восстановить сценарий во время его работы, , как описано здесь . В 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 "$@"
else
rm "$0"
fi
Пример использования: сохраните этот файл в /home/foo/a.sh:
#!/bin/sh
echo "$0 $@"
. /home/foo/the-above-code.sh
echo "Again, $0 $@"
Если вы вызовете вышеуказанный скрипт как ./a.sh 1 2 3
, результатэто:
/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
, делает работу, какобъяснил здесь .