ruby on rails to command line interaction - ruby-on-rails

Very new to Ruby so please try to look past my ignorance. Cause I have no idea what I am talking about currently. However I know the ability to do what I want exists. Essentially I have some JAVA server side that can be used via a command line. I am trying to figure out where and how to begin with communicating in the same notion of me typing it out in the cli without actually typing it out to the cli. Basicly I want to pass the commands like as if I was using the CLI but Im not. Does that make sense?
Its for a CLI to UI conversion. I have seen the process done RoR to JAVA in such a fashion but where to begin I couldn't tell ya to save my life.

First of all, I would suggest at least looking into jRuby, which can interact with java classes as though they were ruby classes.
If you still want the cli integration, the naive approach is extremely simple, all you need to do is wrap your cli command in backticks (`) and it will execute the command as if you typed it into a shell, and return the results as a string.
If you need to do this very frequently, check out https://github.com/rtomayko/posix-spawn which is a much more efficient way of doing it then the backtick approach.

If the Java program has a command prompt of its own, look into popen. It allows you to open a subprocess as an I/O stream allowing you to send it input and read its output. If all you need is to start the process and get its output then use backticks as suggested by Matt Briggs:
output = `the-command-to-start-the-java-program`

Related

Run ruby code with eval and it's gems, rails

I'm using eval to run some code (that is in a database, there are no ruby files) but this code requires some gems. How would I go about running the code? Maybe there's a better way than eval?
To give a bit more context, I have a toggle button in the view that switches a boolean to true or false in the model. This is possible for every "piece of code".
When it gets switched to true, the code starts running in a thread that never stops, and when it's switched to false this kills the thread.
I'm just trying to make the thread run the code right now.
I'm pretty new to rails so maybe there's a much better way than doing it by hand like what I'm doing, but I've tried googling some typical threading stuff and it's used for sending mail or other such things. Not for something that never stops unless told to (ie toggle the button that switches the boolean to false).
Thanks in advance.
It sounds like you need the code to be prefixed with gem imports -- which probably requires a bundler environment to load those gems in the first place.
Since the code is stored in the database directly, you could prefix them with another column / constant that does all the gem loading for you.
If the gems are already installed via bundler on the server, try prefixing your code with bundle exec. To do this, you'll need to write the code to a temporary file location first.
To install the proper gems, that's part of your build/deploy processes.
To run a script in the rails environment, which sounds like what you need, you can use rails runner. E.g. something like:
rails runner lib/scripts/my_script_to_run.rb
This script would then get the required code from the database, and already have the correct (rails) context to be able to run the code.
Or maybe even more appropriate:
rails runner <your-ruby-code-here>
See documentation
An alternative is to look at background-jobs, which seem imho a better fit to this problem. Check out the guides for ActiveJob : http://edgeguides.rubyonrails.org/active_job_basics.html
The advantage of using background-jobs:
it is a proven way of working
some adapters include extra managerial tools
you do not have to manage threads yourself
there is a clean way to describe jobs in code and queue jobs
using existing concepts/solutions is also easier to explain to other developers
There is a variety of adapters available and some of the easiest just store the jobs in the current database. For a full list see http://edgeapi.rubyonrails.org/classes/ActiveJob/QueueAdapters.html, I would recommend starting with Que or DelayedJob. Your flow would change a little in that case: I would queue a job, and instead of looping, I would requeue as long as the toggle is not switched. But of course: I do not know your precise use-case so your approach could be equally valid or better.

How do I call a script from a script in Redis?

I want to run many Lua scripts one after another, without allowing any commands to run in between. I also need to pass the result of the first script to the second one, etc.
I've solved the problem temporarily by putting all my scripts in one file. However, the second script modifies a key returned by the first script. Because of this, putting everything in one file violates the EVAL command semantics as all the keys that the second script uses should be passed using the KEYS array.
Actually, it is possible. Redis has an undocumented feature that allows doing just that. The basic premise is that once you EVAL or SCRIPT LOAD a script, you can call that script from another one by invoking the function f_<sha1 hash> (where sha1 hash is the SHA1 hash of the first script).
Credit for this goes to Josiah Carlson (who, in turn, gives credit to Nathan Fritz). Dr. Josiah was kind enough to provide all the details in here (this file is a part of a Python package that helps managing Lua scripts that call other scripts).
You cannot do that. However violating EVAL semantics this way should not be a problem as long as you do not use Redis Cluster.

Turning on dbg tracing on a remote node?

When running our Erlang application in our system tests, I sometimes want to turn on and capture a debug trace.
The Erlang node is started using a relx start script (called as _rel/bin/foo foreground), so I don't have any control over the startup options. The system test runner (written in Python) is capturing stdout from the node.
How do I connect to an Erlang node, using -remsh, turn on dbg-tracing, and have that output written to stdout on the original node? And how do I do this all in a Python-friendly way (though I'm happy to write an escript if that'll make it easier).
To complicate this further, the relx generated release doesn't include the runtime_tools library, so dbg: isn't actually available, so I'll also add this question.
There are quite few way you could do that. All depends on what you are familiar with, and what your use case is.
I would start from doing everything by hand. That way you have greatest control on that's going one, and how effects look like (if you are turning too much debugging or not enough). That's I'm most familiar with, and in the end you almost always will have to connect to remote shell and do something by hand (from my experience)
One feature of dbg that not too many people talk about i ability of saving/loading trace pasterns from files. I find those easiest way to store and share debugging information in between sessions; but lack of readability might be too big trade-off.
You don't have to use dbg if you don't want to interfere with your live system too much. You could use erlang:trace which is given by default, but you must be cautious about state you leave your VM in (dbg should turn off all tracing upon exit; with erlang:trace that's your responsibility)
If you debug session is part of python script, writng escript and calling it from python would be my way to go. You just have to remember that escripts are run in new VM, and -remsh will not allow you to just run your code on other VM. You will have to use rpc module for that.
Since you are using application is released you might look into logging. One might assume that there should already be some logging in place, quite possible lager which is somewhat standard in Erlang, and which have possibility to change logging level during runtime.
Personally I would try some mix of first and last option, and just experiment.

Using Process.spawn as a replacement for Process.fork

My development environment is a Windows machine running ruby 1.9.3p125 (RubyInstaller) and rails 3.2.8.
One issue that comes up, time and again, when using third-party gems, is the lack of fork() on Windows. This has recently hindered my ability to use pretty much any distributed test running gem (like these), due to their dependence on fork.
Some older questions on StackOverflow have attempted to find a resolution to this same problem, but were either before the addition of Process.spawn into ruby, or were from people forced to use an older version of Ruby, for some other reason.
One of the proposed solutions is to use Cygwin to gain fork() support, which is simply out of the question for this - I think I would prefer to switch to Linux fully, before that.
Another proposed solution has been using the win32-process gem to gain fork() support. Fork support was removed from the most recent version (0.7.0), and using the next oldest version (0.6.6), which does (sort-of) support fork does not seem to work, at least for running any of the distributed testing gems that I have tried (Spork, Parallel tests, Hydra, Specjour, practically all of them). Interestingly enough, the author of the gem alludes, in the readme, to Process.spawn being an acceptable workaround for Process.fork.
I have seen a lot of information either implying, or stating outright that spawn can be used as a replacement for fork, on Windows, with Ruby 1.9. I have spent a fair amount of time playing with this, basically trying to replace Process.fork with Process.spawn in several of the referenced gems, with no success. It seems to me that perhaps the behavior is similar, but not exactly the same. For example, it is unclear whether spawn actually copies the entire process in the same way the fork does, or simply creates a new process with the supplied arguments. It is also unclear as to whether the spawn method even accepts another ruby method as an argument, or only a system command. The docs seem to imply that it is only a command, but a method seems to work (sort-of), but I may be doing things incorrectly. I think that for some things, fork was just used to create a "cheap thread", in previous ruby versions that did not support threading. However, it seems that these distributed testing gems may legitimately rely on the full functionality of fork(), in order to maintain the project state, and to not load the whole ruby environment for every test. This is a bit outside of my normal programming duties and experience, so I may be making some incorrect assumptions.
So, my question is, can Process.spawn be used relatively simply to achieve the same outcome as Process.fork, in all cases? I am beginning to suspect not, but if so, could someone please post an example of how one would go about making the transformation?
EDIT: There is one common use case of fork() that can be replaced with spawn() -- the fork()--exec() combo. A lot of older (and modern) UNIX applications, when they want to spawn another process, will first fork, and then make an exec call (exec replaces the current process with another). This doesn't actually need fork(), which is why it can be replaced with spawn(). So, this:
if(!fork())
exec("dir")
end
can be replaced with:
Process.spawn("dir")
If any of the gems are using fork() like this, the fix is easy. Otherwise, it is almost impossible.
EDIT: The reason why win32-process' implementation of fork() doesn't work is that (as far as I can tell from the docs), it basically is spawn(), which isn't fork() at all.
No, I don't think it can be done. You see, Process.spawn creates a new process with the default blank state and native code. So, while I can do something like Process.spawn('dir') will start a new, blank process running dir, it won't clone any of the current process' state. It's only connection to your program is the parent - child connection.
You see, fork() is a very low level call. For example, on Linux, what fork() basically does is this: first, a new process is created with exactly cloned register state. Then, Linux does a copy-on-write reference to all of the parent process' pages. Linux then clones some other process flags. Obviously, all of these operations can only be done by the kernel, and the Windows kernel doesn't have the facilities to do that (and can't be patched to either).
Technically, only native programs need the OS for some sort of fork()-like support. Any layer of code needs the cooperation of the layer above it to do something like fork(). So while native C code needs the cooperation of the kernel to fork, Ruby theoretically only needs the cooperation of the interpreter to do a fork. However, the Ruby interpreter does not have a snapshot/restore feature, which would be necessarily to implement a fork. Because of this, normal Ruby fork is achieved by forking the interpreter itself, not the Ruby program.
So, while if you could patch the Ruby interpreter to add a stop/start and snapshot/restore feature, you could do it, but otherwise? I don't think so.
So what are your options? This is what I can think of:
Patch the Ruby interpreter
Patch the code that uses fork() to maybe use threads or spawn
Get a UNIX (I suggest this one)
Use Cygwin
Edit 1:
I wouldn't suggest using Cygwin's fork, as it involves special Cygwin process tables, there is no copy-on-write, which makes it very inefficient. Also, it involves a lot of jumping back and forth and a lot of copying. Avoid it if possible. Also, because Windows provides no facilities to copy address spaces, forks are very likely to fail, and will quite a lot of the time (see here).

Learning Erlang? speedbump thread, common, small problems

I just want know all the small problems that got between you and your final solution when you were new to Erlang.
For example, here are the first speedbumps I had:
Use controlling_process(Socket, Pid) if you spawn off in multiple threads. Right packet to the right thread.
You going to start talking to another server? Remember to net_adm:ping('car#bsd-server'). in the shell. Else no communication will get through.
Timer:sleep(10), if you want to do nothing. Always useful when debugging.
Learning to browse the standard documentation
Once you learn how the OTP documentation is organised it becomes much easier to find what you're looking for (you tend to need to learn which applications provide which modules or kinds of modules).
Also just browsing the documentation for applications is often quite rewarding - I've discovered lots of really useful code this way - sys, dbg, toolbar, etc.
The difference between shell erlang and module erlang
Shell erlang is a slightly different dialect to module erlang. You can't define module functions (only funs), you need to load record definitions in order to work with records (rr/1) and so on. Learning how to write erlang code in terms of anonymous functions is somewhat tricky, but is essential for working on production systems with a remote shell.
Learning the interaction between the shell and {start,spawn}_link ed processes - when you run some shell code that crashes (raises an exception), the shell process exits and will broadcast exit signals to anything you linked to. This will in turn shut down that new gen_server you're working on. ("Why does my server process keep disappearing?")
The difference between erlang expressions and guard expressions
Guard expressions (when clauses) are not Erlang expressions. They may look similar, but they're quite different. Guards cannot call arbitrary erlang functions, only guard functions (length/1, the type tests, element/2 and a few others specified in the OTP documentation). Guards succeed or fail and don't have side effects. Erlang expressions on the other hand can do what they like.
Code loading
Working out when and how code upgrades work, the incantation to get a gen_server to upgrade to the latest version of a callback module (code:load(Mod), sys:suspend(Pid), sys:change_code(Pid, Mod, undefined, undefined), sys:resume(Pid).).
The code server path (code:get_path/0) - I can't count how many times I ran into undefined function errors that turned out to be me forgetting to add an ebin directory to the code search path.
Building erlang code
Working out a useful combination of emake (make:all/0 and erl -make) and gnu make took quite a long time (about three years so far :).
My current favourite makefiles can be seen at http://github.com/archaelus/esmtp/tree/master
Erlang distribution
Getting node names, dns, cookies and all the rest right in order to be able to net_adm:ping/1 the other node. This takes practise.
Remote shell IO intricacies
Remembering to pass group_leader() to io:format calls run on the remote node so that the output appears in your shell rather than mysteriously disappearing (I think the SASL report browser rb still has a problem with sending some of its output to the wrong node when used over a remote shell connection)
Integrating it into msvc 6, so I could use the editor, and see the results in the output window.
I created a tool, with
command - path to erlc
arguments - +debug_info $(FileName)$(FileExt)
Initial Directory - $(fileDir)
Checked Use Output Window.
Debugging is hard. All I know to do is to stick calls to "error_logger:info_msg" in my code.
Docs have been spotty -- they're correct, but very very terse.
This is my own fault, but: I started coding before I understood eunit, so a lot of my code is harder to test than it should be.
controlling_process()
Use controlling_process(Socket, Pid) if you spawn off in multiple threads. Right packet to the right thread.
net_adm:ping()
You going to start talking to another server? Remember to net_adm:ping('car#bsd-server'). in the shell. Else no communication will get through.
timer:sleep()
Pause for X ms.
The thing that took me the most time to get my head around was just the idea of structuring my code entirely around function calls and message passing. The rest of it either just fell out from there (spawning, remote nodes) or felt like the usual stuff you've got to learn in any new language (syntax, stdlib).

Resources