I'm trying to make a script that does 2 things: (1) starts a proxy and (2) runs a rails console with pry and a custom prompt
The problem is that I can't figure out how to prevent Ctrl+C interrupts from reaching the proxy process.
Here's what I've tried:
- Trap
INTandTERMsignals at several different parts of execution - Generating a bash script with the proxy command and running that
- Running a separate script that runs the proxy job and the console/pry code
Nothing has worked so far.
If you have any suggestions, they would be greatly appreciated.
Here's a test script to try it out. Here's what you'll need for it:
pryinstalled- The script in a
railsapp root folder - To run
chmod +xon it so it's executable
#!/usr/bin/env ruby
class TestInterrupt
include Process
include Signal
def start
override_interrupt
start_script
start_console
exit
end
private
attr_reader :bash_job, :console_job
def override_interrupt
trap("INT") { puts "global INT. Run `!!!`, `quit`, or `exit` to terminate" }
trap("TERM") { puts "global TERM. Run `!!!`, `quit`, or `exit` to terminate" }
puts "=== Trapping global INT, TERM ==="
end
def start_script
@bash_job = fork do
trap("INT") { puts "bash_job INT" }
trap("TERM") { puts "bash_job TERM" }
puts "=== Trapping bash_job INT, TERM ==="
exec("echo Starting shell script && sleep 5 && echo Ending shell script")
end
Process.detach(@bash_job)
end
def start_console
@console_job = fork do
trap("INT") { puts "console_job INT" }
trap("TERM") { puts "console_job TERM" }
puts "=== Trapping console INT, TERM ==="
exec console_code
end
puts "=== Starting rails console (PID: console_job) ==="
wait(console_job)
end
def console_code
<<~BASH
rails runner '#{pry_code}'
BASH
end
def pry_code
<<~RUBY
require "pry"
pry_prompt = Pry.config.prompt
env_prompt = Pry::Helpers::Text.cyan("TestInterrupt")
Pry.config.prompt = [
proc { |*a| "\#{env_prompt} \#{pry_prompt.first.call(*a)}" },
proc { |*a| "\#{env_prompt} \#{pry_prompt.second.call(*a)}" },
]
Signal.trap("INT") { puts "inner INT" }
Signal.trap("TERM") { puts "inner TERM" }
puts "=== Trapping inner INT, TERM ==="
pry
RUBY
end
end
TestInterrupt.new.start
I know
INTis CTRL-C and CTRL-D is not a signal, so I can only debug this a little bit:Works, doesn't exit.
Doesn't work.
Works. Doesn't exit. Seeing is believing
watch -n 1 ps ft pts/4:Same thing with forks and execs and rails console:
One of them didn't make it: