RedPlug's Tory

[Powershell] 함수1

Windows2020. 11. 21. 21:46

요새 공부를 하고 있긴 한데 정작 파워쉘쪽에 좀 소홀 했던것 같아서 

오랜만에 김도균 강사님 책 펴고 공부해봤네요~^^

어떤 언어를 해도 함수얘기는 거의 공통적으로 나오는 얘기라서 어렵지 않게 이해가 된 것 같습니다.

실무에서 바로 쓰는 파워쉘 - 김도균
9장 - 고급 스크립트 작성 기술

단순한 스크립트 작성에서 좀 더 나아가기 위한 방법인 함수에 대한 내용입니다.

함수의 기본 골격은 다음과 같습니다.

Function Verb-Noun {

     [CmdletBinding()]

     1) param()

     2) BEGIN{}

     3) PROCESS{}

     4) END{}

}

1. param

[Parameter(위치, 필수 매개변수, 파이프라인 입력)]

[데이터 형식]$변수명 = 기본값(옵션)

2. BEGIN

제일먼서 실행되는 부분이며 한번만 실행된다. 사전설정이 필요한 구문을 작성 예) 데이터베이스 초기 연결 설정, 특별한 설정이 필요 없는 경우 비워 놓는다.

3. PROCESS{}

함수의 주 로직이 들어가는 부분, 반복 처리를 하는 로직의 경우 작성 시 BEGIN쪽으로 넣어야 하는 블록을 구분하는게 좋다.(한번 실행하는걸 여러번 실행하게 되기 때문)

4. END{}

제일마지막에 실행되는 구분. 정리 작업에 해당 하는 구문(데이터베이스 연결종료 등), 별도로 필요하지 않는 다면 비워놓는다.

 

함수를 만드는 절차

  1. 함수를 function이라는 키워드와 함께 동사-명사 이름 규칙을 따라 함수 이름을 선언
  2. 함수의 블록 내부에서 처리하는 매개변수 설정을 param() 블록에 입력
  3.  주 처리 로직의 설정에 해당하는 구문을 BEGIN 블록에 입력
  4. 원하는 작업의 주 처리 로직을 PROCESS 블록에 입력
  5. 주 처리 로직의 정리에 해당 하는 작업을 END 블록에 입력

예제함수

function Get-SecurityEvents {
[CmdletBinding()]
Param(
[Parameter(Position=0,Mandatory=$True)]
[string]$ComputerName,

[int]$EventID = 4634
)   
    BEGIN 
    {
        $LogName = Read-Host "로그 이름을 입력하세요."        
    }
    PROCESS
    {
        Get-EventLog -ComputerName $ComputerName `
        -LogName $LogName |
    Where-Object -Property EventID -eq $EventID |
    Select-Object -First 7
    }
END {}
}

함수로 만들경우 바로 실행되지 않으며 함수를 실행하여 메모리에 올리고 실행하고자 하는 함수 이름을 콘솔에서 호출하여야 한다.

하기는 함수를 호출 후 확인하는 스크린샷

정상적으로 함수 호출 되었으며, 실행

파워쉘의 범위

범위 설명 범위 한정자
전역 파워셸 세션을 시작할 때 범위 $global:변수명
로컬 현재 범위, 전역 범위나 다른 범위가 될 수 있다. $local:변수명
스크립트 스크립트 파일이 실행되는 동안 만들어지는 범위 $script:변수명
전용(Private) 전용 범위의 항목은 현재 범위 외부에서 보이지 않는다 $private:변수명
숫자를 부여한 범위 숫자 범위는 한 범위와 다른 범위의 상대 위치를 나타낸다.  

범위 한정자를 활용하면 함수나 스크립트 내부의 변수에 접근하게 하거나, 함수의 실행 범위를 지정해 다른 범위에서 해당 함수를 접근하게 할 수 있다.

예제(Chap9EX2~3.ps1)

$Global:globalVar='전역 범위. 스크립트 밖에서 접근'

Function Check-FunctionScope
{
    $functionVar = '함수 범위. 함수내에서만 접근'
    "functionVar은 $functionVar"
    $Local:localVarInFunc='함수내에서 선언한 로컬 범위'
    $Script:scriptVarInFunc='함수내에서 선언한 스크립트 범위'
    $Global:globalVarInFunc='함수내에서 선언한 전역 범위'
    ''
    CallFrom-Function
}
''

$scriptVar = '스크립트 범위. 스크립트 내에서만 접근'
"scriptVar은 $scriptVar"
''

Check-FunctionScope
''
CallFrom-ScriptFunction global:CallFrom-Function
{
    $callByFunction = '다른 함수에서 불렀어요.'
    "callByFunction 변수는 $callByFunction"
}

Function global:CallFrom-Script
{
    $callByScript = '다른 스크립트에서 불렀어요.'
    "callByScript 변수는 $callByScript"
}

$Global:globalVar='전역 범위. 스크립트 밖에서 접근'

Function Check-FunctionScope
{
    $functionVar = '함수 범위. 함수내에서만 접근'
    "functionVar은 $functionVar"
    $Local:localVarInFunc='함수내에서 선언한 로컬 범위'
    $Script:scriptVarInFunc='함수내에서 선언한 스크립트 범위'
    $Global:globalVarInFunc='함수내에서 선언한 전역 범위'
    ''
    CallFrom-Function
}
''

$scriptVar = '스크립트 범위. 스크립트 내에서만 접근'
"scriptVar은 $scriptVar"
''

Check-FunctionScope
''
CallFrom-Script

3번스크립트 실행 후 2번 스크립트 실행

 

예제 : Chap9EX4.ps1

function Send-OutlookMail{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$False)]
        [string] $From = "redplug@outlook.com"
        [Parameter(Mandatory=$True)]
        [string] $To,
        [Parameter(Mandatory=$False)]
        [string] $Cc = "redplug@gmail.com"
        [Parameter(Mandatory=$True)]
        [string] $Subject,
        [Parameter(Mandatory=$False)]
        [string] $Body = "PowerShell Send Mail"
    )
    BEGIN 
    {
        $Cred = (Get-Credential)  // 인증처리 부분
        $SmtpSvr="smtp.live.com" 
        $SmtpPort="587"     
    }
    PROCESS
    {
        Send-MailMessage -From $From -To $To -Cc $Cc -Subject $Subject `
        -Body $Body -SmtpServer $SmtpSvr  -Port $SmtpPort -UseSsl `
        -Credential $Cred -Encoding UTF8
    }
    END
    {
        Clear-Variable -Name Cred
    }
}

발송엔 성공했는데 안보이길래 뒤져봤더니 스펨함에 떨어졌네요.