I'm creating a little script that will send 10 jobs to a printer. I'm trying to loop one of my methods using a times loop except when I run the program, it won't loop, it just send one job..
Example:
[<user>#<server> ruby]$ ruby clean_printer laser32
request id is laser32-1038115 (1 file(s))
[<user>#<server> ruby]$
Am I doing something wrong to where this won't loop..?
Source:
#!/usr/local/bin/ruby
class CleanPrinter
attr_accessor :printer
def initialize(printer)
#printer = printer
end
def create_jobs
exec("lp -d #{#printer} test.txt")
end
def loop
10.times do
create_jobs
end
end
end
test = CleanPrinter.new(ARGV[0])
test.loop
Yes it's a class, yes I will take it out of the class.
Note that exec() actually replaces the current process image, thereby effectively exiting your program on the first iteration. You might want to switch to using system() instead.
Related
I have some code the executes every n minutes and updates some values. I check those values with conditionals and if needed, I call a loop that makes an LED blink. That loop function looks like:
def blink_led_constant
while 1
# RPi::GPIO.set_high 18
# sleep(1)
# RPi::GPIO.set_low 18
# sleep(1)
end
end
Basically I want this LED to blink in the background until a certain condition is met. How do I set this to function to run, but also continue past the function call to reiterate my program?
Right now based on how I wrote this, if this function is called it gets stuck infinitely.
Thanks
You can use a thread to do this.
def blink_led_constant
loop do
# RPi::GPIO.set_high 18
# sleep(1)
# RPi::GPIO.set_low 18
# sleep(1)
end
end
thread = Thread.new { blink_led_constant }
Then you can execute other commands while blink_led_constant runs in the background. Change the loop do to a while if you want it to break once a condition is met. Once the condition is met to stop the led from blinking call Thread.kill(thread) or thread.kill.
I have an unstoppable Ruby script that I need to be able to stop. Here is the following code:
require 'win32ole'
wsh = WIN32OLE.new("WScript.Shell")
def fileToArray(file)
x = []
File.foreach("#{file}") do |line|
x << line.to_s.split('')
end
return x.flatten!
end
tests = fileToArray("C:\\xampp\\htdocs\\x\\Script\\includes\\classes.php")
sleep 10
x = 0
y = tests.length
while x <= y do
send = tests[x]
speed = 0.025
if x == y
print "Test Complete"
break()
#You guys don't need to see this code, it's just detecting what keys are
#in the array and reading them to the file. But important to know that it is incrementing based on sent keys
else
x += 1
end
end
My problem is that the classes.php it is reading from is 4,000 lines long and takes a long time to get through. If it messes up, I have to wait until it is finished. There is no way for me to stop this loop from running until it is finished unless I completely log out from everything, CTRL+ALT+DEL Option: Logout. I've tried curses I've tried gets on exit. CTRL^C doesn't work either. I'd much rather have a written in solution, but otherwise I wouldn't mind knowing a few keys to killswitch the process a.k.a. "Kill it, kill it with keys"
You read each byte in an array, how long does your array get if you let in run till the end ? Filling an array of hundreds of thousands takes a long time indeed. Should see the rest of your code to decide if there is no better way, and why the win32ole object ?
If the standard windows keys to interrupt the jog don't word (Ctrl-c or Ctrl-break) and you can't use taskmanager, surely the console will still be responsive.
Here a script that does what you do. I put it in an endless loop so that I have to terminate it. The Process.pid shows the process id.
In advance you open a console and when you want to terminate the script you enter the following
taskkill /f /pid 5532
The /f is for forcing to terminate, the number is the pid you get from your script
# encoding:utf-8
STDOUT.sync = true
s1 = File.read __FILE__
puts Process.pid
class String
def to_a
while true # endless loop just for testing the kill
each_byte.inject([]){|result, char| result << char}
end
end
end
p s1.to_a
Tested with Windows 7 and Ruby MRI 1.9.3
EDIT:
based on your comment here another way to send keys to a program
If I understand correctly what you want to do you also don't need to split the string in advance.
require 'win32ole'
#for this script Autoit3 must be installed
s1 = "a string of thousands of characters"
# activate the correct window with the appclass
ai.Opt("WinTitleMatchMode", 4)
appClass = "[CLASS:xxxxxxxx]" # retrieved with AutoIt Window Info
ai = WIN32OLE.new("AutoItX3.Control")
ai.WinActivate(appClass)
# or with the handle
handle = "[HANDLE:#{ai.wingethandle(appClass)}]"
ai.WinActivate(handle)
# send keys, controlkeys or words to the program
ai.Send('{HOME}') #you can send control keys like that
s1.each_byte{|char| ai.Send(char); sleep 1} #to send everything char after char
s1[0..10].each_byte{|char| ai.Send(char); sleep 1} #to send the first 10 chars
I'm have a multithreaded program that prints to the console in hundreds of places. Unfortunately, instead of
Line 2
Line 1
Line 3
I get
Line2Line1
Line3
I am trying to make puts thread safe.
In Python (which I don't think has this problem, but suppose it did), I'd do
old_print = print
print_mutex = threading.Lock()
def print(*args, **kwargs):
print_mutex.acquire()
try:
old_print(*args, **kwargs)
finally:
print_mutex.release()
I'm trying this in Ruby,
old_puts = puts
puts_mutex = Mutex.new
def puts(*args)
puts_mutex.synchronize {
old_puts(*args)
}
But this doesn't work: "undefined method old_puts"
How can I make thread-safe (i.e. not print partial lines)?
alias old_puts puts
or more modern way:
module MyKernel
PutsMutex = Mutex.new
def puts(*)
PutsMutex.synchronize{super}
end
end
module Kernel
prepend MyKernel
end
The reason for this behaviour is that puts internally calls the underlying write function twice - one for the actual value to be written, and one for the newline to be written. (Explained in Ruby's puts is not atomic)
Here's a hack to make puts call write exactly once: Append \n to the string you're writing. Here's what this looks like in my code:
# Threadsafe `puts` that outputs text and newline atomically
def safe_puts(msg)
puts msg + "\n"
end
puts internally checks whether the object being written has a newline at the end, and only calls write again if that isn't true. Since we've changed the input to end with a newline, puts ends up making only one call to write.
I'm finding this a bit odd. I would expect each iteration of parse_line(ARGF.read_line) here to wait for input from STDIN. What actually is happening is the first iteration skips waiting for user input, but subsequent iterations do wait. My temporary workaround is just to iterate an extra time.
def parse_line(line)
line.split(" ").map(&:to_i)
end
def get_number_of_slices
parse_line(ARGF.readline(1)).first
end
def get_all_slice_dimensions(number_of_slices)
number_of_slices += 1 # for some reason the first read doesn't wait for user input...
number_of_slices.times.collect { puts "iter"; parse_line(ARGF.readline) }
end
def main
puts (get_all_slice_dimensions get_number_of_slices)
end
main
Added code so that it is a full working program. I found that when I changed readline(1) to readline in get_number_of_slices, I did not need to add 1 to number_of_slices in get_all_slice_dimensions any longer, but I would still like to know the reason why this affects the behavior. If you pay attention to the output, iter will print twice the first time.
I'm trying to figure out if I can get the time it takes for a method to execute using TracePoint in ruby 2.0. Any help is appreciated.
Update
I want to clarify this question. My goal is to get the time it takes for all methods to execute even if you don't know what those methods will be. I've found this to be quite tricky. Deivid's response below involves setting a t0 and t1 variables in a shared context, then setting the time values on call and return. While this works for a simple example, it becomes unmanageable when trying to log the time of all method calls in a more complex ruby program. Take for example the following program:
class C
def self.slow
C.fast
sleep 3
end
def self.fast
end
end
C.slow
In this program, it is only possible to monitor t0 and t1 times if you keep track of the method names being called. In an even more complex program such as a Rails app with many stack frames where you do not know in advance all of the methods that will be executed, it is not as obvious as to the best way to monitor and print all call and return times.
The solution 'may' involve keeping a hash of call times where the key is some combination of the Thread.current.object_id and the tp.method_id.. I have not found the correct key though that is unique enough to ensure that the return time can be matched to the caller, considering you may have recursive method calls that create non-standard call and return situations.
class C
def self.slow n
return C.fast if n == 0
sleep 1
slow n-1
end
def self.fast
end
end
#times = {}
traceCall = TracePoint.new(:call, :return) do |tp|
key = "#{tp.defined_class}_#{tp.method_id}_#{caller(0).size}"
if tp.event == :call
#times[key] = Time.now
else
#times[key] = Time.now - #times[key]
end
end.enable do
C.slow 3
end
p #times