How to monitor open file descriptors in Ruby on Rails? - linux

Background:
I had an issue with my Rails server recently where it would stop responding, requiring a bounce to get it back up and running. This issue was due to a controller that does some forking upon receiving a POST, to do some heavy-weight concurrent processing -- server response time kept increasing until the server completely stopped responding. I'm pretty sure I have fixed that issue (DB connections copied upon fork weren't getting closed in child processes), but it would be great to authoritatively test that.
Question:
Is there a way to monitor open file descriptors from inside my Rails app? It's running on Linux, so I've been mucking around with the proc filesystem and the lsof command to observe the open file descriptors; this is messy, because it only gives you a snapshot of the current processes. Ideally I would like to print the open file descriptors in the parent and child processes before, during, and after the processing, to ensure that file descriptors don't stay open past their welcome.

One method to consider (probably the simplest) is using a background worker of some sort, such as with Workling, and making it run lsof in intervals, and getting output using syntax:
`lsof | grep something` # shell command example.
Programs like lsof can really hurt performance if run too frequently. Perhaps every 10s to 30s. Perhaps down to maybe 5s, but that's really pushing it. I'm assuming you have a dedicated server or a beasty virtual machine.
In your background worker, you can store these command results into a variable, or grep it down to what you're really looking for (as demonstrated), and access/manipulate the data as you please.

Related

Is it possible to attach to a running background process with ruby?

I have a nodejs daemon running on my server, I would like to give him some input on stdin and read it stdout from a Rails controller, is it possible with Ruby?
I am looking at Open3 but it seems to give me only the chance to spawn a new process.
I need the keep the nodejs process running because the starting overhead is too high to be called at every request.
In general there is no way to attach to a running process's IO streams unless it was set up to do so initially. It is easy if, for example, the process was set up to read from a pipe: just have Ruby write to that pipe like any other file (this is what the Open3 lib does).
For a daemon usually there are more proper ways to interact with it than hijacking its input with a pipe, though it depends on the particular daemon you are running and how it is being managed by the OS. For example, sockets are a popular way to communicate to a running process on *nix systems.

Shorting the time between process crash and shooting server in the head?

I have a routine that crashes linux and force a reboot using a system function.
Now I have the problem that I need to crash linux when a certain process dies. Using a script starting the process and if the script ends restart the server is not appropriate since it takes some ms.
Another idea is spawning the shooting processes alongside and use polling of a counter and if the counter is not incremented reboot the server would be another idea.
This would result in an almost instant reaction.
Now the question is what would be a good timeframe. I have no idea how the scheduler of linux would guarantee a certain update of any such counter and what a good timeout would be.
Also I would like to hear some alternatives to this second process spawning. Is there a possibility to advice linux to run a certain routine in case of a crash of the given process or a listener meachanism for the even of problems with a given process?
The timeout idea is already implemented in the kernel. You can register any application as a software watchdog, but you'll have to lower the default timeout. Have a look at http://linux.die.net/man/8/watchdog for some ideas. That application can also handle user-defined tests. Realistically unless you're trying to run kernel like linux-rt, having timeouts lower than 100ms can be dangerous on a system with heavy load - especially if the check needs to poll another application.
In cases of application crashes, you can handle them if your init supports notifications. For example both upstart and systemd can do that by monitoring files (make sure coredumps are created in the right place).
But in any case, I'd suggest rethinking the idea of millisecond-resolution restarts. Do you really need to kill the system in that time, or do you just need to isolate it? Just syncing the disks will take a few extra milliseconds and you probably don't want to miss that step. Instead of just killing the host, you could make sure the affected app isn't working (SIGABRT?) and kill all networking (flush iptables, change default to DROP).

Network map/mon tool clogs up telnet daemon / login processes

We have an embedded Linux (Kernel 2.6.x / Busybox) system (IP camera/web server) which is being tripped over by a network mapping/monitoring tool (specifically The Dude but I think the problem is a general one) repeatedly probing the Telnet port.
The sequence of events is this:
The tool probes port 23
Our system's Telnet daemon (busybox telnetd) spawns a new /bin/login thread
The tool, having satisfied itself there's something there, skips merrily on its way (it neither logs in nor closes the connection)
This keeps happening (every N seconds) until there are so many sockets open that our system can no longer serve a web page through lack of sockets, and there are hundreds of bin/login processes hanging around.
Apologies for vagueness, full logs & wireshark captures are on a different PC at this moment.
As I see it, we need to do a couple of things:
Put some sort of timeout on the telnet client / bin/login process if no login attempt is made
Put some sort of limit on the number of ports the telnet client can have open at any time
Kill off hanging / zombie sockets (TCP timeout / keepalive config?)
I'm not 100% clear on the correct approach to these three, given that the device is also serving web pages and streaming video so changes to system globals may impact the other services. I was a little surprised that Busybox seems to be open to what's effectively the world's slowest DDOS attack.
Edit:
I've worked out what I think is a reasonable way round this, a new question started for ironing out the wrinkles in that idea. Basically, login exits as soon as someone logs in, so we can kill logins with (relative) impunity when a new instance is launched.
The tool, having satisfied itself there's something there, skips merrily on its way (it neither logs in nor closes the connection)
That is an issue and in fact a type of DOS attack.
This keeps happening (every N seconds) until there are so many sockets open that our system can no longer serve a web page through lack of sockets, and there are hundreds of bin/login processes hanging around.
Apart from stopping the DOS attack you might want to mitigate it using some tools. In this specific case you might want to configure low TCP timeouts and thus get the sockets closed soon after they are open due to inactivity on the other end and thus the login processes should be terminated as well.
Well, let me answer my own question by linking to myself answering my own question on killing zombie logins each time a new one is spawned.
The solution is forcing telnetd to run a script instead of /bin/login, where the script kills any other instances of /bin/login before running a new one. Not ideal but hopefully solving the problem.

