스크립트 끝에서 모든 변수를 삭제하는 것이 좋은 습관입니까?

스크립트 끝에서 모든 변수를 삭제하는 것이 좋은 습관입니까?

쉘 스크립트에 사용된 변수를 스크립트 마지막 부분에서 제거할 수 있나요?

rm -rf $abc
rm -rf $def

또는

unset $abc
unset $def

등.

이것은 실제로 좋은 습관입니까?

답변1

이것은아주 나쁜관행.

rm파일 삭제. 이는 변수와 관련이 없습니다. 그럼에도 불구하고 스크립트가 종료되고 운영 체제가 셸의 메모리를 회수하면 변수 자체가 해제됩니다.


간단한 경우에는 변수 중 하나의 값과 동일한 이름을 가진 파일이 다음 구성에 의해 삭제됩니다.

abc=filename
rm -f $abc  # Deletes "filename" in the current directory

상황은 더욱 악화됩니다. 파일 이름이 포함 abc된 경우def공백으로 구분된 개별 단어로(또는 의 다른 문자), 이러한 파일을 제거하고 와일드카드가 단어에 나타나면 IFS와일드카드도 확장됩니다 .*

abc='hello world'
rm -f $abc  # Deletes file "hello" and "world" (leaves "hello world" alone)
abc='5 * 3'
rm -f $abc  # Deletes all files, because * is expanded (!)
def='-r /'
rm -f $def  # Really deletes *all* files this user can access

쉘 매개변수는 다음으로 확장됩니다.$var~에 의해분사, 여기서 변수의 각 문자는 IFS변수를 서로 다른 매개변수로 나눕니다. 그러면 모든 단어는파일 이름 확장자의 영향을 받음*, ?및 패턴을 사용하여 [abc...]파일 이름을 만듭니다. 변수의 내용에 따라 상황이 정말 나빠질 수 있습니다. 이렇게 하지 마십시오.


비워 둘 필요가 없습니다.설정되지 않음어떤 방식으로든 쉘 스크립트 끝에 변수를 추가하십시오.

답변2

실제로 쉘 변수 또는 임시 파일을 의미하는지 궁금합니다.

현재 수행 중인 작업이 다음과 같은 경우(임시 파일):

tmp=$(mktemp)
something > "$tmp"
something else < "$tmp"
rm "$tmp"

물론 작업이 끝나면 임시 파일을 삭제하세요. 스크립트가 중간에 충돌하더라도 파일은 그대로 남아 있지만 이는 드문 일이 아닙니다. 원한다면 trap 'rm -f -- "$tmp"' EXIT쉘이 종료될 때 파일을 삭제할 수 있습니다.

