While debugging a web app locally, one might need access to i.e. the database on a server. This can easily be achieved on macOS via
ssh -L 5432:127.0.0.1:5432 user@domain.com -N
I tried to make this work as a XojoScript before starting the debug process.
var result as string
result = DoShellCommand("ssh -L 5432:127.0.0.1:5432 user@domain.com -N")
But this obviously doesn’t work, as this script ends in an endless loop. Does anyone have an idea how this can be achieved? Running the bash command asynchronously doesn’t seem to help either.
fwiw… there is a mbs plug-in that allows connection via ssh
1 Like
unfortunately ending up in an endless loop as well. I bet I’m getting something completely wrong …
The problem with doing this in a post-build script is that the shell goes out of scope and terminates the connection. Instead, I suggest doing this in the Open event of your app, wrapped in #if DebugBuild pragmas. I just did this for a user about two weeks ago. Make a properties on the App class called:
SSHShell as Shell
tunnelDidOpen as Boolean
…add the following code to the Open event…
#if DebugBuild
sshshell = New shell
AddHandler sshshell.DataAvailable, AddressOf Shell_DataAvailable
sshshell.ExecuteMode = shell.ExecuteModes.Asynchronous
Dim cmd As String = "ssh -o ConnectTimeout=15 user@domain.com -L 5432:127.0.0.1:5432 -N -v &"
sshshell.Execute(cmd)
// to let the ssh tunnel get established
Dim timeout As Integer = Ticks + 60*10
While Ticks < timeout And Not tunnelDidOpen
app.DoEvents(100)
Wend
If Ticks >= timeout Then
// Couldn't establish the SSH Tunnel
Dim response As String = sshshell.Result
Break
quit(1)
End If
#EndIf DebugBuild
…and the following method:
Private Sub Shell_DataAvailable(obj As Shell)
Static data As String
data = data + obj.ReadAll
If InStr(data,"Entering interactive session.") > 0 Then
tunnelDidOpen = True
End If
End Sub
When you run your app, the tunnel will be started and when it closes, the shell will close and take the tunnel with it.
Edit: I should note that I did this in a Web project where DoEvents is okay in the Opening event. If this were a desktop project, I would suggest instead using a Timer and call a second method to finish launching your app.
1 Like
One word: Brilliant!!
Thank you so much! Works perfectly fine.
For deploying my app from macOS to my linux web server on the internet, I’m using the following Build Script, set to run only for “release”. I called the script “deployToServer” and it has to be positioned after Build in the Linux Build Settings in the Xojo IDE:
var result as string
result = DoShellCommand("/Users/jmu/xojo/myapp/deploy.sh")
showUrl("https://myapp.mydomain.com")
The deploy.sh file looks like the following:
#!/bin/sh
echo "STOP myapp Services"
ssh user@domain.com 'sudo systemctl stop myapp.service'
rsync -avz --delete /Users/jmu/xojo/myapp/Builds\ -\ myappLinux\ 64\ bit/myapp/ user@domain.com:/var/www/html/nmyapp/
echo "START myapp Services"
ssh user@domain.com 'sudo systemctl start myapp.service'
exit 0
This bash script stops the running app service on the server, then it deletes the existing content and rsynchs all the data from the build folder to the webserver and then restarts the app service on the server.
Disclaimer: perhaps one needs to adjust the owner and the rights after the rsync, but in my case it is working out-of-the-box.
Prerequisites: you need to run your app via a service. @Tim_Parnell has a script helping you on the necessary steps.