Временная папка, которая автоматически уничтожается после выхода из процесса

Я бы использовал функцию оболочки:

composer() {
    php "$PWD"/composer.phar "$@"
}
10
07.11.2018, 12:44
3 ответа

Напишите функцию оболочки -, которая будет выполняться, когда ваш скрипт завершится. В приведенном ниже примере я называю это «очисткой» и устанавливаю ловушку, которая будет выполняться на уровнях выхода, например :0 1 2 3 6

trap cleanup 0 1 2 3 6

cleanup()
{
  [ -d $TMP ] && rm -rf $TMP
}

Дополнительную информацию см. в этом сообщении.

4
27.01.2020, 20:00

В случае временного файла ваш пример в вопросе создаст его, затем отсоединит от каталога (, сделав его «исчезнувшим» ), и когда скрипт закроет файловый дескриптор (, вероятно, после завершение ), пространство, занимаемое файлом, может быть освобождено системой. Это распространенный способ работы с временными файлами в таких языках, как 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.

13
27.01.2020, 20:00

Вы можете войти в него, а затем удалить его, при условии, что вы не пытаетесь впоследствии использовать пути внутри него:

#! /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внутри него.

Канонические ответы (устанавливают ловушку на ВЫХОД )не работают, если ваш скрипт вынужден выполнить нечистый выход (например. с 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, подключится к ней и запустит commandс заданными аргументами. commandне не унаследует возможности CAP_SYS_ADMIN.

Эта файловая система не будет доступна из другого процесса, не запущенного из command, и она волшебным образом исчезнет (со всеми файлами, которые были созданы в ней ), когда commandи ее дочерние элементы умрут, независимо от того, как это происходит. Обратите внимание, что это просто удаление пространства имен монтирования --. Между commandи другими процессами, запущенными тем же пользователем, нет жестких барьеров; они все еще могли проникнуть внутрь его пространства имен либо через ptrace(2), /proc/PID/cwd, либо другими способами.

Захват "бесполезного" /proc/sysvipc- это, конечно, глупо, но альтернативой был бы спам /tmpпустыми каталогами, которые пришлось бы удалить или сильно усложнить эту маленькую программу форками и ожиданиями. В качестве альтернативы dirможно изменить, например, на. /mnt/chtmpи создать его пользователем root при установке; не делайте его настраиваемым пользователем -и не устанавливайте его на принадлежащий пользователю -путь, так как это может подвергнуть вас ловушкам символических ссылок и другим волосатым вещам, на которые не стоит тратить время.

чтмп.с

#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);
}
7
27.01.2020, 20:00

Теги

Похожие вопросы