그러나 개별 파일을 삭제할 때는 -f -r`을 사용해야 합니다 rm -f -- "$tmp", as.would help in avoiding error messages if the file was e.g. removed earlier for some reason. No reason to use

mktemp(또한 기본적으로 "좋은" 파일 이름을 생성 하더라도 해당 변수를 인용하는 것을 잊지 마십시오 .)


그러나 이렇게 하면(변수):

read var
do something with "$var"
rm "$var"

그럼 당신은그러고 싶지 않아: 삭제할 파일이 없고 사용자 입력만 있습니다. 쉘이 종료되면 쉘 변수는 더 이상 존재하지 않으므로 설정을 해제할 필요가 없습니다.


그러나 스크립트를 다른 쉘에서 가져온 경우(또는 .bashrc유사한 쉘에 있는 경우) 스크립트가 종료될 때 쉘이 종료되지 않습니다. 이 경우 unset마지막으로 사용한 임시 변수를 유지하고 남은 쉘 수명 동안 해당 설정을 유지하지 않는 것이 유용할 수 있습니다.

# in .bashrc
__hour=$(date +%H)
if [ "$__hour" -lt 12 ] ; then echo "Good Morning!" ; 
elif [ "$__hour" -gt 18 ] ; then echo "Good Evening!" ;
fi
unset __hour

변수 이름은 이 스크립트 외부에서 사용되는 일부 변수와 여전히 충돌할 수 있으므로 이름을 지정할 때 주의해야 합니다.

답변3

오늘 쉘 스크립트의 오류 출력이 막혔습니다. 그 이유는 내보낸 환경 변수가 실제로 쉘 스크립트에 몰래 들어가 불쾌한 부작용을 일으킬 수 있기 때문입니다. 구체적인 방법은 다음과 같습니다.

#!/bin/sh
#
line="$line $1"
echo $line

으로 호출하면 myscript.sh smeagol이미 내보낸 line변수가 몰래 들어옵니다. unset line스크립트 항목의 오염을 방지 해야 합니다 .

답변4

스크립트 끝에서 모든 변수를 설정 해제하는 것이 좋은 습관입니까? 1

쉘 스크립트는 다양한 방식으로 실행될 수 있으므로(아래 "1. 쉘 스크립트 호출 방법" 섹션 참조) 이는 사용 사례와 의도에 따라 달라집니다. 이는 변수가 원래 쉘(쉘을 호출한 쉘)에 의해 유지되는지 여부에 영향을 미칩니다. 스크립트) 여부.

예를 들어, ting 변수에 대한 여러 사례는 다음과 같습니다 unset.

  • 나쁜, 만약에이 스크립트의 초점은 환경 변수를 설정하는 것입니다.

    그리고 이 역시 쉘 스크립트가 호출되는 방식에 따라 달라집니다(섹션 1 참조).

  • 나쁜, 만약에이 스크립트는 쉘 변수를 노출하도록 설계되었습니다.어떤 목적으로.

    예를 들어, 스크립트는 더 큰 "쉘 스크립트 모음" 내의 "모듈"이고 다른 쉘 스크립트는 소위 "하위 스크립트"에 의해 설정된 변수에 의존합니다. (이전 항목과 동일한 주의 사항이 적용됩니다. 섹션 1을 참조하세요.)

  • 좋아요, 누구든지 원한다면무지한 사용자를 보호하세요(본인 포함) 그리고->이전 사항이 적용되지 않는 경우<-(그렇지 않은 경우가 많습니다).

    참고: 무지 = 지식이 적음

    예를 들어, 모든 쉘 변수가 열거되는 "설정 해제 섹션"(참조) 시간과 미래의 고통을 줄여줍니다. 저는 매일 쉘 스크립트를 작성하지 않으며, 글을 쓰는 동안 많은 코멘트를 남기지만, 제 손에 있는 근육 기억은 스크립트를 어떻게 실행하는지 상관하지 않습니다. 세션(아래 "1. 쉘 스크립트 호출 방법" 섹션을 다시 참조하세요). 또한 좋은 문서라도 다른 사람이 스크립트를 사용할 것으로 예상되는 경우에는 도움이 되지 않습니다. 이는 종종 무시되기 때문입니다(나의 무지한 자기 포함).

  • (내가 무엇을 놓치고 있나요?)

1. 쉘 스크립트 호출 방법

TL;DR
(사이트가 마크다운 테이블을 지원하지 않기 때문에 ASCII 테이블. 이 답변의 더 나은 형식의 버전을 참조하세요.이 점.)

|    Shell script calling     |   Preserves     | Relevant  |
|          method             | variables and   | section   |
|                             |    exports      |           |
| --------------------------- | --------------- | --------- |
| `<interpreter> <file_name>` |        no       | 1.1       |
| `.`                         |        yes      | 1.2       | (workaround in 1.2.1) 
| executable script           |        no       | 1.3       |
| `source`                    |        yes      | 1.4       | (workaround in 1.2.1)

1.1<interpreter> <file_name>

예를 들어 스크립트를 호출 script.sh하고 해당 스크립트가 포함된 디렉터리에서 호출하는 경우:

  •     sh script.sh
  • bash script.sh
  •   zsh script.sh
  • fish script.sh

이 방법은서브쉘(고급 Bash 스크립팅 가이드: 21장. 서브셸), 이는 하위 프로세스의 새로운 쉘입니다.

쉘 및 환경 변수폐기됩니다스크립트 실행이 완료된 후 스크립트를 호출한 셸은 영향을 받지 않습니다.

스크립트의 요점이 현재 셸에서 사용할 환경 변수를 설정하는 것이라면 다음을 사용하세요.

1.2개dot( .) POSIX 표준 명령

관련 주제:stackoverflow: 쉘 스크립트가 완료된 후 환경 변수를 유지합니다.

.할 것이다"현재 환경에서 명령 실행"(POSIX 표준, 도트 매뉴얼 페이지) 시작하지 않고서브쉘.

쉘 및 환경 변수유효하게 유지됩니다스크립트 실행이 완료된 후.

동일한 스크립트를 다시 실행하면 예기치 않은 동작이 발생할 수 있습니다. 예를 들어, 다음 스크립트가 주어지면(이라고 부르겠습니다 test.sh)

#!/usr/bin/env bash

# https://unix.stackexchange.com/questions/129391/passing-named-arguments-to-shell-scripts
while [ $# -gt 0 ]; do
  case "$1" in

    --option_a|-a)
      OPTION_A=$2
      ;;
    --option_b|-b)
      OPTION_B=$2
      ;;
    *)
      printf "***************************\n"
      printf "* Error: Invalid argument.*\n"
      printf "***************************\n"
      exit 1
  esac
  shift
  shift
done

# Setting default value if script is not called with `--option`
OPTION_A="${OPTION_A:-"default A"}"
OPTION_B="${OPTION_B:-"default B"}"

echo "OPTION_A: ${OPTION_A}"
echo "OPTION_B: ${OPTION_B}"

섹션 1.1 및 1.3에 설명된 방법을 통해 실행하면 모든 것이 정상입니다.

$ chmod +x test.sh
$ ./test.sh
OPTION_A: default A
OPTION_B: default B

$ bash test.sh -a 27
OPTION_A: 27
OPTION_B: default B

$ ./test.sh      
OPTION_A: default A
OPTION_B: default B

그러나 변수의 기본값을 사용하려면(명령줄 옵션이 다음과 같은 경우) .또는 (아래 섹션 1.4 참조)을 사용하십시오.source아니요만약에:

# source test.sh === . ./test.sh

$ source test.sh
OPTION_A: default A
OPTION_B: default B

$ . ./test.sh -a 27 
OPTION_A: 27
OPTION_B: default B

$ source test.sh      
OPTION_A: 27
OPTION_B: default B

1.2.1 현재 쉘을 망치지 않고 .(and )를 사용하는 방법은 무엇입니까 ?source

괄호( ())를 사용하면 그 사이의 명령이서브쉘(섹션 1.1 및 1.3과 동일한 방법).

예를 들어, ( source test.sh ).

관련 문서 및 스레드:

1.3 스크립트 파일의 실행 가능 비트 설정

위의 "1.1"의 설명을 참조하십시오 <interpreter> <file_name>.

관련 주제:unix&linux: Bash에 source실행 비트가 필요하지 않은 이유는 무엇입니까?

예를 들어 스크립트를 호출 script.sh하고 해당 스크립트가 포함된 디렉터리에서 호출하는 경우:

$ chmod +x script.sh

$ ./script.sh

1.4 source명령

포인트의 동의어( .'1.2 참조)도트 ( .) POSIX 표준 명령” 섹션 위).

내가 아는 한, 이 동의어는 bash, fish 및 zsh에 존재하지만 다른 쉘에도 존재할 수 있지만 source이식성을 위해 더 잘 사용됩니다..

관련 주제:unix&linux: 소스의 별칭으로 점(.)을 사용하는 이유는 무엇입니까? 왜 다른 명령에는 단축키가 없나요?


각주

[1]: 질문을 다시 말하면, 여기 답변은 변수에 초점을 맞추고 rm변수를 설정 해제하지 않기 때문입니다. 요약하다:

  • rm파일 삭제

  • unset

    이는 $다음 용도로 사용됩니다.매개변수 확장(GNU Bash 문서, 3.5.3 쉘 매개변수 확장) 이 경우에는2, 이전에는 필요하지 않았습니다 . 그렇지 않으면 참조하는 내용을 variable_name설정 해제하려고 시도합니다 .variable_name

    $ abc=27
    $ def=abc
    
    $ echo "abc=${abc}; def=${def}"
    abc=27; def=abc
    
    #       v
    $ unset $def
    #       ^
    $ echo "abc=${abc}; def=${def}"
    abc=; def=abc
    
    #       V
    $ unset  def
    #       ^
    $ echo "abc=${abc}; def=${def}"
    abc=; def=
    

    하지만 약간 복잡할 수 있습니다.unix&linux: unset그것은 무엇을 하는가?.

[2]: 또한 참조stackoverflow: 특수 달러 기호 쉘 변수는 무엇입니까?

[3]: 이 주제의 좋은 주제:

관련 정보