다른 스크립트의 임시 파일 수명주기를 처리하기 위해 재사용 가능한 스크립트를 디자인하는 방법

다른 스크립트의 임시 파일 수명주기를 처리하기 위해 재사용 가능한 스크립트를 디자인하는 방법

다른("응용 프로그램") 스크립트에 대한 임시 파일을 사용하여 전체 작업 집합을 처리하는 재사용 가능한("유틸리티") 스크립트를 만들어야 합니다.

  1. 만들다
  2. 생성된 임시 파일을 추적하세요.
  3. 이탈(정기적인 사용자 완료 및 중단)을 포착하고 생성된 모든 항목을 삭제합니다.

각 응용 프로그램 스크립트는 사용하는 모든 하위 스크립트에 대해 한 번 호출하는 일부 "기본" 스크립트에 의존하는 대신 유틸리티 스크립트 자체를 "포함"해야 합니다.

핵심 요구 사항은 유틸리티 스크립트를 사용하는 응용 프로그램 스크립트가 서로 호출할 수 있어야 하며 각 스크립트는 차례로 임시 파일을 사용해야 한다는 것입니다. 스크립트 간의 모든 호출은

./some_script.sh

그리고

. ./some_script.sh

일부 스크립트는 오류 코드로 종료되고 다른 스크립트는 명시적으로 종료되지 않습니다 exit. 애플리케이션 스크립트 자체는 서브셸을 사용하여 명령줄에서 호출할 수 있습니다. 예를 들면 다음과 같습니다.

echo "Parameter" |
./feed_parameter_to_script.sh script_using_tmps.sh

이상적으로는 애플리케이션 스크립트가 자체 코드로 서브셸에서 임시 파일 생성을 호출할 수 있지만 이것이 필수는 아닙니다.

내가 찾은 유일한 해결책은각 스크립트가 자체적으로 tmp 삭제를 수행하도록 허용, 이는 내 요구 사항의 항목 3을 충족하지 않습니다.

나와 같은 요구 사항에 대한 모범 사례는 무엇입니까?

답변1

스크립트가 자체적으로 엉망인 부분을 정리할 수 없는 경우 이는 이상적인 모범 사례가 될 것입니다. 따라서 제가 생각할 수 있는 차선책은 알려진 위치에 존재하고 다음을 포함하는 세마포어 파일을 사용하는 것입니다. 각 스크립트가 해당 파일을 찾는 데 필요한 데이터입니다. 예를 들어:

#!/bin/bash
if [[ -r $HOME/run/scratchfiles ]]; then
    scratchfiles="$(cat $HOME/run/scratchfiles)"
else
    scratchfiles=$(mktemp -d) && printf "%s" "$scratchfiles" > $HOME/run/scratchfiles
fi
[...]

더 이상 필요하지 않은 파일 정리를 담당하는 스크립트는 간단히 [[ -d "$scratchfiles" ]] && rm -fr "$scratchfiles"위의 내용을 제공할 수 있습니다.

답변2

Bash를 사용하는 경우 withtemp임시 파일을 처리하기 위해 얼마 전에 유틸리티 함수를 작성했습니다. 이 함수는 서브셸에서 실행되고 명령을 실행하여 인수 목록에 임시 파일 경로를 추가하거나, 대체 문자열(예:)이 지정된 경우 모든 임시 파일과 n번째 임시 파일을 {}대체합니다 . 다음 옵션이 정의됩니다.{}{n}

  • -s: 파일을 삭제할 때 shred대신 사용됩니다.rm
  • -c <command>: 각각을 평가하여 commandstdout을 다음 임시 파일로 리디렉션하고 추가 명령은 마지막 파일로 리디렉션됩니다.
  • -n <number>: 생성할 임시 파일 수입니다.
  • -r <replacement>: 대체 문자열을 사용합니다.
bash-5.1$ type withtemp
withtemp is a function
withtemp () 
{ 
    ( local -a RM=(rm -f);
    local -a COMMANDS=();
    local REPSTR='';
    local REPSTRN='';
    local -i NUMFILES=1;
    local TMPFILE;
    local -a TMPFILES=();
    local -a TMPFDS=();
    local -i i;
    unset OPTIND;
    while getopts sc:n:r: OPTION; do
        case "$OPTION" in 
            s)
                RM=(shred -zu)
            ;;
            c)
                COMMANDS+=("$OPTARG")
            ;;
            n)
                NUMFILES=$OPTARG
            ;;
            r)
                REPSTR=$OPTARG
            ;;
        esac;
    done;
    [ $NUMFILES -le 0 ] && NUMFILES=1;
    for ((i = 0; i < $NUMFILES; ++i))
    do
        TMPFILE=$(mktemp);
        exec {TMPFDS[$i]}> $TMPFILE;
        TMPFILES+=($TMPFILE);
    done;
    trap '"${RM[@]}" "${TMPFILES[@]}"' EXIT;
    i=0;
    for c in "${COMMANDS[@]}";
    do
        eval "$c" 1>&${TMPFDS[$i]};
        [ $((i + 1)) -lt ${#TMPFDS[@]} ] && (( ++i ));
    done;
    for i in ${TMPFDS[@]};
    do
        exec {i}>&-;
    done;
    shift $OPTIND
    if [ -n "$REPSTR" ]; then
        set -- "${@//$REPSTR/${TMPFILES[@]}}";
        for i in "${!TMPFILES[@]}";
        do
            REPSTRN=${REPSTR:0:-1}$((i + 1))${REPSTR: -1};
            set -- "${@//$REPSTRN/${TMPFILES[$i]}}";
        done;
    else
        set -- "$@" "${TMPFILES[@]}";
    fi;
    eval "$@" )
}
bash-5.1$ withtemp -n2 -c 'echo executing first command >&2; echo temp file one contents' \
                   -c 'echo executing second command >&2; echo temp file two contents' \
                   head -v
executing first command
executing second command
==> /tmp/tmp.47hSk9mVe4 <==
temp file one contents

==> /tmp/tmp.tBWnCc2ri1 <==
temp file two contents
bash-5.1$ withtemp -s -n2 -r{} -c 'tac /etc/passwd' -c 'tac /etc/group' \
                   'grep ^root: {2} {1}'
/tmp/tmp.OwMdFfuEMw:root:x:0:root
/tmp/tmp.eTXi6Ti17n:root:x:0:0::/root:/bin/bash

관련 정보