Start and Kill the browser using Ruby - ruby

All,
I've got a problem which I need your help.
Using Ruby 1.9.3 in Windows, I'm starting a browser with the following command:
system('start http://www.stackoverflow.com')
I've tried getting the pid of the above system cmd in various ways like exec, Thread and IO.popen. But everytime I get the different PID which I assume the PID of the ruby process.
But I need the PID of the started browser, so that I can kill the browser once I finish my task at the end.
Note that I don't want to use Watir / Selenium or any automation tool.
Kindly help me on this.

Don't use start, it will spawn new window, open browser and then detach the window. Specify the browser path explicitly to solve the problem:
browser = %q{"C:\Program Files\Internet Explorer\iexplore.exe"}
pipe = IO.popen("#{browser} http://www.stackoverflow.com")
puts pipe.pid
Process.kill(9, pipe.pid)
Run start /? for help message of start command.

Related

Getting the pid from application process launched from open command on macOS

From within a Java application on macOS, I use Runtime.getRuntime().exec("open -Wn filename") to launch a file with its Default application, lets call it the Viewing application (for example AdobeReader for pdf). That works fine.
My issue arises, when I want to close the viewing application (for example AdobeReader).
The problem is, that the open command itself is launched as a child process of the java application, but the open command launches the viewing application not as a child process, but as child of launchd(1). As a result, when I destroy the process from the Java application, only the open process is killed, but not the viewing application.
So far I could not manage to get a PID of the viewing application process to be able to kill it. With a ps I can only find it, when I have the application name, but that is exactly what I do not have, since I want to let the os decide about the viewing application.
Does anybody have an idea how I could
get the pid of the application that is launched from the open command, without knowing the applications Name or UTI(remember, open is not the parent process of the viewing application)?
or
make the launched application a child of the open process, so I can kill it by killing the open process?
or
any other possible solution?
Your ideas are very much appreciated.
I found a solution by getting the pid from the lsof command, since I know the filename:
lsof -t filename
Having the pid, I can kill the process, means the Viewing Application:
kill $(lsof -t filename)
The full solution looks like this:
String killCommand = "kill $(lsof -t " + filename+ ")";
ProcessBuilder builder = new ProcessBuilder("bash", "-c", killCommand);
builder.start();
Not very pretty, but it does the job.

Trying to exit Ruby processes

When I attempt to exit ruby processes, namely, specs, rails console, and binding.pry calls, there are two options: ctrl+c, ctrl+z, or if things are really stuck, open a separate tab and killall ruby. However, when I ctrl+c the first time, the terminal outputs Exiting... Interrupt again to exit immediately. but hangs permanently. If I ctrl+c again to force exit, it successfully exits. However, from that point on, I can no longer see what I'm typing into the shell. So if I type ls, the line will still appear blank, but if I hit enter, it will successfully execute the ls command.
When I ctrl+z, it manages to stop the process successfully. However, after doing this a few times, I wind up with a bunch of ruby processes running, which seem to block running new ruby processes. In this scenario, killall ruby does nothing (nor does any derivative such as looking up by pid). I have to open activity monitor (mac) and force quit each proc individually.
Any ideas how I managed to get myself into this/how to resolve it?
Killing all your Ruby instances is a shotgun approach; you might hit targets you didn't intend, so I suggest to avoid it.
When your shell doesn't show what you're typing any more you need to (blindly) enter reset to reset the terminal.
Ctrl+Z doesn't kill your process, it just get's suspended. You should get an output that tells you a job number, like:
[1] + 95295 suspended man reset
Here, 1 is the job number. You can then resume the command by typing fg %<jobnumber>, in this example fg %1. Or you can kill it with kill -9 %<jobnumber>, like kill -9 %1.

Close program in shell script with pkill

I open a browser in a shell script. After opening the browser, I want to close it in my script with
pkill browser
The problem is commands after opening browser are not executed until I manually close the browser, so I can't close it in the script. Any solutions?
You might also (it does not always work, depending on how many childs the browser forks) record the PID of the started background browser and not use pkill:
browser &
BROWSER_PID=$!
# something
kill "$BROWSER_PID"
How about run the command that invoke the browser in background (&):
open_browser &
# wait .. (ex. sleep 10)
pkill browser

Running command in background using cygwin from Windows cmd

I use cygwin from my Windows command line, I've always done everything quite happily except being able to run something in the background (i.e. putting & at the end of a command).
Just to give you more context, I want to be able to start a Mercurial web server and still be able to keep using the command line window and even closing it without killing the server. For example:
>hg serve &
listening at http://localhost:8000/ (bound to *:8000)
>echo "Still able to do this"
Any workarounds to this?
I had a similar problem running Apache, finally I used cygstart, it's like CMD start:
cygstart --hide /c/apache/bin/httpd.exe
In this case, it will run Apache as an background proccess thanks to the --hide option
Found the solution:
start <command> /B
start is a windows command, do a help start for more info
Alternatively and for my case
hg serve --daemon
or
hg serve -d
will do the trick

Can a standalone ruby script (windows and mac) reload and restart itself?

I have a master-workers architecture where the number of workers is growing on a weekly basis. I can no longer be expected to ssh or remote console into each machine to kill the worker, do a source control sync, and restart. I would like to be able to have the master place a message out on the network that tells each machine to sync and restart.
That's where I hit a roadblock. If I were using any sane platform, I could just do:
exec('ruby', __FILE__)
...and be done. However, I did the following test:
p Process.pid
sleep 1
exec('ruby', __FILE__)
...and on Windows, I get one ruby instance for each call to exec. None of them die until I hit ^C on the window in question. On every platform I tried this on, it is executing the new version of the file each time, which I have verified this by making simple edits to the test script while the test marched along.
The reason I'm printing the pid is to double-check the behavior I'm seeing. On windows, I am getting a different pid with each execution - which I would expect, considering that I am seeing a new process in the task manager for each run. The mac is behaving correctly: the pid is the same for every system call and I have verified with dtrace that each run is trigging a call to the execve syscall.
So, in short, is there a way to get a windows ruby script to restart its execution so it will be running any code - including itself - that has changed during its execution? Please note that this is not a rails application, though it does use activerecord.
After trying a number of solutions (including the one submitted by Byron Whitlock, which ultimately put me onto the path to a satisfactory end) I settled upon:
IO.popen("start cmd /C ruby.exe #{$0} #{ARGV.join(' ')}")
sleep 5
I found that if I didn't sleep at all after the popen, and just exited, the spawn would frequently (>50% of the time) fail. This is not cross-platform obviously, so in order to have the same behavior on the mac:
IO.popen("xterm -e \"ruby blah blah blah\"&")
The classic way to restart a program is to write another one that does it for you. so you spawn a process to restart.exe <args>, then die or exit; restart.exe waits until the calling script is no longer running, then starts the script again.

Resources