Window에서 psmux.exe를 {홈}/.local/bin 으로 이동
This commit is contained in:
1 parent
e01eb5db9c
commit
eeeffccd91
1 file changed
+138
-65
+138
-65
@@ -46,6 +46,12 @@ function ErrExit { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 }
|
|||||||
# Constants
|
# Constants
|
||||||
# ────────────────────────────────────────────
|
# ────────────────────────────────────────────
|
||||||
$ConfFile = Join-Path $env:USERPROFILE '.tmux.conf'
|
$ConfFile = Join-Path $env:USERPROFILE '.tmux.conf'
|
||||||
|
$LocalBin = Join-Path $env:USERPROFILE '.local\bin'
|
||||||
|
|
||||||
|
# Ensure $LocalBin directory exists
|
||||||
|
if (-not (Test-Path $LocalBin)) {
|
||||||
|
New-Item -ItemType Directory -Path $LocalBin -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
# ────────────────────────────────────────────
|
# ────────────────────────────────────────────
|
||||||
# Step 0: Ensure OpenSSH Server (비활성화됨)
|
# Step 0: Ensure OpenSSH Server (비활성화됨)
|
||||||
@@ -79,94 +85,161 @@ $ConfFile = Join-Path $env:USERPROFILE '.tmux.conf'
|
|||||||
|
|
||||||
|
|
||||||
# ────────────────────────────────────────────
|
# ────────────────────────────────────────────
|
||||||
# Step 1: Install tmux
|
# Step 1: Install tmux (psmux) and copy *.exe to ~/.local/bin
|
||||||
# ────────────────────────────────────────────
|
# ────────────────────────────────────────────
|
||||||
Info "Installing tmux..."
|
Info "Installing tmux (psmux)..."
|
||||||
|
|
||||||
$tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue
|
$localTmux = Join-Path $LocalBin 'tmux.exe'
|
||||||
if ($tmuxCmd) {
|
$localPsmux = Join-Path $LocalBin 'psmux.exe'
|
||||||
$currentVer = & tmux -V 2>$null
|
|
||||||
if (-not $currentVer) { $currentVer = "unknown" }
|
|
||||||
Info "tmux is already installed ($currentVer). Skipping installation."
|
|
||||||
} else {
|
|
||||||
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
|
|
||||||
ErrExit "winget is required. Install it from the Microsoft Store or https://learn.microsoft.com/en-us/windows/package-manager/winget/"
|
|
||||||
}
|
|
||||||
|
|
||||||
winget install psmux --accept-package-agreements --accept-source-agreements 2>&1 | Out-Null
|
$needsInstall = $true
|
||||||
Success "tmux (psmux) installed via winget"
|
if (Test-Path $localTmux) {
|
||||||
}
|
$currentVer = & $localTmux -V 2>$null
|
||||||
|
if (-not $currentVer) { $currentVer = & $localTmux --version 2>$null }
|
||||||
# ────────────────────────────────────────────
|
if ($currentVer) {
|
||||||
# Verify tmux is available and add to PATH permanently if needed
|
Info "tmux is already installed in $LocalBin ($currentVer)."
|
||||||
# ────────────────────────────────────────────
|
$needsInstall = $false
|
||||||
$tmuxBin = $null
|
|
||||||
|
|
||||||
# 1) Try current PATH
|
|
||||||
$tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue
|
|
||||||
if ($tmuxCmd) {
|
|
||||||
$tmuxBin = $tmuxCmd.Source
|
|
||||||
}
|
|
||||||
|
|
||||||
# 2) Refresh PATH from registry (winget may have added paths)
|
|
||||||
if (-not $tmuxBin) {
|
|
||||||
$env:Path = [System.Environment]::GetEnvironmentVariable('Path', 'User') + ';' + [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
|
|
||||||
$tmuxCmd = Get-Command tmux -ErrorAction SilentlyContinue
|
|
||||||
if ($tmuxCmd) {
|
|
||||||
$tmuxBin = $tmuxCmd.Source
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# 3) Search common locations where winget installs tmux / psmux
|
if ($needsInstall) {
|
||||||
if (-not $tmuxBin) {
|
$wingetAvailable = [bool](Get-Command winget -ErrorAction SilentlyContinue)
|
||||||
|
$installed = $false
|
||||||
|
|
||||||
|
if ($wingetAvailable) {
|
||||||
|
try {
|
||||||
|
Info "Running winget install psmux..."
|
||||||
|
winget install psmux --accept-package-agreements --accept-source-agreements 2>&1 | Out-Null
|
||||||
|
Success "tmux (psmux) installed via winget"
|
||||||
|
$installed = $true
|
||||||
|
} catch {
|
||||||
|
Warn "winget install failed: $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fallback to direct download from GitHub releases if winget is missing or failed
|
||||||
|
if (-not $installed) {
|
||||||
|
Info "Downloading psmux directly from GitHub releases..."
|
||||||
|
$arch = $env:PROCESSOR_ARCHITECTURE
|
||||||
|
$psmuxZipAsset = if ($arch -eq "ARM64") { "psmux-v3.3.8-windows-arm64.zip" } else { "psmux-v3.3.8-windows-x64.zip" }
|
||||||
|
$downloadUrl = "https://github.com/psmux/psmux/releases/download/v3.3.8/$psmuxZipAsset"
|
||||||
|
|
||||||
|
try {
|
||||||
|
$latestRel = Invoke-RestMethod -Uri "https://api.github.com/repos/psmux/psmux/releases/latest" -UseBasicParsing -TimeoutSec 5
|
||||||
|
$assetPattern = if ($arch -eq "ARM64") { "psmux-*-windows-arm64.zip" } else { "psmux-*-windows-x64.zip" }
|
||||||
|
$matchedAsset = $latestRel.assets | Where-Object { $_.name -like $assetPattern } | Select-Object -First 1
|
||||||
|
if ($matchedAsset) {
|
||||||
|
$downloadUrl = $matchedAsset.browser_download_url
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
# Use fallback URL
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpZip = Join-Path $env:TEMP "psmux_$(Get-Random).zip"
|
||||||
|
try {
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
Invoke-WebRequest -Uri $downloadUrl -OutFile $tmpZip -UseBasicParsing
|
||||||
|
$ProgressPreference = 'Continue'
|
||||||
|
|
||||||
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||||
|
$archive = [System.IO.Compression.ZipFile]::OpenRead($tmpZip)
|
||||||
|
foreach ($entry in $archive.Entries) {
|
||||||
|
if ($entry.Name.EndsWith(".exe", [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||||
|
$destPath = Join-Path $LocalBin $entry.Name
|
||||||
|
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($entry, $destPath, $true)
|
||||||
|
Success "Extracted $($entry.Name) to $LocalBin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$archive.Dispose()
|
||||||
|
$installed = $true
|
||||||
|
} catch {
|
||||||
|
Warn "Failed to download psmux archive: $_"
|
||||||
|
} finally {
|
||||||
|
if (Test-Path $tmpZip) { Remove-Item $tmpZip -Force -ErrorAction SilentlyContinue }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search for winget-installed *.exe files and copy them to $LocalBin
|
||||||
$searchDirs = @(
|
$searchDirs = @(
|
||||||
(Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Links'),
|
|
||||||
(Join-Path $env:LOCALAPPDATA 'Programs\psmux'),
|
(Join-Path $env:LOCALAPPDATA 'Programs\psmux'),
|
||||||
(Join-Path $env:LOCALAPPDATA 'Programs\tmux-windows'),
|
(Join-Path $env:LOCALAPPDATA 'Programs\tmux-windows'),
|
||||||
|
(Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Links'),
|
||||||
'C:\Program Files\psmux',
|
'C:\Program Files\psmux',
|
||||||
'C:\Program Files\tmux-windows',
|
'C:\Program Files\tmux-windows',
|
||||||
'C:\Program Files (x86)\psmux',
|
'C:\Program Files (x86)\psmux',
|
||||||
'C:\Program Files (x86)\tmux-windows'
|
'C:\Program Files (x86)\tmux-windows'
|
||||||
)
|
)
|
||||||
foreach ($dir in $searchDirs) {
|
|
||||||
if (Test-Path $dir) {
|
$wingetPackages = Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages'
|
||||||
foreach ($exe in @('tmux.exe', 'psmux.exe')) {
|
if (Test-Path $wingetPackages) {
|
||||||
$candidate = Join-Path $dir $exe
|
$pkgDirs = Get-ChildItem -Path $wingetPackages -Directory -Filter "*psmux*" -Recurse -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
|
||||||
if (Test-Path $candidate) { $tmuxBin = $candidate; break }
|
if ($pkgDirs) { $searchDirs += $pkgDirs }
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($tmuxBin) { break }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Recurse under WinGet/Packages for tmux or psmux
|
foreach ($dir in $searchDirs) {
|
||||||
if (-not $tmuxBin -and (Test-Path (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages'))) {
|
if (Test-Path $dir) {
|
||||||
foreach ($filter in @('tmux.exe', 'psmux.exe')) {
|
$candidateExes = Get-ChildItem -Path $dir -Filter "*.exe" -ErrorAction SilentlyContinue
|
||||||
$found = Get-ChildItem -Path (Join-Path $env:LOCALAPPDATA 'Microsoft\WinGet\Packages') -Recurse -Filter $filter -ErrorAction SilentlyContinue | Select-Object -First 1
|
if ($candidateExes) {
|
||||||
if ($found) { $tmuxBin = $found.FullName; break }
|
foreach ($exe in $candidateExes) {
|
||||||
|
if ($exe.Name -in @('tmux.exe', 'psmux.exe', 'pmux.exe')) {
|
||||||
|
Copy-Item -Path $exe.FullName -Destination (Join-Path $LocalBin $exe.Name) -Force
|
||||||
|
Success "Copied $($exe.Name) to $LocalBin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (Test-Path $localTmux) { break }
|
||||||
|
}
|
||||||
|
|
||||||
|
# If tmux.exe is still not in $LocalBin but psmux.exe is, create tmux.exe copy
|
||||||
|
if (-not (Test-Path $localTmux) -and (Test-Path $localPsmux)) {
|
||||||
|
Copy-Item -Path $localPsmux -Destination $localTmux -Force
|
||||||
|
Success "Created tmux.exe alias from psmux.exe in $LocalBin"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tmuxBin) {
|
# ────────────────────────────────────────────
|
||||||
# Add tmux's directory to PATH for this session
|
# Verify tmux in $LocalBin and add $LocalBin to PATH permanently
|
||||||
$tmuxDir = Split-Path $tmuxBin
|
# ────────────────────────────────────────────
|
||||||
if ($env:Path -notlike "*$tmuxDir*") {
|
$tmuxBin = $null
|
||||||
$env:Path = "$tmuxDir;$env:Path"
|
if (Test-Path $localTmux) {
|
||||||
Info "Added $tmuxDir to PATH for this session"
|
$tmuxBin = $localTmux
|
||||||
}
|
} elseif (Test-Path $localPsmux) {
|
||||||
Success "tmux is available: $tmuxBin"
|
$tmuxBin = $localPsmux
|
||||||
|
}
|
||||||
|
|
||||||
# Permanently add tmux's directory to user PATH if not already there
|
# Add $LocalBin to current session PATH
|
||||||
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
|
if ($env:Path -notlike "*$LocalBin*") {
|
||||||
if ($userPath -notlike "*$tmuxDir*") {
|
$env:Path = "$LocalBin;$env:Path"
|
||||||
[System.Environment]::SetEnvironmentVariable('Path', "$tmuxDir;$userPath", 'User')
|
Info "Added $LocalBin to PATH for this session"
|
||||||
Success "Added $tmuxDir to user PATH permanently (takes effect on next login)"
|
}
|
||||||
} else {
|
|
||||||
Info "$tmuxDir already in user PATH"
|
# Permanently add $LocalBin to User PATH if not already present
|
||||||
|
$userPath = [System.Environment]::GetEnvironmentVariable('Path', 'User')
|
||||||
|
if (-not $userPath) { $userPath = "" }
|
||||||
|
$pathParts = $userPath -split ';' | Where-Object { $_ -ne '' }
|
||||||
|
$normalizedLocalBin = $LocalBin.TrimEnd('\')
|
||||||
|
$alreadyInUserPath = $false
|
||||||
|
foreach ($p in $pathParts) {
|
||||||
|
if ($p.Trim().TrimEnd('\') -eq $normalizedLocalBin) {
|
||||||
|
$alreadyInUserPath = $true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $alreadyInUserPath) {
|
||||||
|
$newUserPath = if ($userPath) { "$normalizedLocalBin;$userPath" } else { $normalizedLocalBin }
|
||||||
|
[System.Environment]::SetEnvironmentVariable('Path', $newUserPath, 'User')
|
||||||
|
Success "Added $LocalBin to User PATH permanently"
|
||||||
} else {
|
} else {
|
||||||
Warn "tmux was not found in PATH after installation."
|
Info "$LocalBin is already in User PATH"
|
||||||
Warn "Please restart your terminal or add tmux's directory to your PATH manually."
|
}
|
||||||
|
|
||||||
|
if ($tmuxBin) {
|
||||||
|
Success "tmux is available: $tmuxBin"
|
||||||
|
} else {
|
||||||
|
Warn "tmux was not found in $LocalBin after installation."
|
||||||
|
Warn "Please check if winget or manual installation succeeded."
|
||||||
}
|
}
|
||||||
|
|
||||||
# ────────────────────────────────────────────
|
# ────────────────────────────────────────────
|
||||||
|
|||||||
Reference in new issue
Block a user