mirror of https://github.com/docusealco/docuseal
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
661 lines
26 KiB
661 lines
26 KiB
[](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster) [](https://github.com/ruby/debug/actions/workflows/protocol.yml)
|
|
|
|
# debug.rb
|
|
|
|
This library provides debugging functionality to Ruby (MRI) 2.7 and later.
|
|
|
|
This debug.rb is the replacement of traditional lib/debug.rb standard library, which is implemented by `set_trace_func`.
|
|
New debug.rb has several advantages:
|
|
|
|
* Fast: No performance penalty on non-stepping mode and non-breakpoints.
|
|
* [Remote debugging](#remote-debugging): Support remote debugging natively.
|
|
* UNIX domain socket (UDS)
|
|
* TCP/IP
|
|
* Integration with rich debugger frontends
|
|
|
|
| Frontend | [Console](https://github.com/ruby/debug#invoke-as-a-remote-debuggee) | [VSCode](https://github.com/ruby/debug#vscode-integration) | [Chrome DevTool](#chrome-devtool-integration) |
|
|
| ----------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
| Connection | UDS, TCP/IP | UDS, TCP/IP | TCP/IP |
|
|
| Requirement | None | [vscode-rdbg](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) | Chrome |
|
|
|
|
* Extensible: application can introduce debugging support in several ways:
|
|
* By `rdbg` command
|
|
* By loading libraries with `-r` command line option
|
|
* By calling Ruby's method explicitly
|
|
* Misc
|
|
* Support threads (almost done) and Ractors (TODO).
|
|
* Support suspending and entering the debug console with `Ctrl-C` at most of timing.
|
|
* Show parameters on backtrace command.
|
|
* Support recording and replay debugging.
|
|
|
|
# Installation
|
|
|
|
```console
|
|
$ gem install debug
|
|
```
|
|
|
|
Alternatively, specify `-Ipath/to/debug/lib` in `RUBYOPT`, or as a Ruby command-line option
|
|
This is especially useful for debugging this gem during development.
|
|
|
|
If using Bundler, add the following to your Gemfile:
|
|
|
|
```ruby
|
|
gem "debug", ">= 1.0.0"
|
|
```
|
|
|
|
(The version constraint is important; `debug < 1.0.0` is an older, abandoned gem that is completely different from this product.)
|
|
|
|
# HOW TO USE
|
|
|
|
To use the debugger, you will do roughly the following steps:
|
|
|
|
1. Set breakpoints.
|
|
2. Run a program with the debugger.
|
|
3. At the breakpoint, enter the debugger console.
|
|
4. Use debug commands.
|
|
* [Evaluate Ruby expressions](#evaluate) (e.g. `p lvar` to see the local variable `lvar`).
|
|
* [Query the program status](#information) (e.g. `info` to see information about the current frame).
|
|
* [Control program flow](#control-flow) (e.g. move to another line with `step`, to the next line with `next`).
|
|
* [Set another breakpoint](#breakpoint) (e.g. `catch Exception` to set a breakpoint that'll be triggered when `Exception` is raised).
|
|
* [Activate tracing in your program](#trace) (e.g. `trace call` to trace method calls).
|
|
* [Change the configuration](#configuration-1) (e.g. `config set no_color true` to disable coloring).
|
|
* Continue the program (`c` or `continue`) and goto 3.
|
|
|
|
## Invoke with the debugger
|
|
|
|
There are several ways to invoke the debugger, depending on your needs, preferences, and the environment.
|
|
|
|
### Modify source code with [`binding.break`](#bindingbreak-method) (similar to `binding.pry` or `binding.irb`)
|
|
|
|
If you can modify the source code, you can use the debugger by adding `require 'debug'` at the top of your program and putting [`binding.break`](#bindingbreak-method) method into lines where you want to stop as breakpoints.
|
|
This is similar to how `binding.pry` and `binding.irb` work.
|
|
|
|
`binding.break` has two aliases which do the same thing:
|
|
|
|
- `binding.b`
|
|
- `debugger`
|
|
|
|
After that, run the program as usual and you will enter the debug console at breakpoints you inserted.
|
|
|
|
The following is an example of the [`binding.break`](#bindingbreak-method) method.
|
|
|
|
```console
|
|
$ cat target.rb # Sample program
|
|
require 'debug'
|
|
|
|
a = 1
|
|
b = 2
|
|
binding.break # Program will stop here
|
|
c = 3
|
|
d = 4
|
|
binding.break # Program will stop here
|
|
p [a, b, c, d]
|
|
|
|
$ ruby target.rb # Run the program normally.
|
|
DEBUGGER: Session start (pid: 7604)
|
|
[1, 10] in target.rb
|
|
1| require 'debug'
|
|
2|
|
|
3| a = 1
|
|
4| b = 2
|
|
=> 5| binding.break # Now you can see it stops at this line
|
|
6| c = 3
|
|
7| d = 4
|
|
8| binding.break
|
|
9| p [a, b, c, d]
|
|
10|
|
|
=>#0 <main> at target.rb:5
|
|
|
|
(rdbg) info locals # You can show local variables
|
|
=>#0 <main> at target.rb:5
|
|
%self => main
|
|
a => 1
|
|
b => 2
|
|
c => nil
|
|
d => nil
|
|
|
|
(rdbg) continue # Continue the execution
|
|
[3, 11] in target.rb
|
|
3| a = 1
|
|
4| b = 2
|
|
5| binding.break
|
|
6| c = 3
|
|
7| d = 4
|
|
=> 8| binding.break # Again the program stops here
|
|
9| p [a, b, c, d]
|
|
10|
|
|
11| __END__
|
|
=>#0 <main> at target.rb:8
|
|
|
|
(rdbg) info locals # And you can see the updated local variables
|
|
=>#0 <main> at target.rb:8
|
|
%self => main
|
|
a => 1
|
|
b => 2
|
|
c => 3
|
|
d => 4
|
|
|
|
(rdbg) continue
|
|
[1, 2, 3, 4]
|
|
```
|
|
|
|
### Invoke the program from the debugger as a traditional debuggers
|
|
|
|
If you don't want to modify the source code, you can use the `rdbg` command (or `bundle exec rdbg`) to run the program with the debugger.
|
|
This is similar to how you'd launch a program with `ruby program.rb`.
|
|
Then you can set breakpoints with the debug command `break` (`b` for short).
|
|
|
|
```console
|
|
$ cat target.rb # Sample program
|
|
a = 1
|
|
b = 2
|
|
c = 3
|
|
d = 4
|
|
p [a, b, c, d]
|
|
|
|
$ rdbg target.rb # run like `ruby target.rb`
|
|
DEBUGGER: Session start (pid: 7656)
|
|
[1, 7] in target.rb
|
|
=> 1| a = 1
|
|
2| b = 2
|
|
3| c = 3
|
|
4| d = 4
|
|
5| p [a, b, c, d]
|
|
6|
|
|
7| __END__
|
|
=>#0 <main> at target.rb:1
|
|
|
|
(rdbg)
|
|
```
|
|
|
|
The `rdbg` command suspends the program at the beginning of the given script (`target.rb` in this case) and you can use debug commands to control execution from there.
|
|
`(rdbg)` is the console prompt.
|
|
Let's set breakpoints on line 3 and line 5 with `break` command (`b` for short).
|
|
|
|
```console
|
|
(rdbg) break 3 # set breakpoint at line 3
|
|
#0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
|
|
|
|
(rdbg) b 5 # set breakpoint at line 5
|
|
#1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
|
|
|
|
(rdbg) break # show all registered breakpoints
|
|
#0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
|
|
#1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
|
|
```
|
|
|
|
You can see that two breakpoints are registered.
|
|
Let's continue the program by using the `continue` command.
|
|
|
|
```console
|
|
(rdbg) continue
|
|
[1, 7] in target.rb
|
|
1| a = 1
|
|
2| b = 2
|
|
=> 3| c = 3
|
|
4| d = 4
|
|
5| p [a, b, c, d]
|
|
6|
|
|
7| __END__
|
|
=>#0 <main> at target.rb:3
|
|
|
|
Stop by #0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
|
|
|
|
(rdbg)
|
|
```
|
|
|
|
You can see that we stopped at line 3.
|
|
Let's see the local variables with the `info` command, and continue execution with the `continue`.
|
|
The program will then suspend at line 5 and you can use the `info` command again.
|
|
|
|
```console
|
|
(rdbg) info
|
|
=>#0 <main> at target.rb:3
|
|
%self => main
|
|
a => 1
|
|
b => 2
|
|
c => nil
|
|
d => nil
|
|
|
|
(rdbg) continue
|
|
[1, 7] in target.rb
|
|
1| a = 1
|
|
2| b = 2
|
|
3| c = 3
|
|
4| d = 4
|
|
=> 5| p [a, b, c, d]
|
|
6|
|
|
7| __END__
|
|
=>#0 <main> at target.rb:5
|
|
|
|
Stop by #1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
|
|
|
|
(rdbg) info
|
|
=>#0 <main> at target.rb:5
|
|
%self => main
|
|
a => 1
|
|
b => 2
|
|
c => 3
|
|
d => 4
|
|
|
|
(rdbg) continue
|
|
[1, 2, 3, 4]
|
|
```
|
|
|
|
NOTE: When using `rdbg` you can suspend your application with `C-c` (SIGINT) and enter the debug console.
|
|
It will help if you want to know what the program is doing.
|
|
|
|
### Use `rdbg` with commands written in Ruby
|
|
|
|
If you want to run an executable written in Ruby like `rake`, `rails`, `bundle`, `rspec`, and so on, you can use `rdbg -c` option.
|
|
|
|
* Without the `-c` option, `rdbg <name>` means that `<name>` is a Ruby script and it is invoked like `ruby <name>` with the debugger.
|
|
* With the `-c` option, `rdbg -c <name>` means that `<name>` is an executable in `PATH` and simply invokes it with the debugger.
|
|
|
|
Examples:
|
|
|
|
* `rdbg -c -- rails server`
|
|
* `rdbg -c -- bundle exec ruby foo.rb`
|
|
* `rdbg -c -- bundle exec rake test`
|
|
* `rdbg -c -- ruby target.rb` is the same as `rdbg target.rb`
|
|
|
|
NOTE: `--` is needed to separate the command line options for `rdbg` from the executable being invoked, and its options.
|
|
For example, `rdbg -c rake -T` would be parsed as `rdbg -c -T -- rake`, which is incorrect.
|
|
It should be `rdbg -c -- rake -T`.
|
|
|
|
NOTE: If you want to use Bundler (`bundle` executable), you need to add `gem 'debug'` to your `Gemfile`.
|
|
|
|
### Using VSCode
|
|
|
|
Like other languages, you can use this debugger on the VSCode.
|
|
|
|
1. Install [VSCode rdbg Ruby Debugger - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg)
|
|
2. Open `.rb` file (e.g. `target.rb`)
|
|
3. Register breakpoints with "Toggle breakpoint" in the Run menu (or type F9 key)
|
|
4. Choose "Start debugging" in "Run" menu (or type F5 key)
|
|
5. You will see a dialog "Debug command line" and you can choose your favorite command line you want to run.
|
|
6. Chosen command line is invoked with `rdbg -c`, and VSCode shows the details at breakpoints.
|
|
|
|
Please refer to [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/editor/debugging) for operations on VSCode.
|
|
|
|
You can configure the extension in `.vscode/launch.json`.
|
|
Please see the extension page for more details.
|
|
|
|
## Remote debugging
|
|
|
|
You can use this debugger as a remote debugger.
|
|
For example, it will help in the following situations:
|
|
|
|
* Your application does not run on TTY, and it is hard to use `binding.pry` or `binding.irb`.
|
|
* Your application is running on a Docker container, and there is no TTY.
|
|
* Your application is running as a daemon.
|
|
* Your application uses pipe for `STDIN` or `STDOUT`.
|
|
* Your application is running as a daemon and you want to query the running status (checking a backtrace and so on).
|
|
|
|
You can run your application as a remote debuggee, and the remote debugger console can attach to the debuggee anytime.
|
|
|
|
### Invoke as a remote debuggee
|
|
|
|
There are multiple ways to run your program as a debuggee:
|
|
|
|
| Stop at program start | [`rdbg` option](https://github.com/ruby/debug#rdbg---open-or-rdbg--o-for-short) | [require](https://github.com/ruby/debug#require-debugopen-in-a-program) | [debugger API](https://github.com/ruby/debug#start-by-method) |
|
|
| --------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
| Yes | `rdbg --open` | `require "debug/open"` | `DEBUGGER__.open` |
|
|
| No | `rdbg --open --nonstop` | `require "debug/open_nonstop"` | `DEBUGGER__.open(nonstop: true)` |
|
|
|
|
#### `rdbg --open` (or `rdbg -O` for short)
|
|
|
|
Launch a script with `rdbg --open target.rb` to run `target.rb` as a debuggee program.
|
|
It also opens the network port and suspends at the beginning of `target.rb`.
|
|
|
|
```console
|
|
$ rdbg --open target.rb
|
|
DEBUGGER: Session start (pid: 7773)
|
|
DEBUGGER: Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-7773)
|
|
DEBUGGER: wait for debugger connection...
|
|
```
|
|
|
|
By default, `rdbg --open` uses UNIX domain socket and generates the path name automatically (`/home/ko1/.ruby-debug-sock/ruby-debug-ko1-7773` in this case).
|
|
|
|
You can connect to the debuggee with `rdbg --attach` command (`rdbg -A` for short).
|
|
|
|
```console
|
|
$ rdbg -A
|
|
[1, 7] in target.rb
|
|
=> 1| a = 1
|
|
2| b = 2
|
|
3| c = 3
|
|
4| d = 4
|
|
5| p [a, b, c, d]
|
|
6|
|
|
7| __END__
|
|
=>#0 <main> at target.rb:1
|
|
|
|
(rdbg:remote)
|
|
```
|
|
|
|
If there are no other files in the default directory, `rdbg --attach` will automatically connect to the UNIX domain socket listed.
|
|
If there are multiple files, you need to specify which to use.
|
|
|
|
When `rdbg --attach` connects to the debuggee, you can use any debug commands (set breakpoints, continue the program, and so on) like the local debug console.
|
|
When a debuggee program exits, the remote console will also terminate.
|
|
|
|
NOTE: If you use the `quit` command, only the remote console exits and the debuggee program continues to run (and you can connect it again).
|
|
If you want to exit the debuggee program, use `kill` command.
|
|
|
|
If you want to use TCP/IP for remote debugging, you need to specify the port and host with `--port` like `rdbg --open --port 12345` and it binds to `localhost:12345`.
|
|
You can add an optional `--port_range` to try multiple ports in a reliable way.
|
|
For example, `rdbg --open --port 12345 --port_range 10` will try to bind to 12345, 12346, 12347,… until it finds an available port.
|
|
|
|
To connect to the debuggee, you need to specify the port.
|
|
|
|
```console
|
|
$ rdbg --attach 12345
|
|
```
|
|
|
|
If you want to choose the host to bind, you can use `--host` option.
|
|
Messages communicated between the debugger and the debuggee are *NOT* encrypted so please use remote debugging carefully.
|
|
|
|
#### `require 'debug/open'` in a program
|
|
|
|
If you can modify the program, you can open the debugging port by adding `require 'debug/open'` in the program.
|
|
|
|
If you don't want to stop the program at the beginning, you can also use `require 'debug/open_nonstop'`.
|
|
Using `debug/open_nonstop` is useful if you want to open a backdoor to the application.
|
|
However, it is also dangerous because it can become another vulnerability.
|
|
Please use it carefully.
|
|
|
|
By default, UNIX domain socket is used for the debugging port.
|
|
To use TCP/IP, you can set the `RUBY_DEBUG_PORT` environment variable.
|
|
|
|
```console
|
|
$ RUBY_DEBUG_PORT=12345 ruby target.rb
|
|
```
|
|
|
|
### Integration with external debugger frontend
|
|
|
|
You can attach with external debugger frontend with VSCode and Chrome.
|
|
|
|
```
|
|
$ rdbg --open=[frontend] target.rb
|
|
```
|
|
|
|
This will open a debug port and the `[frontend]` can attach to the port.
|
|
|
|
#### VSCode integration
|
|
|
|
([vscode-rdbg v0.0.9](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) or later is required)
|
|
|
|
If you don't run a debuggee Ruby process on VSCode, you can attach it to VSCode later with the following steps.
|
|
|
|
`rdbg --open=vscode` opens the debug port and tries to invoke the VSCode (`code` executable).
|
|
|
|
```console
|
|
$ rdbg --open=vscode target.rb
|
|
DEBUGGER: Debugger can attach via UNIX domain socket (/tmp/ruby-debug-sock-1000/ruby-debug-ko1-27706)
|
|
DEBUGGER: wait for debugger connection...
|
|
Launching: code /tmp/ruby-debug-vscode-20211014-27706-gd7e85/ /tmp/ruby-debug-vscode-20211014-27706-gd7e85/README.rb
|
|
DEBUGGER: Connected.
|
|
```
|
|
|
|
It tries to invoke the new VSCode window and VSCode will attach to the debuggee Ruby program automatically.
|
|
|
|
You can also use `open vscode` in a REPL.
|
|
|
|
```console
|
|
$ rdbg target.rb
|
|
[1, 8] in target.rb
|
|
1|
|
|
=> 2| p a = 1
|
|
3| p b = 2
|
|
4| p c = 3
|
|
5| p d = 4
|
|
6| p e = 5
|
|
7|
|
|
8| __END__
|
|
=>#0 <main> at target.rb:2
|
|
(rdbg) open vscode # command
|
|
DEBUGGER: wait for debugger connection...
|
|
DEBUGGER: Debugger can attach via UNIX domain socket (/tmp/ruby-debug-sock-1000/ruby-debug-ko1-28337)
|
|
Launching: code /tmp/ruby-debug-vscode-20211014-28337-kg9dm/ /tmp/ruby-debug-vscode-20211014-28337-kg9dm/README.rb
|
|
DEBUGGER: Connected.
|
|
```
|
|
|
|
If the machine which runs the Ruby process doesn't have a `code` executable on `$PATH`, the following message will be shown:
|
|
|
|
```console
|
|
(rdbg) open vscode
|
|
DEBUGGER: wait for debugger connection...
|
|
DEBUGGER: Debugger can attach via UNIX domain socket (/tmp/ruby-debug-sock-1000/ruby-debug-ko1-455)
|
|
Launching: code /tmp/ruby-debug-vscode-20211014-455-gtjpwi/ /tmp/ruby-debug-vscode-20211014-455-gtjpwi/README.rb
|
|
DEBUGGER: Can not invoke the command.
|
|
Use the command-line on your terminal (with modification if you need).
|
|
|
|
code /tmp/ruby-debug-vscode-20211014-455-gtjpwi/ /tmp/ruby-debug-vscode-20211014-455-gtjpwi/README.rb
|
|
|
|
If your application is running on a SSH remote host, please try:
|
|
|
|
code --remote ssh-remote+[SSH hostname] /tmp/ruby-debug-vscode-20211014-455-gtjpwi/ /tmp/ruby-debug-vscode-20211014-455-gtjpwi/README.rb
|
|
|
|
```
|
|
|
|
Note that you can attach with `rdbg --attach` and continue REPL debugging.
|
|
|
|
#### Chrome DevTool integration
|
|
|
|
Using `rdbg --open=chrome` will show the following message:
|
|
|
|
```console
|
|
$ rdbg target.rb --open=chrome
|
|
DEBUGGER: Debugger can attach via TCP/IP (127.0.0.1:43633)
|
|
DEBUGGER: With Chrome browser, type the following URL in the address-bar:
|
|
|
|
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=127.0.0.1:57231/b32a55cd-2eb5-4c5c-87d8-b3dfc59d80ef
|
|
|
|
DEBUGGER: wait for debugger connection...
|
|
```
|
|
|
|
Type the following in the address bar on Chrome browser, and you can continue the debugging with chrome browser:
|
|
|
|
```txt
|
|
devtools://devtools/bundled/inspector.html?v8only=true&panel=sources&ws=127.0.0.1:57231/b32a55cd-2eb5-4c5c-87d8-b3dfc59d80ef`
|
|
```
|
|
|
|
Similar to VSCode, you can use `open chrome` to open the debugger in Chrome.
|
|
|
|
For more information about how to use Chrome debugging, [see the devtools docs](https://developer.chrome.com/docs/devtools/).
|
|
|
|
## Configuration
|
|
|
|
You can configure the debugger's behavior with debug commands and environment variables.
|
|
When the debug session is started, some [initialization scripts](#initial-scripts) (e.g., `~/.rdbgrc`) are loaded, allowing you to configure the debugger's behavior to your needs and preferences.
|
|
|
|
### Configuration list
|
|
|
|
You can configure the debugger's behavior with environment variables and `config` command.
|
|
Each configuration has an environment variable and a name which can be specified by `config` command.
|
|
|
|
```
|
|
# configuration example
|
|
config set log_level INFO
|
|
config set no_color true
|
|
```
|
|
|
|
<% cat = nil; DEBUGGER__::CONFIG_SET.each do |key, (env, desc, _, default)| %>
|
|
<% /\A(\w+): (.+)/ =~ desc; if cat != $1; cat = 1 %>
|
|
* <%= $1 %>
|
|
<% cat = $1; end %> * `<%= env %>` (`<%= key %>`): <%= default ? "#{$2} (default: #{default})" : $2 %><% end %>
|
|
|
|
There are other environment variables:
|
|
|
|
* `NO_COLOR`: If the value is set, set `RUBY_DEBUG_NO_COLOR` ([NO_COLOR: disabling ANSI color output in various Unix commands](https://no-color.org/)).
|
|
* `RUBY_DEBUG_ENABLE`: If the value is `0`, do not enable debug.gem feature.
|
|
* `RUBY_DEBUG_ADDED_RUBYOPT`: Remove this value from `RUBYOPT` at first. This feature helps loading debug.gem with `RUBYOPT='-r debug/...'`, and you don't want to derive it to child processes. In this case, you can set `RUBY_DEBUG_ADDED_RUBYOPT='-r debug/...'` (same value), and this string will be deleted from `RUBYOPT` at first.
|
|
* `RUBY_DEBUG_EDITOR` or `EDITOR`: An editor used by `edit` debug command.
|
|
* `RUBY_DEBUG_BB`: Define `Kernel#bb` method which is alias of `Kernel#debugger`.
|
|
|
|
### Initial scripts
|
|
|
|
If there is a `~/.rdbgrc` file it is loaded as an initialization script (which contains debug commands) when the debug session is started.
|
|
|
|
* `RUBY_DEBUG_INIT_SCRIPT` environment variable can specify the initial script file.
|
|
* You can specify the initial script with `rdbg -x initial_script` (like gdb's `-x` option).
|
|
|
|
Initial scripts are useful to write your favorite configurations.
|
|
For example, you can set breakpoints with `break file:123` in `~/.rdbgrc`.
|
|
|
|
If there is a `~/.rdbgrc.rb` file it is also loaded as a Ruby script when the debug session is started.
|
|
|
|
## Debug command on the debug console
|
|
|
|
On the debug console, you can use the following debug commands.
|
|
|
|
There are additional features:
|
|
|
|
* `<expr>` without debug command is almost the same as `pp <expr>`.
|
|
* If the input line `<expr>` does *NOT* start with any debug command, the line `<expr>` will be evaluated as a Ruby expression, and the result will be printed with `pp` method.
|
|
So that the input `foo.bar` is the same as `pp foo.bar`.
|
|
* If `<expr>` is recognized as a debug command, of course, it is not evaluated as a Ruby expression but is executed as debug command.
|
|
For example, you can not evaluate such single-letter local variables `i`, `b`, `n`, `c` because they are single-letter debug commands. Use `p i` instead.
|
|
* For consistency, the author (Koichi Sasada) recommends using the `p`, `pp`, or `eval` command to evaluate the Ruby expression every time.
|
|
* `Enter` without any input repeats the last command (useful when repeating `step`s) for some commands.
|
|
* `Ctrl-D` is equal to `quit` command.
|
|
* [debug command compare sheet - Google Sheets](https://docs.google.com/spreadsheets/d/1TlmmUDsvwK4sSIyoMv-io52BUUz__R5wpu-ComXlsw0/edit?usp=sharing)
|
|
|
|
You can use the following debug commands.
|
|
Each command should be written in 1 line.
|
|
The `[…]` notation means this part can be eliminated. For example, `s[tep]` means `s` or `step` is a valid command. `ste` is not valid.
|
|
The `<…>` notation means the argument.
|
|
|
|
<%= DEBUGGER__.help %>
|
|
|
|
### Using IRB as the Debug Console
|
|
|
|
Starting from version `v1.9`, you can now use IRB as the debug console. This integration brings additional features such as:
|
|
|
|
* Autocompletion
|
|
* Support for multi-line input
|
|
* Access to commands not available in `debug`, like `show_source` or `show_doc`
|
|
* [Configurable command aliases](https://docs.ruby-lang.org/en/master/IRB.html#module-IRB-label-Command+Aliases)
|
|
|
|
To switch to the IRB console, simply use the `irb` command in the debug console.
|
|
|
|
Once activated, you'll notice the prompt changes to:
|
|
|
|
```console
|
|
irb:rdbg(main):001>
|
|
```
|
|
|
|
If you want to make IRB the default console for all sessions, configure the `irb_console` setting by either:
|
|
|
|
* Setting the `RUBY_DEBUG_IRB_CONSOLE=true` environment variable
|
|
* Or adding `config set irb_console 1` to your `~/.rdbgrc`
|
|
|
|
To disable the IRB console in the current session, execute `config set irb_console 0` in the console.
|
|
|
|
## Debugger API
|
|
|
|
### Start debugging
|
|
|
|
#### Start by requiring a library
|
|
|
|
You can start debugging without `rdbg` command by requiring the following libraries:
|
|
|
|
* `require 'debug'`: Same as `rdbg --nonstop --no-sigint-hook`.
|
|
* `require 'debug/start'`: Same as `rdbg`.
|
|
* `require 'debug/open'`: Same as `rdbg --open`.
|
|
* `require 'debug/open_nonstop'`: Same as `rdbg --open --nonstop`.
|
|
|
|
You need to require one of them at the very beginning of the application.
|
|
Using `ruby -r` (for example `ruby -r debug/start target.rb`) is another way to invoke with debugger.
|
|
|
|
NOTE: Until Ruby 3.0, there is old `lib/debug.rb` in the standard library.
|
|
`lib/debug.rb` was not maintained well in recent years, and the purpose of this library is to rewrite old `lib/debug.rb` with recent techniques.
|
|
|
|
So, if this gem is not installed, or if the `Gemfile` doesn't include this gem and `bundle exec` is used, you will see the following output:
|
|
|
|
```console
|
|
$ ruby -r debug -e0
|
|
.../2.7.3/lib/ruby/2.7.0/x86_64-linux/continuation.so: warning: callcc is obsolete; use Fiber instead
|
|
Debug.rb
|
|
Emacs support available.
|
|
|
|
.../2.7.3/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:162: if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
|
|
(rdb:1)
|
|
```
|
|
|
|
#### Start by method
|
|
|
|
After loading `debug/session`, you can start a debug session with the following methods.
|
|
They are convenient if you want to specify debug configurations in your program.
|
|
|
|
* `DEBUGGER__.start(**kw)`: start debug session with local console.
|
|
* `DEBUGGER__.open(**kw)`: open debug port with configuration (without configurations open with UNIX domain socket).
|
|
* `DEBUGGER__.open_unix(**kw)`: open debug port with UNIX domain socket.
|
|
* `DEBUGGER__.open_tcp(**kw)`: open debug port with TCP/IP.
|
|
|
|
For example:
|
|
|
|
```ruby
|
|
require 'debug/session'
|
|
DEBUGGER__.start(no_color: true, # disable colorize
|
|
log_level: 'INFO') # Change log_level to INFO
|
|
|
|
... # your application code
|
|
```
|
|
|
|
### `binding.break` method
|
|
|
|
`binding.break` (or `binding.b`) sets a breakpoint at that line.
|
|
It also has several keywords.
|
|
|
|
If `do: 'command'` is specified, the debugger suspends the program, runs the `command` as a debug command, and continues the program.
|
|
It is useful if you only want to call a debug command and don't want to stop there.
|
|
For example:
|
|
|
|
```ruby
|
|
def initialize
|
|
@a = 1
|
|
binding.b do: 'info \n watch @a'
|
|
end
|
|
```
|
|
|
|
In this case, execute the `info` command, then register a watch breakpoint for `@a` and continue to run.
|
|
You can also use `;;` instead of `\n` to separate your commands.
|
|
|
|
If `pre: 'command'` is specified, the debugger suspends the program and runs the `command` as a debug command, and keeps suspended.
|
|
It is useful if you have operations before suspend.
|
|
For example:
|
|
|
|
```ruby
|
|
def foo
|
|
binding.b pre: 'p bar()'
|
|
...
|
|
end
|
|
```
|
|
|
|
In this case, you can see the result of `bar()` every time you stop there.
|
|
|
|
## rdbg command help
|
|
|
|
```console
|
|
<%= `exe/rdbg --help` %>
|
|
```
|
|
|
|
# Additional Resources
|
|
|
|
- [From byebug to ruby/debug](https://st0012.dev/from-byebug-to-ruby-debug) by Stan Lo - A migration guide for `byebug` users.
|
|
- [ruby/debug cheatsheet](https://st0012.dev/ruby-debug-cheatsheet) by Stan Lo
|
|
|
|
# Contributing
|
|
|
|
Bug reports and pull requests are welcome on GitHub at [https://github.com/ruby/debug]().
|
|
This debugger is not mature so your feedback will help us.
|
|
|
|
Please also check the [contributing guideline](/CONTRIBUTING.md).
|
|
|
|
# Acknowledgement
|
|
|
|
* Some tests are based on [deivid-rodriguez/byebug: Debugging in Ruby 2](https://github.com/deivid-rodriguez/byebug)
|
|
* Several codes in `server_cdp.rb` are based on [geoffreylitt/ladybug: Visual Debugger](https://github.com/geoffreylitt/ladybug)
|