Merge branch 'master' into python-subprocess
This commit is contained in:
commit
435e33e23e
3 changed files with 164 additions and 25 deletions
|
|
@ -383,8 +383,8 @@ research that.
|
|||
|
||||
Vimspector's tools are intended to automate your existing process for setting
|
||||
this up rather than to offer batteries-included approach. Ultimately, all
|
||||
vimspector is going to do is run your commands over SSH and co-ordinate with the
|
||||
adapter.
|
||||
vimspector is going to do is run your commands over SSH, or docker, and
|
||||
co-ordinate with the adapter.
|
||||
|
||||
### Python (debugpy) Example
|
||||
|
||||
|
|
@ -394,7 +394,9 @@ and connect to it using debugpy.
|
|||
|
||||
The usage pattern is to hit `<F5>`, enter `host` (the host where your app runs),
|
||||
`account` (the account it runs under), and `port` (a port that will be opened on
|
||||
the remote host). Vimspector then orchestrates the various tools to set you up.
|
||||
the remote host). Vimspector also supports exec'ing into Docker run containers
|
||||
with `container` (the container name or id your app is running in).
|
||||
Vimspector then orchestrates the various tools to set you up.
|
||||
|
||||
```json
|
||||
|
||||
|
|
@ -405,7 +407,7 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
|
|||
"host": "${host}",
|
||||
"launch": {
|
||||
"remote": {
|
||||
"host": "${host}", // Remote host to ssh to (mandatory)
|
||||
"host": "${host}", // Remote host to ssh to (mandatory if not using container)
|
||||
"account": "${account}", // User to connect as (optional)
|
||||
|
||||
// Optional.... Manual additional arguments for ssh
|
||||
|
|
@ -417,7 +419,7 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
|
|||
// %CMD% replaced with the remote-cmdLine configured in the launch
|
||||
// configuration. (mandatory)
|
||||
"launchCommmand": [
|
||||
"python", "-m", "debugpy", "--listen 0.0.0.0:${port}",
|
||||
"python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"%CMD%"
|
||||
]
|
||||
|
||||
|
|
@ -432,14 +434,8 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
|
|||
},
|
||||
"attach": {
|
||||
"remote": {
|
||||
"host": "${host}", // Remote host to ssh to (mandatory)
|
||||
"host": "${host}", // Remote host to ssh to (mandatory if not using container)
|
||||
"account": "${account}", // User to connect as (optional)
|
||||
|
||||
// Optional.... Manual additional arguments for ssh
|
||||
// "ssh": {
|
||||
// "args": [ "-o", "StrictHostKeyChecking=no" ]
|
||||
// },
|
||||
|
||||
// Command to get the PID of the process to attach (mandatory)
|
||||
"pidCommand": [
|
||||
//
|
||||
|
|
@ -453,7 +449,7 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
|
|||
// Command to attach the debugger; %PID% replaced with output of
|
||||
// pidCommand above (mandatory)
|
||||
"attachCommand": [
|
||||
"python", "-m", "debugpy", "--listen 0.0.0.0:${port}",
|
||||
"python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"--pid", "%PID%"
|
||||
]
|
||||
|
||||
|
|
@ -522,7 +518,7 @@ the remote host). Vimspector then orchestrates the various tools to set you up.
|
|||
|
||||
### C-family (gdbserver) Example
|
||||
|
||||
This example uses vimspector to remotely luanch or attach to a binary using
|
||||
This example uses vimspector to remotely launch or attach to a binary using
|
||||
`gdbserver` and then instructs vscode-cpptools to attach to that `gdbserver`.
|
||||
|
||||
The appraoch is very similar to the above for python, just that we use gdbserver
|
||||
|
|
@ -610,6 +606,117 @@ and have to tell cpptools a few more options.
|
|||
}
|
||||
```
|
||||
|
||||
### Docker Example
|
||||
|
||||
This example uses vimspector to remotely launch or attach to a docker container
|
||||
port.
|
||||
|
||||
``` json
|
||||
{
|
||||
"adapters": {
|
||||
"python-remote": {
|
||||
"port": "${port}",
|
||||
"launch": {
|
||||
"remote": {
|
||||
"container": "${container}", // Docker container id or name to exec into to.
|
||||
|
||||
// Command to launch the debugee and attach the debugger;
|
||||
// %CMD% replaced with the remote-cmdLine configured in the launch
|
||||
// configuration. (mandatory)
|
||||
"launchCommmand": [
|
||||
"python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"%CMD%"
|
||||
]
|
||||
|
||||
// Optional alternative to launchCommmand (if you need to run multiple
|
||||
// commands)
|
||||
// "launchCommmands": [
|
||||
// [ /* first command */ ],
|
||||
// [ /* second command */ ]
|
||||
// ]
|
||||
|
||||
}
|
||||
},
|
||||
"attach": {
|
||||
"remote": {
|
||||
"container": "${container}", // Docker container id or name to exec into.
|
||||
// Command to get the PID of the process to attach (mandatory)
|
||||
// This command gets appended to "docker exec ${container}"
|
||||
"pidCommand": [
|
||||
//
|
||||
// Remember taht you can use ${var} to ask for input. I use this to
|
||||
// call a custom command to returm the PID for a named service, so
|
||||
// here's an examle:
|
||||
//
|
||||
"sh", "-c", "pgrep", "-f", "${filename}"
|
||||
],
|
||||
|
||||
// Command to attach the debugger; %PID% replaced with output of
|
||||
// pidCommand above (mandatory)
|
||||
"attachCommand": [
|
||||
"sh", "-c", "python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"--pid", "%PID%"
|
||||
]
|
||||
|
||||
// Optional alternative to attachCommand (if you need to run multiple
|
||||
// commands)
|
||||
// "attachCommands": [
|
||||
// [ /* first command */ ],
|
||||
// [ /* second command */ ]
|
||||
// ],
|
||||
|
||||
// Optional.... useful with buggy gdbservers to kill -TRAP %PID%
|
||||
// "initCompleteCommand": [
|
||||
// /* optional command to run after initialized */
|
||||
// ]
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"remote-launch": {
|
||||
"adapter": "python-remote",
|
||||
|
||||
"remote-request": "launch",
|
||||
"remote-cmdLine": [
|
||||
"${RemoteRoot}/${fileBasename}", "*${args}"
|
||||
],
|
||||
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "${RemoteRoot}"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"remote-attach": {
|
||||
"variables": {
|
||||
// Just an example of how to specify a variable manually rather than
|
||||
// vimspector asking for input from the user
|
||||
"FileName": "${fileName}"
|
||||
},
|
||||
|
||||
"adapter": "python-remote",
|
||||
"remote-request": "attach",
|
||||
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "${RemoteRoot}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Appendix: Configuration file format
|
||||
|
||||
The configuration files are text files which must be UTF-8 encoded. They
|
||||
|
|
|
|||
|
|
@ -78,8 +78,19 @@
|
|||
"properties": {
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"required": [ "host" ],
|
||||
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will ssh to 'account'@'host' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"host"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"container"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string",
|
||||
|
|
@ -87,7 +98,11 @@
|
|||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "Name of the remote host to connect to (via passwordless SSH). "
|
||||
"description": "Name of the remote host to connect to (via passwordless SSH)."
|
||||
},
|
||||
"container": {
|
||||
"type": "string",
|
||||
"description": "Name or container id of the docker run container to connect to (via docker exec -it)."
|
||||
},
|
||||
"pidCommand": {
|
||||
"type": "array",
|
||||
|
|
|
|||
|
|
@ -613,13 +613,13 @@ class DebugSession( object ):
|
|||
# e.g. expand variables when we use them, not all at once. This would
|
||||
# remove the whole %PID% hack.
|
||||
remote = atttach_config[ 'remote' ]
|
||||
ssh = self._GetSSHCommand( remote )
|
||||
remote_exec_cmd = self._GetRemoteExecCommand( remote )
|
||||
|
||||
# FIXME: Why does this not use self._GetCommands ?
|
||||
cmd = ssh + remote[ 'pidCommand' ]
|
||||
pid_cmd = remote_exec_cmd + remote[ 'pidCommand' ]
|
||||
|
||||
self._logger.debug( 'Getting PID: %s', cmd )
|
||||
pid = subprocess.check_output( cmd ).decode( 'utf-8' ).strip()
|
||||
self._logger.debug( 'Getting PID: %s', pid_cmd )
|
||||
pid = subprocess.check_output( pid_cmd ).decode( 'utf-8' ).strip()
|
||||
self._logger.debug( 'Got PID: %s', pid )
|
||||
|
||||
if not pid:
|
||||
|
|
@ -628,7 +628,7 @@ class DebugSession( object ):
|
|||
return
|
||||
|
||||
if 'initCompleteCommand' in remote:
|
||||
initcmd = ssh + remote[ 'initCompleteCommand' ][ : ]
|
||||
initcmd = remote_exec_cmd + remote[ 'initCompleteCommand' ][ : ]
|
||||
for index, item in enumerate( initcmd ):
|
||||
initcmd[ index ] = item.replace( '%PID%', pid )
|
||||
|
||||
|
|
@ -638,7 +638,7 @@ class DebugSession( object ):
|
|||
commands = self._GetCommands( remote, 'attach' )
|
||||
|
||||
for command in commands:
|
||||
cmd = ssh + command[ : ]
|
||||
cmd = remote_exec_cmd + command[ : ]
|
||||
|
||||
for index, item in enumerate( cmd ):
|
||||
cmd[ index ] = item.replace( '%PID%', pid )
|
||||
|
|
@ -665,11 +665,11 @@ class DebugSession( object ):
|
|||
|
||||
if 'remote' in run_config:
|
||||
remote = run_config[ 'remote' ]
|
||||
ssh = self._GetSSHCommand( remote )
|
||||
remote_exec_cmd = self._GetRemoteExecCommand( remote )
|
||||
commands = self._GetCommands( remote, 'run' )
|
||||
|
||||
for index, command in enumerate( commands ):
|
||||
cmd = ssh + command[ : ]
|
||||
cmd = remote_exec_cmd + command[ : ]
|
||||
full_cmd = []
|
||||
for item in cmd:
|
||||
if isinstance( command_line, list ):
|
||||
|
|
@ -694,6 +694,23 @@ class DebugSession( object ):
|
|||
|
||||
return ssh
|
||||
|
||||
def _GetDockerCommand( self, remote ):
|
||||
docker = [ 'docker', 'exec' ]
|
||||
docker.append( remote[ 'container' ] )
|
||||
return docker
|
||||
|
||||
def _GetRemoteExecCommand( self, remote ):
|
||||
is_ssh_cmd = any( key in remote for key in [ 'ssh',
|
||||
'host',
|
||||
'account', ] )
|
||||
is_docker_cmd = 'container' in remote
|
||||
|
||||
if is_ssh_cmd:
|
||||
return self._GetSSHCommand( remote )
|
||||
elif is_docker_cmd:
|
||||
return self._GetDockerCommand( remote )
|
||||
raise ValueError( 'Could not determine remote exec command' )
|
||||
|
||||
|
||||
def _GetCommands( self, remote, pfx ):
|
||||
commands = remote.get( pfx + 'Commands', None )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue