My system is Ubuntu 14, im running several game servers in screens on it, the session where the game servers are running is "alle_server", my screens are "server0", "server1" until "server9"
i have a script that should check if there is a process "server#" while # is the server-number:
#!/usr/bin/env ruby
require 'open3'
while true
x = Array.new(1)
x = Open3.capture3('ps -aux |grep "scripts/server." | grep "[0-9]$" -o')
for i in 0..10
if !(x[0].include? i.to_s)
p i
`screen -S alle_server -X screen -L /home/u220324/cod2/scripts/server#{i}`
end
end
sleep(60)
end
Ok, I know its dumb to create that array, still it shouldnt do some weird stuff.... when I run this script in a screen session (even when I don't attach it to the "alle_server" screen, sooner or later ALL screensessions disappear at the same moment), but at this moment all servers from 0 to 9 are online and not down
Is it because i try to start that server10 script which doesn't exist?
ps: I had to use that code snippet because the backticks in the code where messing it up
Related
To learn about BASH scripting, I set myself the objective to write a Cron script which shuts down a PC with Mint 20 when activity on the Ethernet interface dropped below a threshold over an 1 hour.
I mainly (but not exclusively) use the PC as File/DLNA Server. The script works, but now I find that it also shuts down the PC the rare times I'm using the the front end. So I want my script to verify if the screen has been blanked (As per Power Management settings)
To test the principle I included this in my script:
screenon=$(/usr/bin/xset -q | grep 'Monitor is' | cut -d "s" -f 2)}
which when run in a terminal window gives (debug: set -x)
screenon= On
but when run from cron gives. (logger)
/usr/bin/xset: unable to open display ""
I have learned about similar problems, but cannot figure out how to solve this.
My script includes:PATH=$PATH:/usr/local/bin
and my PATH is: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
Thanks in advance for any help.
I am trying to write the output of top to a file every 5 seconds which I also got to work.
cmd = "top -s 5 -pid 123 >> top.txt"
p = IO.popen(cmd)
However, the problem I have is that I can't find a way of closing top
I have tried
Process.kill('KILL', p.pid)
but top keeps writing to the output file.
p.close hangs but if I ctrl + c it does seem to exit the top command as well. But this as this requires me to manually ctrl + c it is not a viable solution.
Any help would be appreciated!
The problem is the redirection. >> is a feature of a shell: it starts the process and connects its stdout to the given file. In order for Ruby to do this, it actually starts a shell, which starts top and sets up the redirection.
So p.pid is the PID of the shell, not top. When you kill it, it kills only the shell and top gets disowned, continuing to run under PID 1.
I recommend using Popen3 instead and running just top -s 5 -pid 123 without redirection. This gives you the subprocess as well as its stdout/stderr, so you can manage the output yourself (such as appending it to a file) while being able to kill it.
Alternatively, make a wrapper shell script that runs top with redirection and set it up to kill top when it exits: How do I terminate all the subshell processes? Then have Ruby run that wrapper script.
I am trying to monitor the progress of copying a raspberry-pi OS image to a microSD card. This is similar to Kill a process called using open3 in ruby, except I'm not killing the process, I'm sending it a command for it to issue a progress message.
rpath = device_path.gsub(/disk/, "rdisk")
puts "\n\nCopying image to #{rpath}"
if false
stdout_err, status = Open3.capture2e( "sudo", "dd", "bs=1m", "if=#{source_path}", "of=#{rpath}" )
puts stdout_err
else
cmd = "sudo dd bs=1m if=#{source_path} of=#{rpath}"
Open3.popen2e(cmd) do |stdin, stdout_err, wait_thr|
Thread.new do
stdout_err.each {|l| puts l}
end
Thread.new do
while true
sleep 5
if true
Process.kill("INFO", wait_thr.pid) #Tried INFO, SIGINFO, USR1, SIGUSR1
# all give: `kill': Operation not permitted (Errno::EPERM)
else
stdin.puts 20.chr #Should send ^T -- has no effect, nothing to terminal during flash
end
end
end
wait_thr.value
end
The first section (after 'if false') flashes the image using Open3.capture2e. This works, but of course issues no progress information.
The section after the 'else' flashes the image using Open3.popen2e. It also attempts to display progress by either issuing 'Process.kill("INFO", wait_thr.pid)', or by sending ^T (20.chr) to the stdin stream every 5 seconds.
The Process.kill line generates an "Operation not permitted" error. The stdin.puts line has no effect at all.
One other thing... While the popen2e process is flashing, hitting ctrl-T on the keyboard DOES generate a progress response. I just can't get it to do it programmatically.
Any help is appreciated!
Newer versions of dd have an optional progress bar, as seen here. Even so I think you'll want to rethink how you execute that shell command so that it thinks it's attached to a terminal. Easiest thing to do is fork/exec, like:
cmd = "sudo dd bs=1m if=#{source_path} of=#{rpath} status=progress"
fork do
exec(cmd) # this replaces the forked process with the cmd, giving it direct access to your terminal
end
Process.wait() # waits for the child process to exit
If that's not an option you may want to look into other ways of getting unbuffered output, including just writing a bash script instead of a ruby one.
This hopefully should be an easy question to answer. I am attempting to have mumble-ruby run automatically I have everything up and running except after running this simple script it runs but ends. In short:
Running this from terminal I get "Press enter to terminate script" and it works.
Running this via a cronjob runs the script but ends it and runs cli.disconnect (I assume).
I want the below script to run automatically via a cronjob at a specified time and not end until the server shuts down.
#!/usr/bin/env ruby
require 'mumble-ruby'
cli = Mumble::Client.new('IP Address', Port, 'MusicBot', 'Password')
cli.connect
sleep(1)
cli.join_channel(5)
stream = cli.stream_raw_audio('/tmp/mumble.fifo')
stream.volume = 2.7
print 'Press enter to terminate script';
gets
cli.disconnect
Assuming you are on a Unix/Linux system, you can run it in a screen session. (This is a Unix command, not a scripting function.)
If you don't know what screen is, it's basically a "detachable" terminal session. You can open a screen session, run this script, and then detach from that screen session. That detached session will stay alive even after you log off, leaving your script running. (You can re-attach to that screen session later if you want to shut it down manually.)
screen is pretty neat, and every developer on Unix/Linux should be aware of it.
How to do this without reading any docs:
open a terminal session on the server that will run the script
run screen - you will now be in a new shell prompt in a new screen session
run your script
type ctrl-a then d (without ctrl; the "d" is for "detach") to detach from the screen (but still leave it running)
Now you're back in your first shell. Your script is still alive in your screen session. You can disconnect and the screen session will keep on trucking.
Do you want to get back into that screen and shut the app down manually? Easy! Run screen -r (for "reattach"). To kill the screen session, just reattach and exit the shell.
You can have multiple screen sessions running concurrently, too. (If there is more than one screen running, you'll need to provide an argument to screen -r.)
Check out some screen docs!
Here's a screen howto. Search "gnu screen howto" for many more.
Lots of ways to skin this cat... :)
My thought was to take your script (call it foo) and remove the last 3 lines. In your /etc/rc.d/rc.local file (NOTE: this applies to Ubuntu and Fedora, not sure what you're running - but it has something similar) you'd add nohup /path_to_foo/foo 2>&1 > /dev/null& to the end of the file so that it runs in the background. You can also run that command right at a terminal if you just want to run it and have it running. You have to make sure that foo is made executable with chmod +x /path_to_foo/foo.
Use an infinite loop. Try:
while running do
sleep(3600)
end
You can use exit to terminate when you need to. This will run the loop once an hour so it doesnt eat up processing time. An infinite loop before your disconnect method will prevent it from being called until the server shuts down.
I have a Ruby script that I need to have running all the time in my Linux box. I tried nohup ruby ruby.rb& but it seems it doesn't work.
How can I have the script running in background?
Have a look at screen which is a command-line utility. Start it with
screen
You will get a new shell which is detached. Start your script there with
ruby whatever.rb
And watch it run. Then hit Ctrl-A Ctrl-D and you should be back at your original shell. You can leave the ssh session now, and the script will continue running. At a later time, login to your box and type
screen -r
and you should be back to the detached shell.
If you use screen more than once, you will have to select the screen session by pid which is not so comfortable. To simplify, you can do
screen -S worker
to start the session and
screen -r worker
to resume it.
Depending on your needs:
fork do
Process.setsid
sleep 5
puts "In daemon"
end
puts "In control script"
In real life you will have to reopen STDOUT/STDERR.