Можем ли мы использовать временные папки, такие как временные файлы
TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP
cat <&3
который будет уничтожен автоматически после выхода из оболочки?
Можем ли мы использовать временные папки, такие как временные файлы
TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP
cat <&3
который будет уничтожен автоматически после выхода из оболочки?
Ответы:
В случае временного файла ваш пример в вопросе создаст его, затем отсоединит его от каталога (заставит его «исчезнуть»), а когда скрипт закроет дескриптор файла (возможно, по завершении), пространство, занимаемое файлом будет исправимо системой. Это распространенный способ работы с временными файлами на таких языках, как C.
Насколько я знаю, невозможно открыть каталог таким же образом, по крайней мере, никоим образом, который бы сделал каталог пригодным для использования.
Распространенным способом удаления временных файлов и каталогов при завершении сценария является установка EXITловушки очистки . Приведенные ниже примеры кода позволяют избежать необходимости полностью манипулировать дескрипторами файлов.
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap 'rm -f "$tmpfile"; rm -rf "$tmpdir"' EXIT
# The rest of the script goes here.
Или вы можете вызвать функцию очистки:
cleanup () {
rm -f "$tmpfile"
rm -rf "$tmpdir"
}
tmpdir=$(mktemp -d)
tmpfile=$(mktemp)
trap cleanup EXIT
# The rest of the script goes here.
EXITЛовушка не будет выполняться после приема KILLсигнала (который не может быть в ловушке), что означает , что не будет никакого очистки не выполняется тогда. Однако он будет выполняться при завершении из-за сигнала INTили TERM(при запуске с bashили ksh, в других оболочках вы можете добавить эти сигналы после EXITв trapкомандной строке) или при нормальном выходе из-за прибытия в конец сценария или выполнения exitвызов.
.и ..запись. (Протестировано на Linux, я не знаю, совместимо ли это на разных платформах.)
exec another-commandявно.
Напишите shell-функцию, которая будет выполнена, когда ваш скрипт завершит работу. В приведенном ниже примере я называю это «очистка» и устанавливаю ловушку для выполнения на уровнях выхода, например: 0 1 2 3 6
trap cleanup 0 1 2 3 6
cleanup()
{
[ -d $TMP ] && rm -rf $TMP
}
Смотрите этот пост для получения дополнительной информации.
cleanupперед чистым выходом (0) и при получении SIGHUP (1), SIGINT (2), SIGQUIT (3) и SIGABRT (6). он не будет работать cleanupпри выходе из сценария из-за SIGTERM, SIGSEGV, SIGKILL, SIGPIPE и т. д. Это явно недостаточно.
Вы можете зайти в него, а затем удалить его, при условии, что впоследствии вы не будете пытаться использовать пути внутри него:
#! /bin/sh
dir=`mktemp -d`
cd "$dir"
exec 4>file 3<file
rm -fr "$dir"
echo yes >&4 # OK
cat <&3 # OK
cat file # FAIL
echo yes > file # FAIL
Я не проверял, но это, скорее всего, та же проблема при использовании openat (2) в C с каталогом, который больше не существует в файловой системе.
Если вы root и в Linux, вы можете играть как с отдельным пространством имен, так и mount -t tmpfs tmpfs /dirвнутри него.
Канонические ответы (ставить ловушку на EXIT) не работают, если ваш скрипт принудительно завершает нечистый выход (например, с помощью SIGKILL); это может привести к зависанию конфиденциальных данных.
Обновить:
Вот небольшая утилита, которая реализует подход пространства имен. Это должно быть скомпилировано с
cc -Wall -Os -s chtmp.c -o chtmp
и данные CAP_SYS_ADMINвозможности файла (как root) с
setcap CAP_SYS_ADMIN+ep chtmp
Когда запускается (как обычный) пользователь как
./chtmp command args ...
он откроет пространство имен своей файловой системы, смонтирует файловую систему tmpfs /proc/sysvipc, вставит в нее chdir и запустит commandс заданными аргументами. неcommand будет наследовать возможности.CAP_SYS_ADMIN
Эта файловая система не будет доступна из другого процесса, из которого commandона не запущена , и она волшебным образом исчезнет (со всеми файлами, которые были созданы внутри нее), когда commandи ее дочерние элементы умрут, независимо от того, как это произойдет. Обратите внимание, что это просто отключение пространства имен монтирования - нет жестких барьеров между commandдругими процессами, выполняемыми одним и тем же пользователем; они все еще могут проникнуть в его пространство имен либо с помощью ptrace(2), /proc/PID/cwdлибо другими способами.
Похищение «бесполезных» /proc/sysvipc, конечно, глупо, но альтернативой было бы спам /tmpс пустыми каталогами, которые пришлось бы удалить, или сильно усложнило бы эту маленькую программу с форками и ожиданиями. В качестве альтернативы dirможно изменить, например, на. /mnt/chtmpи создать его с правами root при установке; не делайте его настраиваемым пользователем и не устанавливайте его по пути, принадлежащему пользователю, поскольку это может подвергнуть вас ловушкам символической ссылки и другим опасным вещам, на которые не стоит тратить время.
chtmp.c
#define _GNU_SOURCE
#include <err.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mount.h>
int main(int argc, char **argv){
char *dir = "/proc/sysvipc"; /* LOL */
if(argc < 2 || !argv[1]) errx(1, "usage: %s prog args ...", *argv);
argv++;
if(unshare(CLONE_NEWNS)) err(1, "unshare(CLONE_NEWNS)");
/* "modern" systemd remounts all mount points MS_SHARED
see the NOTES in mount_namespaces(7); YUCK */
if(mount("none", "/", 0, MS_REC|MS_PRIVATE, 0))
err(1, "mount(/, MS_REC|MS_PRIVATE)");
if(mount("tmpfs", dir, "tmpfs", 0, 0)) err(1, "mount(tmpfs, %s)", dir);
if(chdir(dir)) err(1, "chdir %s", dir);
execvp(*argv, argv);
err(1, "execvp %s", *argv);
}
rm $PWDработа, оболочка еще в этом каталоге. Но никакие новые файлы не могут быть помещены в эту «папку». Только вы можете читать / писать с файлами & 3, & 4. Так что это все еще «временный файл», а не «временная папка».
Вам требуется определенная оболочка?
Если Zsh вариант, пожалуйста, прочитайте zshexpn(1):
Если вместо <(...) используется = (...), то файл, переданный в качестве аргумента, будет именем временного файла, содержащего выходные данные процесса списка. Это может использоваться вместо формы <для программы, которая ожидает
lseek(см.lseek(2)) Во входном файле.[...]
Другая проблема возникает всякий раз, когда работа с заменой, для которой требуется временный файл, закрывается оболочкой, включая случай, когда
&!или&|появляется в конце команды, содержащей подстановку. В этом случае временный файл не будет очищен, поскольку у оболочки больше нет памяти для задания. Обходной путь должен использовать подоболочку, например,(mycmd =(myoutput)) &!поскольку раздвоенный подоболочек будет ждать завершения команды, затем удалите временный файл.
Общий обходной путь, гарантирующий, что подстановка процесса длится в течение соответствующего промежутка времени, заключается в передаче его в качестве параметра анонимной функции оболочки (фрагмент кода оболочки, который запускается сразу с областью действия функции). Например, этот код:
() { print File $1: cat $1 } =(print This be the verse)выводит что-то похожее на следующее
File /tmp/zsh6nU0kS: This be the verse
Например, я использую это в винтовке (часть файлового менеджера рейнджера) для расшифровки файла, а затем запускаю винтовку для временного файла, который удаляется после завершения подпроцессов. (не забудьте установить $TERMCMD)
# ~/.config/ranger/rifle.conf
...
!ext exe, mime octet-stream$, has gpg, flag t = () { rifle -f F "$1" } =(gpg -dq "$1")