Maintaining a long-running task on Linux

My system includes a task which opens a network socket, receives pushed data from the network, processes it, and writes it out to disk or pings other machines depending on the messages. This task is intended to run forever, and the service is designed to have this task always running. But sometimes it crashes.
What's the best practice for keeping a task like this alive? Assume it's okay for the task to be dead for up to 30 seconds before we restart it.
Some obvious ideas include having a watchdog process that checks to make sure the process is still running. Watchdog could be triggered by cron. But how does it know if the process is alive or not? Write a pidfile? touch a heartbeat file? An ideal solution wouldn't continuously spin up more processes if the machine gets bogged down to the point where the watchdog is running faster than the heartbeat.
Are there standard linux tools for this? I can imagine a solution that uses a message queue, but I'm not sure if that's a good idea or not.
Depending on the nature of the task that you wish to monitor, one method is to write a simple wrapper to start up your task in a fork().
The wrapper task can then do a waitpid() on the child and restart it if it is terminated.
This does depend on modifying the source for the task that you wish to run.
sysvinit will restart processes that die, if added to inittab.
If you're worried about the process freezing without crashing and ending the process, you can use a heartbeat and hard kill the active instance, letting init restart it.
You could use monit along with daemonize. There are lots of tools for this in the *nix world.
Supervisor was designed precisely for this task. From the project website:
Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems.
It runs as a daemon (supervisord) controlled by a command line tool, supervisorctl. The configuration file contains a list of programs it is supposed to monitor, among other settings.
The number of options is quite extensive, -- have a look at the docs for a complete list. In your case, the relevant configuration section might be something like this:
[program:my-network-task]
command=/bin/my-network-task # where your binary lives
autostart=true # start when supervisor starts?
autorestart=true # restart automatically when stopped?
startsecs=10 # consider start successful after how many secs?
startretries=3 # try starting how many times?
I have used Supervisor myself and it worked really well once everything was set up. It requires Python, which should not be a big deal in most environments but might be.

Debugging utilities for Linux process hang issues?

I have a daemon process which does the configuration management. all the other processes should interact with this daemon for their functioning. But when I execute a large action, after few hours the daemon process is unresponsive for 2 to 3 hours. And After 2- 3 hours it is working normally.
Debugging utilities for Linux process hang issues?
How to get at what point the linux process hangs?
strace can show the last system calls and their result
lsof can show open files
the system log can be very effective when log messages are written to track progress. Allows to box the problem in smaller areas. Also correlate log messages to other messages from other systems, this often turns up interesting results
wireshark if the apps use sockets to make the wire chatter visible.
ps ax + top can show if your app is in a busy loop, i.e. running all the time, sleeping or blocked in IO, consuming CPU, using memory.
Each of these may give a little bit of information which together build up a picture of the issue.
When using gdb, it might be useful to trigger a core dump when the app is blocked. Then you have a static snapshot which you can analyze using post mortem debugging at your leisure. You can have these triggered by a script. The you quickly build up a set of snapshots which can be used to test your theories.
One option is to use gdb and use the attach command in order to attach to a running process. You will need to load a file containing the symbols of the executable in question (using the file command)
There are a number of different ways to do:
Listening on a UNIX domain socket, to handle status requests. An external application can then inquire as to whether the application is still ok. If it gets no response within some timeout period, then it can be assumed that the application being queried has deadlocked or is dead.
Periodically touching a file with a preselected path. An external application can look a the timestamp for the file, and if it is stale, then it can assume that the appliation is dead or deadlocked.
You can use the alarm syscall repeatedly, having the signal terminate the process (use sigaction accordingly). As long as you keep calling alarm (i.e. as long as your program is running) it will keep running. Once you don't, the signal will fire.
You can seamlessly restart your process as it dies with fork and waitpid as described in this answer. It does not cost any significant resources, since the OS will share the memory pages.

Resources