임시 파일과 같은 임시 폴더를 사용할 수 있습니까?
TMP=$(mktemp ... )
exec 3<>$TMP
rm $TMP
cat <&3
쉘이 종료된 후 자동으로 파괴되는 것은 무엇입니까?
답변1
임시 파일의 경우 질문의 예제에서는 임시 파일을 생성한 다음 디렉터리의 링크를 해제하고("사라지게" 설정) 스크립트가 파일 설명자를 닫을 때(아마도 종료 시) 시스템이 파일이 차지한 공간을 회수합니다. 이는 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
답변2
나중에 해당 경로를 사용하지 않는 경우 해당 경로에 chdir을 추가한 다음 삭제할 수 있습니다.
#! /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
확인하지는 않았지만 파일 시스템에 더 이상 존재하지 않는 디렉토리를 사용하여 C에서 openat(2)를 사용할 때에도 동일한 문제가 발생할 가능성이 높습니다.
Linux의 루트인 경우 별도의 네임스페이스를 사용하고 mount -t tmpfs tmpfs /dir
그 안에서 작업할 수 있습니다.
스크립트가 비정상 종료(예: SIGKILL 사용)로 강제 종료되면 표준 답변(EXIT에 트랩 설정)이 작동하지 않습니다. 이로 인해 민감한 데이터가 남을 수 있습니다.
고쳐 쓰다:
이것은 네임스페이스 메소드를 구현하는 작은 유틸리티입니다. 다음과 같이 컴파일해야 합니다.
cc -Wall -Os -s chtmp.c -o chtmp
및 주어진 CAP_SYS_ADMIN
파일 기능(루트로서)
setcap CAP_SYS_ADMIN+ep chtmp
(일반) 사용자로 실행할 때
./chtmp command args ...
파일 시스템 네임스페이스를 공유 해제하고 tmpfs 파일 시스템을 여기에 마운트한 다음 chdir을 지정하고 주어진 인수로 실행합니다 /proc/sysvipc
. ~ 할 것이다command
command
아니요상속된 CAP_SYS_ADMIN
능력.
파일 시스템은 시작되지 않은 다른 프로세스에서 액세스할 수 없으며 , 무슨 일이 일어나더라도 command
하위 프로세스가 종료되면 마법처럼 사라집니다(그 안에 생성된 모든 파일과 함께) . command
이는 마운트 네임스페이스만 공유 해제한다는 점에 유의하십시오. command
동일한 사용자가 실행하는 다른 프로세스 사이에는 여전히 다른 방법을 통해 해당 네임스페이스에 몰래 들어갈 수 ptrace(2)
있습니다 /proc/PID/cwd
.
"쓸모없는" 하이재킹은 /proc/sysvipc
물론 어리석은 일이지만, 대안은 /tmp
삭제해야 하는 빈 디렉토리로 스팸을 보내거나 분기 및 대기를 통해 이 작은 프로그램을 매우 복잡하게 만드는 것입니다. 또는 dir
다음과 같이 변경할 수 있습니다. /mnt/chtmp
그리고 설치할 때 루트로 생성하십시오. 사용자가 구성할 수 있도록 만들지 말고 사용자 소유 경로로 설정하지 마십시오. 그렇게 하면 심볼릭 링크 트랩 및 시간을 들일 가치가 없는 기타 문제가 발생할 수 있습니다.
chmp.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);
}
답변3
스크립트가 완료되면 실행될 쉘 함수를 작성하십시오. 아래 예에서는 "Clean"이라고 부르고 종료 수준에서 실행되도록 트랩을 설정합니다. 예: 0 1 2 3 6
trap cleanup 0 1 2 3 6
cleanup()
{
[ -d $TMP ] && rm -rf $TMP
}
바라보다이것자세한 내용은 게시하세요.
답변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
예를 들어, 나는 소총(Ranger 파일 관리자의 일부)에서 이것을 사용하여 파일을 해독한 다음 하위 프로세스가 종료될 때 삭제되는 임시 파일에서 소총을 실행합니다. (설정하는 것을 잊지 마세요 $TERMCMD
)
# ~/.config/ranger/rifle.conf
...
!ext exe, mime octet-stream$, has gpg, flag t = () { rifle -f F "$1" } =(gpg -dq "$1")