Although Ruby is my language of choice right now, I don't mind so much if anyone answers this with examples in another language, as I am more interested in the concept.
If I have a script running In the background; how would I program that script so that I could pass data input to it whilst it is still running?
If I were running it in a terminal In the foreground, the solution would be as simple as creating a Thread, and killing that Thread upon STDIN at which point a seperate function would invoke to handle the User Input. However considering that this script is running in the background, that method is not practical. I assume that arguments are the best way to interface with the program (although I could be wrong on that).
Of course there are plenty of methods to pass data to the background program, such as linking it to a file, which I then write data too and the program then reads. However I want this data to be inputted strictly through the terminal.
To elaborate: There is an Operating System process which is perpetually running in the background, however I can pass data to it to alter its function by running a command such as: program_name -newdata
, and I am trying to program the same functionality into one of my own scripts.
Thanks in advance.
You can use message passing by using unix sockets. You can do it in one executable file, but for simplicity I do it in 2 separate.
In the program_name_background
file you can kick of a UNIXServer that is listening for unix sockets and parsing messages (and run whatever you need in a different thread):
#!/usr/bin/ruby
require 'socket'
require 'json'
require 'FileUtils'
socket_path = "/tmp/program_name_background.sock"
at_exit { FileUtils.rm socket_path }
server = UNIXServer.new socket_path
loop do
client = server.accept
message = client.read
json_message = JSON.parse message, symbolize_names: true
p json_message
break if json_message[:type] == "SIGTERM"
end
In the program_name_control
file you can read attributes from the command line and send message to the background process:
#!/usr/bin/ruby
require 'socket'
require 'json'
case ARGV[0]
when "-newdata"
message = {
type: :newdata,
data: ARGV[1]
}
when "stop"
message = { type: :SIGTERM }
else
p "Error: unknown param: #{ARGV[0]}"
exit
end
client = UNIXSocket.open "/tmp/program_name_background.sock"
client.print JSON.generate(message)
client.close
For parsing options you can use the built-in OptionParser
You can test it like:
./program_name_background
./program_name_control -newdata 118
You can also set up symlinks to those files from the /usr/local/bin
folder so you can call them from anywhere without the leading ./
You can daemonizing the background process so it wont be attached to the terminal.