I wrote two little tools today, rlog
and errno
.
errno
- Looking up Error Numbers
The fact that this utility doesn't really exist had always bothered me, so I wrote it myself after grepping through /usr/include
looking for ESOMETHING
constants and their numeric definitions.
It works like a little something like this:
$ errno 2
ENOENT 2 No such file or directory
$ errno EAFNOSUPPORT EAGAIN EWOULDBLOCK EINVAL
EAFNOSUPPORT 47 Address family not supported by protocol family
EAGAIN 35 Resource temporarily unavailable
EAGAIN 35 Resource temporarily unavailable
EINVAL 22 Invalid argument
$ errno | grep Bad
EBADF 9 Bad file descriptor
EFAULT 14 Bad address
EPROCUNAVAIL 76 Bad procedure for program
EBADEXEC 85 Bad executable (or shared library)
EBADARCH 86 Bad CPU type in executable
EBADMSG 94 Bad message
This can be quite handy when all you get from a program is the error message (i.e. 'Invalid argument') and you're trying to track down which system call is failing. Most kernels ship with pretty good syscall man pages, and they tend to list all of the possible values of errno
that can result, and why.
For example:
ERRORS
The socket() system call fails if:
[EACCES] Permission to create a socket of the specified
type and/or protocol is denied.
[EAFNOSUPPORT] The specified address family is not supported.
[EMFILE] The per-process descriptor table is full.
[ENFILE] The system file table is full.
[ENOBUFS] Insufficient buffer space is available.
The socket cannot be created until sufficient
resources are freed.
[ENOMEM] Insufficient memory was available to fulfill
the request.
[EPROTONOSUPPORT] The protocol type or the specified protocol is
not supported within this domain.
[EPROTOTYPE] The socket type is not supported by the protocol.
If a new protocol family is defined, the socreate process is free
to return any desired error code. The socket() system call will
pass this error code along (even if it is undefined).
Now, if you get ENOMEM
, and print a message via strerror(3)
, you'll get something like this in your output stream:
Cannot allocate memory
With errno
, you can reverse that process and get back the ENOMEM
constant, with ease:
errno | grep 'Cannot allocate memory'
ENOMEM 12 Cannot allocate memory
Hey, look at that! It's ENOMEM
. Incidentally, on my Macbook, that maps to the numeric error code 12. Neat.
The errno
utility also lets you "preview" the error message a given code will produce, which can be helpful in supporting lots of different platforms.
The code for errno
is over here, on Github
rlog
- Ring Buffer Logging
A ring buffer, or circular buffer is a constant-space data structure that prioritizes newer things over older things. rlog
is a Ring Buffer Logging utility that brings an innovative twist to the collection, retrieval and longterm obligation of debug logging.
Ah, debugging, that glorious panacea of the operations world.
If only I had debugging mode turned on, I bet I could get to the bottom of
this weird problem! But turning it on means restarting the daemon, and I
may not be able to reproduce the problem once that happens!
Oh what's a cloud engineer to do!?
One solution, popular with people who like to pay for lots and lots of storage and then never read the logs, is to just log everything, all the time. They set up centralized syslog, Hadoop, Elastic Search, Cassandra, or even -gasp- MongoDD. After a few weeks, there is so much data to look through, it's pointless to even try!
Rather than do that, I wrote rlog
.
rlog
reads every line from standard input, and datestamps each. It allocates enough space to retain 2048 messages. When the 2049th message is received, the 1st messages is dropped. The 2050th messages pushes out the 2nd message, and so on.
When a client connects to rlog
(usually via 127.0.0.1:1040
), they receive the most recent 2048 messages immediately (hence the datestamps), and then receive future messages as they are received by rlog
itself.
It's like tail -f
, except (a) there is no file and (b) it takes up no disk space.
I'll be using rlog
to provide high-resolution debugging output from live production systems. When I need the diagnostics, I hook up a nc
process to the port. When I don't, it's chewing a (small) constant amount of RAM. Win-win!
rlog
is also over at Github
Little Tools = The Best Tools
They can be sharp. They don't take a lot of time to build. The low time investment makes them more malleable; easier to fix; improve; expand.
Happy Hacking!