2010~2011년의 팁 글에는 네트워크를 다룬 것이 여럿 있었다. 핑으로 호스트 확인하기, 웹에서 파일 받기, FTP 다루기. 그때는 System.Net.NetworkInformation.Ping이나 System.Net.WebRequest 같은 .NET 클래스를 직접 만들어 썼다. 지금은 기본 명령으로 다 된다.
Test-Connection: 핑
Test-Connection -TargetName 192.168.0.1 -Count 2
Destination: 192.168.0.1
Ping Source Address Latency BufferSize Status
(ms) (B)
---- ------ ------- ------- ---------- ------
1 rpi-cluster-0 192.168.0.1 0 32 Success
2 rpi-cluster-0 192.168.0.1 0 32 Success
결과는 개체라서 Latency로 정렬하거나 Status로 거를 수 있다. 되는지 안 되는지만 알고 싶으면 -Quiet를 붙인다. True나 False만 돌려준다.
if (Test-Connection db1 -Count 1 -Quiet) { 'up' }
핑이 막혀 있는 곳이 많다. 그럴 때는 포트가 열렸는지를 본다.
Test-Connection github.com -TcpPort 443 # True
경로 추적(-Traceroute)과 MTU 확인(-MtuSize)도 같은 명령에 있다.
Windows PowerShell 5.1의 Test-Connection은 매개변수와 결과의 모양이 다르다(-ComputerName, ResponseTime). 5.1용으로 쓴 스크립트를 7로 가져오면 여기서 걸린다.
대역 전체를 훑기
2011년에 쓴 Ping-MultipleTarget은 주소를 하나씩 차례로 두드렸다. 응답 없는 주소마다 제한 시간을 다 기다리므로, 주소가 많을수록 그만큼 오래 걸렸다. ForEach-Object -Parallel로 한꺼번에 보내면 된다.
function Test-Host {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Prefix,
[ValidateRange(1, 254)][int]$Start = 1,
[ValidateRange(1, 254)][int]$End = 254,
[int]$TimeoutSeconds = 1
)
$Start..$End | ForEach-Object -Parallel {
$address = "$using:Prefix$_"
[pscustomobject]@{
Address = $address
Online = Test-Connection -TargetName $address -Count 1 -TimeoutSeconds $using:TimeoutSeconds -Quiet
}
} -ThrottleLimit 64 | Sort-Object { [version]$_.Address }
}
Test-Host -Prefix '192.168.0.' | Where-Object Online
주소 30개를 훑는 데 2.4초 걸렸다. 차례로 하면 응답 없는 26개가 1초씩 기다려 26초가 넘는다.
두 가지를 짚어 둔다. 병렬로 돌린 결과는 끝나는 순서대로 나오므로 마지막에 정렬한다. IP 주소는 글자로 정렬하면 10이 2보다 앞에 오기 때문에 [version]으로 바꿔 정렬한다. 그리고 옛 함수는 결과를 Write-Host로 색칠해 찍었지만, 이 함수는 개체를 돌려준다. 켜진 것만 거르거나 CSV로 내보내는 일은 쓰는 사람이 정한다.
Invoke-RestMethod: API 부르기
JSON을 돌려주는 주소를 부르면 개체로 바꿔서 준다. 날짜는 DateTime으로 바뀌어 있다.
$release = Invoke-RestMethod https://api.github.com/repos/PowerShell/PowerShell/releases/latest
$release.tag_name # v7.6.6
$release.published_at.GetType().Name # DateTime
($release.assets | Where-Object name -Like '*linux-arm64.tar.gz').name
보낼 때는 -Method와 -Body를 준다. 해시 테이블을 JSON으로 바꿔 넣는다.
$body = @{ title = 'Hello'; draft = $true } | ConvertTo-Json
Invoke-RestMethod https://api.example.com/posts -Method Post -Body $body -ContentType 'application/json'
토큰 인증은 매개변수로 있다. 헤더를 손으로 만들지 않는다.
$token = Get-Secret -Name api-token # SecureString
Invoke-RestMethod https://api.example.com/me -Authentication Bearer -Token $token
토큰을 금고에서 꺼내는 Get-Secret은 9편에서 다뤘다.
Invoke-WebRequest: 응답 전체가 필요할 때
상태 코드, 헤더, 본문 원문이 필요하면 이쪽을 쓴다.
$response = Invoke-WebRequest https://example.com
$response.StatusCode # 200
$response.Headers['Content-Type'] # text/html; charset=utf-8
두 명령 모두 4xx, 5xx 응답이면 예외를 던진다. 상태 코드를 직접 보고 판단하려면 -SkipHttpErrorCheck를 붙인다.
$response = Invoke-WebRequest https://api.github.com/nope -SkipHttpErrorCheck
$response.StatusCode # 404
불안정한 상대에게는 다시 시도하게 한다.
Invoke-RestMethod $url -MaximumRetryCount 3 -RetryIntervalSec 5
파일 내려받기와 올리기
내려받기는 -OutFile 하나다. 큰 파일이 중간에 끊겼으면 -Resume으로 이어 받는다.
Invoke-WebRequest $url -OutFile ./pwsh.tar.gz
Invoke-WebRequest $url -OutFile ./pwsh.tar.gz -Resume
2010년 글에서는 System.Net.WebClient를 만들어 DownloadFile()과 UploadFile()을 불렀다. WebClient와 WebRequest는 .NET에서 더는 권하지 않는 클래스가 됐다.
올리기는 두 가지다. 파일 내용을 그대로 본문으로 보내는 것(PUT)과 폼으로 보내는 것(multipart).
Invoke-RestMethod $url -Method Put -InFile ./app.zip
Invoke-RestMethod $url -Method Post -Form @{
description = 'nightly build'
file = Get-Item ./app.zip
}
FTP에 대해
옛 글 둘이 FTP였다. 지금은 권하지 않는다. FTP는 암호와 내용을 암호화하지 않고 보내며, 그때 쓴 FtpWebRequest도 .NET에서 폐기 예정이다. 파일을 옮길 일은 SSH 위에서 한다.
scp ./app.zip talsu@server1:/tmp/
Copy-Item ./app.zip -Destination /tmp/ -ToSession $session # PowerShell 원격 세션
네트워크 어댑터 (Windows)
2010년에는 WMI의 Win32_NetworkAdapter를 찾아 Enable()과 Disable()을 불렀다. 지금 Windows에는 전용 명령이 있다. 조회는 누구나 되고, 끄고 켜는 것은 관리자 권한으로 한다.
Get-NetAdapter
Disable-NetAdapter -Name 'Wi-Fi' -Confirm:$false
Enable-NetAdapter -Name 'Wi-Fi'
Restart-NetAdapter -Name '이더넷'
어댑터 이름은 Windows의 표시 언어를 따른다. 한국어 Windows에서 유선 어댑터는 Ethernet이 아니라 이더넷이다. 먼저 Get-NetAdapter로 이름을 확인한다. 무슨 일이 일어날지만 보려면 -WhatIf를 붙인다.
Get-NetIPAddress, Get-NetRoute, Resolve-DnsName, Test-NetConnection도 같은 계열이다. 이 명령들은 Windows에만 있다. 리눅스와 macOS의 PowerShell에는 없으므로 그쪽에서는 ip, dig 같은 운영체제의 도구를 부른다. 여러 운영체제에서 돌아야 하는 스크립트라면 앞에서 본 Test-Connection과 .NET의 [System.Net.Dns]처럼 어디에나 있는 것을 쓴다.
[System.Net.Dns]::GetHostAddresses('example.com')
다음 글: 콘솔 다루기