How to wait for a system command to execute using ruby script - ruby

I have used system method to run a bat file, the bat file opens and run successfully but my execution wont stop until my bat file has completed its execution
I tried several method like system, exec but nothing is working as I expected. I am new to ruby. I want to be able to stop my execution until my bat file has completed its execution.
Code:
system('path/to/file.bat')

From what I know system is using a subshell and waits for the called command to be fully executed to continue execution of the caller script.
I just executed the following code locally:
require 'time'
puts Time.now; system('sleep 5'); puts Time.now
# result:
# 2023-02-03 11:44:19 +0100
# 2023-02-03 11:44:24 +0100
And as you can see there is 5 seconds between the first Time.now call and the second one, so the calling process waited fo the system to finish the execution before printing the time again.
Maybe the behavior is different on windows. Would you mind to try locally and share the result ?

Related

Ruby running two scripts with mulithreading

So I'm trying to have my ruby (no rails) application be run with a single call from the terminal i.e. 'ruby run.rb'. However I have two scripts that need to be run, app.rb and app2.rb, the issue is, both these scripts don't finish - they keep on being run so as to keep the system running, this means that one of the scripts never gets run - it calls the first script (app.rb) and never the second (app2.rb) these scripts need to be run concurrently!
It does work when I open another command line and just run one script in each however.
I have tried:
def runApp
system("ruby app.rb")
end
def runApp2
system("ruby app2.rb")
end
t1 = Thread.new{runApp()}
t2 = Thread.new{runApp2()}
t1.join
t2.join
However this will only run the first thread (the one running app.rb) because this is being constantly run. Any ideas how it can also run the second thread concurrently?
:EDIT: One of the scripts is using the Sinatra gem, the other also calls one of its functions every ten seconds.
So one possible solution I've found is
system("ruby app.rb & ruby app2.rb")
This only works however if running from linux I think however so I would still appreciate any further solutions.
According to the documentation you can do it like this:
threads = []
threads << Thread.new{runApp()}
threads << Thread.new{runApp2()}
threads.each { |thr| thr.join }
I guess this works because each is parallel.

When running a ruby script via nohup, why doesn't puts write to nohup.out

I'm trying to run a ruby script with nohup:
nohup ruby script.rb &
This takes hours to run, but logs its progress via puts.
Usually, I can look at nohup.out to view the recent output of anything I run with nohup. However, my ruby script doesn't seem to output anything until it finishes, or is killed.
What am I doing wrong?
I'm not familiar with running commands through nohup, but approaching this from a "I'm outputting content to a file and it's only being written after the script exits" type of problem, those are caused by the output being buffered.
So it's very likely that being run through nohup (and thus redirecting the puts output to nohup.out) you lost synchronization. You might need to flush occasionally or enable sync. Since puts is "equivalent to $stdout.puts":
$stdout.flush # run this, occasionally
# or just
$stdout.sync = true

Start a process and keep it running after the ruby script exits

I'm trying to write a ruby script that:
Run a command/script
Stores the command's process pid in a file so I can check if it's still running later, and
the command should keep running after the ruby code exits.
I'm successful in steps 1 and 2, but it looks like the started script (i.e, the child process) terminates once the ruby code is finished.
This is the last version of what I could think about (super simplified):
pid = fork do
exec "/my/fancy/daemon/style/script"
end
File.open('tmp/process.pid', 'w') { |file| file.write(pid.to_s) }
Can you please tell me what am I doing wrong? The ultimate goal is to keep the other script (i.e, the child process) running after the ruby code exits.
You can "detach" your child process:
Process.detach(pid)
See Process#detach for more info.
If you're running your script on a shell, and if your script is the last interactive process, your virtual terminal may exit and cause your child process to hangup as well. If you consider not sending output to the terminal, you can use Process.daemon before running exec.
See Process#daemon.

Windows 2008 Task Scheduler Return Code and Matlab Script

How do I allow my Matlab script to pass back a return code to the Task Scheduler? I currently have a task that runs "matlab -r myscript". The problem is the Task Scheduler always succeeds immediately after starting, even though myscript takes several minutes to run. So, I don't see how to pass back an error code.
How can I make Task Scheduler wait until the script stops running and then get matlab to pass back a return code?
Use the matlab -wait command line option to have it block until the program is finished.
There appears to be an undocumented argument to quit() to set the exit status - e.g. quit(42) - which then shows up in %ERRORLEVEL%. Since it's undocumented, you might not want to rely on it. Alternatively, have your script write its status to a file and have a wrapper script parse it.

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