간단한 설명
PowerShell의 범위 개념을 설명하고 요소의 범위를 설정하고 변경하는 방법을 보여 줍니다.
긴 설명
PowerShell은 읽고 변경할 수 있는 위치를 제한하여 변수, 별칭, 함수 및 PowerShell 드라이브(PSDrive)에 대한 액세스를 보호합니다. PowerShell은 범위 규칙을 사용하여 변경해서는 안 되는 항목을 실수로 변경하지 않도록 합니다.
다음은 범위의 기본 규칙입니다.
범위는 중첩할 수 있습니다. 외부 범위를 부모 범위라고 합니다. 중첩된 범위는 해당 부모의 자식 범위입니다.
항목은 항목이 만들어진 범위와 모든 자식 범위에서 볼 수 있지만 명시적으로 비공개로 설정하지 않는 한 가능합니다.
변수, 별칭, 함수 및 PowerShell 드라이브를 현재 범위 외부의 범위에서 선언할 수 있습니다.
다른 범위를 명시적으로 지정하지 않는 한 범위 내에서 만든 항목은 만들어진 범위에서만 변경할 수 있습니다.
범위에서 항목을 만들 때 해당 항목이 다른 범위의 항목과 이름을 공유하는 경우 원래 항목이 새 항목 아래에 숨겨질 수 있지만 재정의되거나 변경되지는 않습니다.
PowerShell 범위
PowerShell은 다음 범위를 지원합니다.
전역: PowerShell이 시작되거나 새 세션 또는 Runspace를 만들 때 적용되는 범위입니다. PowerShell이 시작될 때 존재하는 변수 및 함수는 자동 변수 및 기본 설정 변수와 같은 전역 범위에서 만들어졌습니다. PowerShell 프로필의 변수, 별칭 및 함수도 전역 범위에서 만들어집니다. 전역 범위는 세션의 루트 부모 범위입니다.
로컬: 현재 범위입니다. 로컬 범위는 전역 범위 또는 다른 범위일 수 있습니다.
스크립트: 스크립트 파일이 실행되는 동안 생성되는 범위입니다. 스크립트의 명령만 스크립트 범위에서 실행됩니다. 스크립트의 명령에서 스크립트 범위는 로컬 범위입니다.
비고
비공개 는 범위가 아닙니다. 항목이 정의된 범위 밖에 있는 항목의 표시 유형을 변경하는 옵션입니다 .
부모 및 자식 범위
스크립트 또는 함수를 호출하여 새 자식 범위를 만들 수 있습니다. 호출 범위는 부모 범위입니다. 호출된 스크립트 또는 함수는 자식 범위입니다. 호출하는 함수나 스크립트가 다른 함수를 호출할 수 있고, 이로 인해 루트 범위가 전역 범위인 자식 범위의 계층 구조가 형성될 수 있습니다.
항목을 명시적으로 비공개로 만들지 않는 한 부모 범위의 항목을 자식 범위에서 사용할 수 있습니다. 그러나 자식 범위에서 만들고 변경하는 항목은 항목을 만들 때 범위를 명시적으로 지정하지 않는 한 부모 범위에 영향을 주지 않습니다.
비고
모듈의 함수는 호출 범위의 자식 범위에서 실행되지 않습니다. 모듈에는 전역 범위에 연결된 자체 세션 상태가 있습니다. 모든 모듈 코드는 자체 루트 범위가 있는 범위의 모듈별 계층 구조에서 실행됩니다.
상속
자식 범위는 부모 범위에서 변수, 별칭 및 함수를 상속하지 않습니다. 항목이 private이 아닌 경우 자식 범위는 부모 범위의 항목을 볼 수 있습니다. 또한 부모 범위를 명시적으로 지정하여 항목을 변경할 수 있지만 항목은 자식 범위의 일부가 아닙니다.
그러나 자식 범위는 항목 집합으로 만들어집니다. 일반적으로 AllScope 옵션이 있는 모든 별칭이 포함됩니다. 이 옵션은 이 문서의 뒷부분에서 설명합니다. 여기에는 AllScope 옵션이 있는 모든 변수와 일부 자동 변수가 포함됩니다.
특정 범위에서 항목을 찾으려면 Get-Variable 또는 Get-AliasScope 매개 변수를 사용합니다.
예를 들어 로컬 범위의 모든 변수를 얻으려면 다음을 입력합니다.
Get-Variable -Scope local
전역 범위의 모든 변수를 얻으려면 다음을 입력합니다.
Get-Variable -Scope global
범위 수정자
변수, 별칭 또는 함수 이름에는 다음 선택적 범위 한정자 중 하나가 포함될 수 있습니다.
global:- 이름이 Global 범위에 있는지 지정합니다.local:- 이름이 로컬 범위에 있는지 지정합니다. 현재 범위는 항상 로컬 범위입니다.private:- 이름이 비공개로 지정되어 현재 범위에서만 표시됩니다.script:- 이름이 스크립트 범위에 있는지 지정합니다. 스크립트 범위는 가장 가까운 상위 스크립트 파일의 범위이나, 가장 가까운 상위 스크립트 파일이 없는 경우 전역.using:- 및Start-Job와 같은Invoke-Commandcmdlet을 통해 스크립트를 실행하는 동안 다른 범위에 정의된 변수에 액세스하는 데 사용됩니다.workflow:- 이름이 워크플로 내에 있는지 지정합니다. 참고: 워크플로는 PowerShell v6 이상에서 지원되지 않습니다.<variable-namespace>- PowerShell PSDrive 공급자가 만든 한정자입니다. 다음은 그 예입니다.네임스페이스 설명 Alias:현재 범위에 정의된 별칭 Env:현재 범위에 정의된 환경 변수 Function:현재 범위에 정의된 함수 Variable:현재 범위에 정의된 변수
스크립트의 기본 범위는 스크립트 범위입니다. functions 와 aliases의 기본 범위는 스크립트에 정의되어 있더라도 local scope입니다.
범위 한정자 사용
새 변수, 별칭 또는 함수의 범위를 지정하려면 범위 한정자를 사용합니다.
변수의 범위 한정자에 대한 구문은 다음과 같습니다.
$[<scope-modifier>:]<name> = <value>
함수의 범위 한정자에 대한 구문은 다음과 같습니다.
function [<scope-modifier>:]<name> {<function-body>}
범위 한정자를 사용하지 않는 다음 명령은 현재 또는 로컬 범위에 변수를 만듭니다.
$a = "one"
전역 범위에서 동일한 변수를 만들려면 범위 global: 한정자를 사용합니다.
$global:a = "one"
스크립트 범위에서 동일한 변수를 만들려면 script: 범위 한정자를 사용합니다.
$script:a = "one"
함수와 함께 범위 한정자를 사용할 수도 있습니다. 다음 함수 정의는 전역 범위에 함수를 만듭니다.
function global:Hello {
Write-Host "Hello, World"
}
범위 한정자를 사용하여 다른 범위의 변수를 참조할 수도 있습니다.
다음 명령은 먼저 로컬 범위에서 $test 변수를 참조한 다음 전역 범위를 참조합니다.
$test
$global:test
Using: 범위 한정자
사용은 원격 명령에서 지역 변수를 식별하는 특수 범위 한정자입니다. 한정자가 없으면 PowerShell은 원격 명령의 변수가 원격 세션에서 정의될 것으로 예상합니다.
Using 범위 한정자는 PowerShell 3.0에서 도입되었습니다.
세션 외부에서 실행되는 스크립트 또는 명령의 경우 Using 범위 한정자가 호출 세션 범위의 변수 값을 포함해야 세션 외부 코드에서 액세스할 수 있습니다.
Using 범위 한정자는 다음 컨텍스트에서 지원됩니다.
- 원격으로 실행된 명령,
Invoke-Command, HostName, SSHConnection 또는 Session 매개 변수(원격 세션)를 사용하여 시작 - 백그라운드 작업이
Start-Job(외부 프로세스 세션)으로 시작되었습니다. -
Start-ThreadJob또는ForEach-Object -Parallel통해 시작된 스레드 작업(별도의 스레드 세션)
컨텍스트에 따라 포함된 변수 값은 호출자의 범위에 있는 데이터의 독립적인 복사본이거나 해당 데이터에 대한 참조입니다. 원격 및 독립 프로세스 세션에서는 항상 독립적인 복제본입니다.
자세한 내용은 about_Remote_Variables에서 확인하십시오.
스레드 세션에서는 참조로 전달됩니다. 즉, 다른 스레드에서 호출 범위 변수를 수정할 수 있습니다. 변수를 안전하게 수정하려면 스레드 동기화가 필요합니다.
자세한 내용은 다음을 참조하십시오.
- start-ThreadJob
- ForEach-개체
변수 값의 직렬화
원격으로 실행된 명령 및 백그라운드 작업은 프로세스 외부에서 실행됩니다. Out-of-process 세션은 XML 기반 직렬화 및 역직렬화를 사용하여 프로세스 경계를 넘어 변수 값을 사용할 수 있도록 합니다. 직렬화 프로세스는 개체를 원래 개체의 속성을 포함하지만 메서드를 포함하지 않는 PSObject으로 변환합니다.
제한된 형식 집합의 경우 역직렬화는 개체를 원래 형식으로 복원합니다. 리하이딩된 개체는 원래 개체 인스턴스의 복사본입니다. 형식 속성과 메서드가 있습니다. System.Version같은 간단한 형식의 경우 복사본은 정확합니다. 복합 형식의 경우 복사본이 불완전합니다. 예를 들어 리하이딩된 인증서 개체에는 프라이빗 키가 포함되지 않습니다.
다른 모든 형식의 인스턴스는 PSObject 인스턴스입니다. PSTypeNames 속성에는 Deserialized접두사가 붙은 원래 형식 이름이 포함됩니다. 예를 들어, Deserialized.System.Data.DataTable입니다.
AllScope 옵션
변수 및 별칭에는 AllScope값을 가질 수 있는 Option 속성이 있습니다. AllScope 속성이 있는 항목은 부모 범위에 의해 소급되어 상속되지는 않지만 사용자가 만드는 모든 자식 범위의 일부가 됩니다.
AllScope 속성이 있는 항목은 자식 범위에 표시되며 해당 범위의 일부입니다. 모든 범위의 항목에 대한 변경 내용은 변수가 정의된 모든 범위에 영향을 줍니다.
범위 관리
여러 cmdlet에는 특정 범위에서 항목을 가져오거나 설정(만들고 변경)할 수 있는 Scope 매개 변수가 있습니다. 다음 명령을 사용하여 Scope 매개 변수가 있는 세션의 모든 cmdlet을 찾습니다.
Get-Help * -Parameter scope
특정 범위에 표시되는 변수를 찾으려면 ScopeGet-Variable 매개 변수를 사용합니다. 표시되는 변수에는 전역 변수, 부모 범위의 변수 및 현재 범위의 변수가 포함됩니다.
예를 들어 다음 명령은 로컬 범위에 표시되는 변수를 가져옵니다.
Get-Variable -Scope local
특정 범위에서 변수를 만들려면 범위 한정자 또는 Set-Variable 매개 변수를 사용합니다. 다음 명령은 전역 범위에 변수를 만듭니다.
New-Variable -Scope global -Name a -Value "One"
New-Alias, Set-Alias또는 Get-Alias cmdlet의 Scope 매개 변수를 사용하여 범위를 지정할 수도 있습니다. 다음 명령은 전역 범위에 별칭을 만듭니다.
New-Alias -Scope global -Name np -Value Notepad.exe
특정 범위에서 함수를 얻으려면 범위에 있을 때 Get-Item cmdlet을 사용합니다.
Get-Item cmdlet에는 Scope 매개 변수가 없습니다.
비고
Scope 매개 변수를 사용하는 cmdlet의 경우 숫자로 범위를 참조할 수도 있습니다. 이 숫자는 한 범위의 상대 위치를 다른 범위로 설명합니다. 범위 0은 현재 또는 로컬 범위를 나타냅니다. 범위 1은 바로 부모 범위를 나타냅니다. 범위 2는 부모 범위를 포함한 그 상위의 범위 등을 나타냅니다. 번호가 매겨진 범위는 여러 재귀 범위를 만든 경우에 유용합니다.
Scope와 함께 Dot Source Notation 사용
스크립트와 함수는 모든 범위 규칙을 따릅니다. 특정 범위에서 만들면 cmdlet 매개 변수 또는 범위 한정자를 사용하여 해당 범위를 변경하지 않는 한 해당 범위에만 적용됩니다.
그러나 점 원본 표기법을 사용하여 현재 범위에 스크립트나 함수를 추가할 수 있습니다. 그런 다음 스크립트가 현재 범위에서 실행되면 스크립트가 만드는 모든 함수, 별칭 및 변수를 현재 범위에서 사용할 수 있습니다.
현재 범위에 함수를 추가하려면 함수 호출에서 함수의 경로와 이름 앞에 점(.)과 공백을 입력합니다.
예를 들어 스크립트 범위(스크립트의 기본값)의 C:\Scripts 디렉터리에서 Sample.ps1 스크립트를 실행하려면 다음 명령을 사용합니다.
c:\scripts\sample.ps1
로컬 범위에서 Sample.ps1 스크립트를 실행하려면 다음 명령을 사용합니다.
. c:\scripts.sample.ps1
호출 연산자(&)를 사용하여 함수나 스크립트를 실행하면 현재 범위에 추가되지 않습니다. 다음 예제에서는 call 연산자를 사용합니다.
& c:\scripts.sample.ps1
호출 연산자에 대한 자세한 내용은 about_operators에서 확인할 수 있습니다.
Sample.ps1 스크립트가 만드는 별칭, 함수 또는 변수는 현재 범위에서 사용할 수 없습니다.
범위 없이 제한
몇 가지 PowerShell 개념은 범위와 유사하거나 범위와 상호 작용합니다. 이러한 개념은 범위 또는 범위의 동작과 혼동될 수 있습니다.
세션, 모듈 및 중첩된 프롬프트는 독립적인 환경이지만 세션에서 전역 범위의 하위 범위는 아닙니다.
회의
세션은 PowerShell이 실행되는 환경입니다. 원격 컴퓨터에서 세션을 만들 때 PowerShell은 원격 컴퓨터에 대한 영구 연결을 설정합니다. 영구 연결을 사용하면 여러 관련 명령에 세션을 사용할 수 있습니다.
세션은 포함된 환경이기 때문에 자체 범위를 갖지만 세션은 세션이 만들어진 세션의 자식 범위가 아닙니다. 세션은 고유의 전역 범위로 시작합니다. 이 범위는 세션의 전역 범위와 독립적입니다. 세션에서 자식 범위를 만들 수 있습니다. 예를 들어 스크립트를 실행하여 세션에서 자식 범위를 만들 수 있습니다.
모듈
PowerShell 모듈을 사용하여 PowerShell 도구를 공유하고 제공할 수 있습니다. 모듈은 cmdlet, 스크립트, 함수, 변수, 별칭 및 기타 유용한 항목을 포함할 수 있는 단위입니다. 명시적으로 정의되지 않는 한, 모듈의 항목은 모듈 외부에서 액세스할 수 없습니다. 따라서 다른 항목이 세션의 cmdlet, 스크립트, 함수 및 기타 항목을 재정의할 수 있다는 걱정 없이 세션에 모듈을 추가하고 공용 항목을 사용할 수 있습니다.
기본적으로 모듈은 현재 범위가 아닌 현재 세션 상태의 최상위 수준에 로드됩니다. 현재 세션 상태는 모듈 세션 상태 또는 전역 세션 상태일 수 있습니다. 세션에 모듈을 추가해도 범위는 변경되지 않습니다. 전역 범위에 있는 경우 모듈은 전역 세션 상태로 로드됩니다. 모든 내보내기는 전역 테이블에 배치됩니다.
module1 내에서 module2를 로드하면 module2가 전역 세션 상태가 아닌 module1의 세션 상태로 로드됩니다. module2의 모든 내보내기는 module1 세션 상태의 맨 위에 배치됩니다.
Import-Module -Scope local을 사용하는 경우, 내보내기가 최상위 수준이 아닌 현재 범위 객체에 배치됩니다.
모듈에 있고 (또는 Import-Module -Scope global)를 사용하여 Import-Module -Global 다른 모듈을 로드하는 경우 해당 모듈과 해당 내보내기는 모듈의 로컬 세션 상태 대신 전역 세션 상태로 로드됩니다. 이 기능은 모듈을 조작하는 모듈을 작성하기 위해 설계되었습니다.
WindowsCompatibility 모듈은 이 작업을 수행하여 프록시 모듈을 전역 세션 상태로 가져옵니다.
세션 상태 내에서 모듈은 자체 범위를 갖습니다. 다음 모듈 C:\temp\mod1.psm1고려합니다.
$a = "Hello"
function foo {
"`$a = $a"
"`$global:a = $global:a"
}
이제 전역 변수 $a만들고 값을 제공하고 foo 함수를 호출합니다.
$a = "Goodbye"
foo
모듈은 모듈 범위에서 변수 $a 선언한 다음, foo 함수는 두 범위에서 변수 값을 출력합니다.
$a = Hello
$global:a = Goodbye
중첩된 프롬프트
중첩된 프롬프트에는 자체 범위가 없습니다. 중첩 프롬프트를 입력하면 중첩된 프롬프트가 환경의 하위 집합입니다. 그러나 로컬 범위 내에 남아 있습니다.
스크립트에는 고유한 범위가 있습니다. 스크립트를 디버깅하고 스크립트의 중단점에 도달하면 스크립트 범위를 입력합니다.
개인 옵션
별칭 및 변수에는 Private 값을 사용할 수 있는 Option 속성이 있습니다. Private 옵션이 있는 항목은 해당 항목이 만들어진 범위에서 보고 변경할 수 있지만 해당 범위 밖에서는 보거나 변경할 수 없습니다.
예를 들어 전역 범위에서 private 옵션이 있는 변수를 만든 다음 스크립트를 Get-Variable 실행하면 스크립트의 명령에 private 변수가 표시되지 않습니다. 이 인스턴스에서 전역 범위 한정자를 사용하면 private 변수가 표시되지 않습니다.
, , New-Variable및 Set-Variable cmdlet의 Option 매개 변수를 New-Alias사용하여 Option 속성의 값을 Private로 Set-Alias설정할 수 있습니다.
가시성
변수 또는 별칭의 Visibility 속성은 생성된 컨테이너 외부에서 항목을 볼 수 있는지 여부를 결정합니다. 컨테이너는 모듈, 스크립트 또는 스냅인일 수 있습니다. 가시성은 Option 속성의 Private 값이 범위용으로 디자인된 것과 동일한 방식으로 컨테이너에 대해 디자인되었습니다.
Visibility 속성은 Public 및 Private 값을 사용합니다. 프라이빗 표시 유형이 있는 항목은 생성된 컨테이너에서만 보고 변경할 수 있습니다. 컨테이너를 추가하거나 가져오는 경우 개인 표시 유형이 있는 항목을 보거나 변경할 수 없습니다.
가시성은 컨테이너용으로 설계되었기 때문에 스코프에서는 다르게 작동합니다.
- 전역 범위에서 비공개 표시 유형이 있는 항목을 만드는 경우 모든 범위에서 항목을 보거나 변경할 수 없습니다.
- 프라이빗 표시 유형이 있는 변수의 값을 보거나 변경하려고 하면 PowerShell에서 오류 메시지가 반환됩니다.
New-Variable 및 Set-Variable cmdlet을 사용하여 프라이빗 표시 유형이 있는 변수를 만들 수 있습니다.
예시
예제 1: 스크립트에서만 변수 값 변경
다음 명령은 스크립트에서 $ConfirmPreference 변수의 값을 변경합니다. 변경 내용은 전역 범위에 영향을 주지 않습니다.
먼저 로컬 범위에서 $ConfirmPreference 변수의 값을 표시하려면 다음 명령을 사용합니다.
PS> $ConfirmPreference
High
다음 명령을 포함하는 Scope.ps1 스크립트를 만듭니다.
$ConfirmPreference = "Low"
"The value of `$ConfirmPreference is $ConfirmPreference."
스크립트를 실행합니다. 스크립트는 $ConfirmPreference 변수의 값을 변경한 다음 스크립트 범위에서 해당 값을 보고합니다. 출력은 다음 출력과 유사해야 합니다.
The value of $ConfirmPreference is Low.
다음으로, 현재 범위에서 $ConfirmPreference 변수의 현재 값을 테스트합니다.
PS> $ConfirmPreference
High
이 예제에서는 스크립트 범위에서 변수 값을 변경해도 부모 범위의 변수 값에는 영향을 주지 않음을 보여 줍니다.
예제 2: 다른 범위에서 변수 값 보기
범위 한정자를 사용하여 로컬 범위 및 부모 범위에서 변수 값을 볼 수 있습니다.
먼저 전역 범위에서 $test 변수를 정의합니다.
$test = "Global"
다음으로, $test 변수를 정의하는 Sample.ps1 스크립트를 만듭니다. 스크립트에서 범위 한정자를 사용하여 $test 변수의 전역 또는 로컬 버전을 참조합니다.
Sample.ps1:
$test = "Local"
"The local value of `$test is $test."
"The global value of `$test is $global:test."
Sample.ps1를 실행하면 출력은 다음 출력과 유사해야 합니다.
The local value of $test is Local.
The global value of $test is Global.
스크립트가 완료되면 $test 전역 값만 세션에 정의됩니다.
PS> $test
Global
예제 3: 부모 범위에서 변수 값 변경
Private 옵션이나 다른 메서드를 사용하여 항목을 보호하지 않는 한 부모 범위에서 변수 값을 보고 변경할 수 있습니다.
먼저 전역 범위에서 $test 변수를 정의합니다.
$test = "Global"
다음으로, $test 변수를 정의하는 Sample.ps1 스크립트를 만듭니다. 스크립트에서 범위 한정자를 사용하여 $test 변수의 전역 또는 로컬 버전을 참조합니다.
Sample.ps1:
$global:test = "Local"
"The global value of `$test is $global:test."
스크립트가 완료되면 $test 전역 값이 변경됩니다.
PS> $test
Local
예제 4: 프라이빗 변수 만들기
private 변수는 값이 Private인 Option 속성이 있는 변수입니다. 프라이빗 변수는 자식 범위에서 상속되지만 변수가 만들어진 범위에서만 보거나 변경할 수 있습니다.
다음 명령은 로컬 범위에서 호출되는 $ptest private 변수를 만듭니다.
New-Variable -Name ptest -Value 1 -Option private
로컬 범위에서 of $ptest 값을 표시하고 변경할 수 있습니다.
PS> $ptest
1
PS> $ptest = 2
PS> $ptest
2
다음으로, 다음 명령이 포함된 Sample.ps1 스크립트를 만듭니다. 이 명령은 의 $ptest값을 표시하고 변경하려고 합니다.
Sample.ps1:
"The value of `$Ptest is $Ptest."
"The value of `$Ptest is $global:Ptest."
변수는 $ptest 스크립트 범위에 표시되지 않으며 출력은 비어 있습니다.
"The value of $Ptest is ."
"The value of $Ptest is ."
예제 5: 원격 명령에서 로컬 변수 사용
로컬 세션에서 만든 원격 명령의 변수의 경우 Using 범위 한정자를 사용합니다. PowerShell은 원격 명령의 변수가 원격 세션에서 만들어졌다고 가정합니다.
구문은 다음과 같습니다.
$Using:<VariableName>
예를 들어 다음 명령은 로컬 세션에서 $Cred 변수를 만든 다음 원격 명령에서 $Cred 변수를 사용합니다.
$Cred = Get-Credential
Invoke-Command $s {Remove-Item .\Test*.ps1 -Credential $Using:Cred}
Using 범위는 PowerShell 3.0에서 도입되었습니다. PowerShell 2.0에서 변수가 로컬 세션에서 만들어졌음을 나타내려면 다음 명령 형식을 사용합니다.
$Cred = Get-Credential
Invoke-Command $s {
param($c)
Remove-Item .\Test*.ps1 -Credential $c
} -ArgumentList $Cred
참고하십시오
- 변수에_대한_정보
- 환경 변수에 대하여
- 함수에_대해
- 스크립트 블록 소개
- start-ThreadJob