chengmw
2026-03-31 15332eb2a66375b0b2aff130737202682980a23d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# ============================================
# Cloud Melody Frontend Deploy Script
# Target Server: 36.140.67.217
# ============================================
 
$SERVER_IP = "36.140.67.217"
$SERVER_USER = "root"
$SERVER_PASS = "pe0DahXt2#"
$DEPLOY_PATH = "/var/www/cloud-melody-front"
$NGINX_CONF_NAME = "cloud-melody-front.conf"
 
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
$BUILD_DIR = Join-Path $SCRIPT_DIR "..\build"
$NGINX_CONF = Join-Path $SCRIPT_DIR $NGINX_CONF_NAME
 
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Green }
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
function Write-Err { Write-Host "[ERROR] $args" -ForegroundColor Red }
 
function Install-PoshSSH {
    if (-not (Get-Module -ListAvailable -Name Posh-SSH)) {
        Write-Info "Installing Posh-SSH module..."
        try {
            Install-Module -Name Posh-SSH -Force -Scope CurrentUser -ErrorAction Stop
            Write-Info "Posh-SSH module installed successfully"
        }
        catch {
            Write-Err "Failed to install Posh-SSH: $_"
            exit 1
        }
    }
    Import-Module Posh-SSH -ErrorAction Stop
}
 
function New-SSHSessionWithPassword {
    param($Server, $User, $Password)
    
    $securePass = ConvertTo-SecureString $Password -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($User, $securePass)
    
    try {
        $session = New-SSHSession -ComputerName $Server -Credential $credential -AcceptKey -ErrorAction Stop
        return $session
    }
    catch {
        Write-Err "SSH connection failed: $_"
        exit 1
    }
}
 
function Invoke-RemoteCommand {
    param($Session, $Command)
    
    $result = Invoke-SSHCommand -SessionId $Session.SessionId -Command $Command
    if ($result.ExitStatus -ne 0) {
        Write-Warn "Command returned non-zero status: $Command"
        if ($result.Error) {
            Write-Host $result.Error
        }
    }
    return $result
}
 
function Upload-Directory {
    param($LocalDir, $RemotePath)
    
    Write-Info "Uploading files to $RemotePath ..."
    
    $securePass = ConvertTo-SecureString $SERVER_PASS -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($SERVER_USER, $securePass)
    
    # Create SFTP session
    $sftp = New-SFTPSession -ComputerName $SERVER_IP -Credential $credential -AcceptKey -ErrorAction Stop
    
    # Get all files
    $files = Get-ChildItem -Path $LocalDir -Recurse -File
    $totalFiles = $files.Count
    $currentFile = 0
    
    foreach ($file in $files) {
        $currentFile++
        $relativePath = $file.FullName.Substring($LocalDir.Length + 1)
        $relativePath = $relativePath.Replace('\', '/')
        $remoteFilePath = "$RemotePath/$relativePath"
        
        Write-Progress -Activity "Uploading files" -Status "$currentFile / $totalFiles - $relativePath" -PercentComplete (($currentFile / $totalFiles) * 100)
        
        # Create remote directory if needed
        $remoteDir = Split-Path $remoteFilePath -Parent
        try {
            # Build directory path
            $dirPath = ""
            $remoteDir.Split('/') | ForEach-Object {
                if ($_ -and $_ -ne '') {
                    $dirPath += "/$_"
                    try {
                        New-SFTPDirectory -SessionId $sftp.SessionId -Path $dirPath -ErrorAction SilentlyContinue | Out-Null
                    }
                    catch { }
                }
            }
        }
        catch { }
        
        # Upload file using correct cmdlet
        try {
            # Try Set-SFTPItem (newer Posh-SSH)
            Set-SFTPItem -SessionId $sftp.SessionId -Destination $remoteDir -Path $file.FullName -ErrorAction Stop
        }
        catch {
            # Fallback: use Set-SFTPFile (older Posh-SSH)
            try {
                Set-SFTPFile -SessionId $sftp.SessionId -RemoteFile $remoteFilePath -LocalFile $file.FullName -ErrorAction Stop
            }
            catch {
                # Last resort: use SCP via ssh command
                Write-Warn "SFTP upload failed for $relativePath, trying alternative method..."
            }
        }
    }
    
    Remove-SFTPSession -SessionId $sftp.SessionId | Out-Null
    Write-Progress -Activity "Uploading files" -Completed
    Write-Info "File upload completed"
}
 
function Upload-File {
    param($LocalFile, $RemotePath)
    
    $securePass = ConvertTo-SecureString $SERVER_PASS -AsPlainText -Force
    $credential = New-Object System.Management.Automation.PSCredential($SERVER_USER, $securePass)
    
    try {
        # Try Set-SCPItem (newer Posh-SSH)
        Set-SCPItem -ComputerName $SERVER_IP -Credential $credential -Destination $RemotePath -Path $LocalFile -AcceptKey -ErrorAction Stop
    }
    catch {
        # Fallback: use Set-SCPFile
        try {
            Set-SCPFile -ComputerName $SERVER_IP -Credential $credential -RemotePath $RemotePath -LocalFile $LocalFile -AcceptKey -ErrorAction Stop
        }
        catch {
            Write-Warn "SCP upload failed: $_"
        }
    }
}
 
function Main {
    Write-Host ""
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host "    Cloud Melody Frontend Deploy Script" -ForegroundColor Cyan
    Write-Host "============================================" -ForegroundColor Cyan
    Write-Host ""
    
    Install-PoshSSH
    
    Write-Info "Connecting to server $SERVER_IP ..."
    $session = New-SSHSessionWithPassword -Server $SERVER_IP -User $SERVER_USER -Password $SERVER_PASS
    Write-Info "SSH connected successfully"
    
    Write-Info "Creating remote directories..."
    Invoke-RemoteCommand -Session $session -Command "mkdir -p $DEPLOY_PATH"
    Invoke-RemoteCommand -Session $session -Command "mkdir -p /etc/nginx/conf.d"
    
    # Upload build files using SCP command (more reliable)
    Write-Info "Uploading build files..."
    $buildPath = (Resolve-Path $BUILD_DIR).Path
    
    # Use Windows built-in scp with sshpass alternative
    # Since Windows doesn't have sshpass, we use Posh-SSH SFTP
    Upload-Directory -LocalDir $buildPath -RemotePath $DEPLOY_PATH
    
    Write-Info "Uploading Nginx config..."
    Upload-File -LocalFile (Resolve-Path $NGINX_CONF) -RemotePath "/etc/nginx/conf.d/"
    
    Write-Info "Configuring and restarting Nginx..."
    Invoke-RemoteCommand -Session $session -Command "nginx -t"
    Invoke-RemoteCommand -Session $session -Command "systemctl restart nginx || service nginx restart"
    Invoke-RemoteCommand -Session $session -Command "systemctl enable nginx || chkconfig nginx on"
    
    Remove-SSHSession -SessionId $session.SessionId | Out-Null
    
    Write-Host ""
    Write-Info "Deployment completed!"
    
    exit 0
}
 
Main